@cc-monitoring/proxy-core 0.2.3 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. package/dist/docs/404.html +1 -1
  2. package/dist/docs/assets/{app.6_CicOIJ.js → app.B9A39uFv.js} +1 -1
  3. package/dist/docs/assets/chunks/@localSearchIndexroot.B6Qfxe6W.js +1 -0
  4. package/dist/docs/assets/chunks/{VPLocalSearchBox.ZMWZsg8z.js → VPLocalSearchBox.DdhC696L.js} +1 -1
  5. package/dist/docs/assets/chunks/{theme.BkvhsjzH.js → theme.CfB2tOFi.js} +2 -2
  6. package/dist/docs/index.html +2 -2
  7. package/dist/docs/overview.html +2 -2
  8. package/dist/docs/packages-utils.html +2 -2
  9. package/dist/docs/proxy-admin/env-and-build.html +2 -2
  10. package/dist/docs/proxy-admin/index.html +2 -2
  11. package/dist/docs/proxy-admin/layout-and-menu.html +2 -2
  12. package/dist/docs/proxy-admin/pages.html +2 -2
  13. package/dist/docs/proxy-admin/routing-and-auth.html +2 -2
  14. package/dist/docs/proxy-admin/services-and-mock.html +2 -2
  15. package/dist/docs/proxy-cli/api-layer.html +2 -2
  16. package/dist/docs/proxy-cli/app-shell.html +2 -2
  17. package/dist/docs/proxy-cli/components-common.html +2 -2
  18. package/dist/docs/proxy-cli/components-config.html +2 -2
  19. package/dist/docs/proxy-cli/components-requests.html +2 -2
  20. package/dist/docs/proxy-cli/components-stats.html +2 -2
  21. package/dist/docs/proxy-cli/components-status.html +2 -2
  22. package/dist/docs/proxy-cli/data-hooks.html +2 -2
  23. package/dist/docs/proxy-cli/index.html +2 -2
  24. package/dist/docs/proxy-cli/utils-and-i18n.html +2 -2
  25. package/dist/docs/proxy-core/chat-api.html +2 -2
  26. package/dist/docs/proxy-core/cli.html +2 -2
  27. package/dist/docs/proxy-core/config.html +2 -2
  28. package/dist/docs/proxy-core/data-layer.html +2 -2
  29. package/dist/docs/proxy-core/entry.html +2 -2
  30. package/dist/docs/proxy-core/index.html +2 -2
  31. package/dist/docs/proxy-core/pm2.html +2 -2
  32. package/dist/docs/proxy-core/providers.html +2 -2
  33. package/dist/docs/proxy-core/proxy.html +2 -2
  34. package/dist/docs/proxy-core/stats.html +2 -2
  35. package/dist/docs/proxy-core/tool.html +2 -2
  36. package/dist/docs/proxy-core/ui-routes.html +2 -2
  37. package/dist/docs/proxy-core/utilities.html +2 -2
  38. package/dist/docs/quickstart.html +2 -2
  39. package/dist/docs/request-flow.html +2 -2
  40. package/dist/mcp-server/index.js +5 -3
  41. package/dist/mcp-server/tools.js +24 -2
  42. package/dist/server/__tests__/server.test.js +9 -1
  43. package/dist/server/__tests__/ui-route.test.js +8 -0
  44. package/dist/server/chat-route.js +6 -0
  45. package/dist/server/proxy.js +5 -0
  46. package/dist/server/ui-route.js +113 -7
  47. package/dist/ui/assets/{1c-HTPXddJd.js → 1c-DAu68mP4.js} +1 -1
  48. package/dist/ui/assets/{abnf-bINSkl_m.js → abnf-Cu8RHCHK.js} +1 -1
  49. package/dist/ui/assets/{abnfDiagram-VRR7QNED-ClDzCbvw.js → abnfDiagram-VRR7QNED-BUBToPXF.js} +1 -1
  50. package/dist/ui/assets/{accesslog-BAnIWzpe.js → accesslog-BG-34XOy.js} +1 -1
  51. package/dist/ui/assets/{actionscript-DVcm6F_C.js → actionscript-iw0HHMGM.js} +1 -1
  52. package/dist/ui/assets/{ada-Cxn-QX4j.js → ada-qRqj6VGQ.js} +1 -1
  53. package/dist/ui/assets/{angelscript-BAwAPvBQ.js → angelscript-BeaXyx_P.js} +1 -1
  54. package/dist/ui/assets/{apache-CjjovgUx.js → apache-CU8d-z9X.js} +1 -1
  55. package/dist/ui/assets/{applescript-VUcyXoVh.js → applescript-d1Wxkqz1.js} +1 -1
  56. package/dist/ui/assets/{arc-3Nou_aku.js → arc-BMsPIm3j.js} +1 -1
  57. package/dist/ui/assets/{arcade-Dz2VAk7O.js → arcade-CtbgrWTM.js} +1 -1
  58. package/dist/ui/assets/{architectureDiagram-ZJ3FMSHR-DhwSsCdN.js → architectureDiagram-ZJ3FMSHR-CVjC5TrS.js} +1 -1
  59. package/dist/ui/assets/{arduino-B-Ptb1K1.js → arduino-Bc9L39Hr.js} +1 -1
  60. package/dist/ui/assets/{armasm-DU_6qZlW.js → armasm-DuWmpjWR.js} +1 -1
  61. package/dist/ui/assets/{asciidoc-DYbYiWKT.js → asciidoc-CDIhFTnx.js} +1 -1
  62. package/dist/ui/assets/{aspectj-CmdNkqAs.js → aspectj-SYj-57Es.js} +1 -1
  63. package/dist/ui/assets/{autohotkey-if9QUvYo.js → autohotkey-hBi5dq37.js} +1 -1
  64. package/dist/ui/assets/{autoit-DGU3G1s6.js → autoit-BSawXzhg.js} +1 -1
  65. package/dist/ui/assets/{avrasm-1zsEtPJ6.js → avrasm-CwYom8Np.js} +1 -1
  66. package/dist/ui/assets/{awk-CvmeshSq.js → awk-BvBRfGo2.js} +1 -1
  67. package/dist/ui/assets/{axapta-CbJGb5cN.js → axapta-CqUavA8k.js} +1 -1
  68. package/dist/ui/assets/{bash-CFXg_i2e.js → bash-BS_ZnmEu.js} +1 -1
  69. package/dist/ui/assets/{basic-6atic5cT.js → basic-xbP4IXrN.js} +1 -1
  70. package/dist/ui/assets/{blockDiagram-677ZJIJ3-BKXinDkB.js → blockDiagram-677ZJIJ3-CmpI3f5p.js} +1 -1
  71. package/dist/ui/assets/{bnf-DydAtPHV.js → bnf-BECwu6uW.js} +1 -1
  72. package/dist/ui/assets/{brainfuck-CnHx1vO0.js → brainfuck-QQgu4j4N.js} +1 -1
  73. package/dist/ui/assets/{coq-BShzwzh7.js → c-BRJEPYra.js} +1 -1
  74. package/dist/ui/assets/{c-like-XpQV9S6j.js → c-like-DYrFOtXy.js} +1 -1
  75. package/dist/ui/assets/{c4Diagram-LMCZKHZV-D5EmWl5d.js → c4Diagram-LMCZKHZV-B6Hgngz9.js} +1 -1
  76. package/dist/ui/assets/{cal-D-orUuBW.js → cal-CNMrJ6v5.js} +1 -1
  77. package/dist/ui/assets/{capnproto-TdI6NT8O.js → capnproto-DYCKl6oY.js} +1 -1
  78. package/dist/ui/assets/{ceylon-Dji8eqtG.js → ceylon-mb8tRPl0.js} +1 -1
  79. package/dist/ui/assets/channel-Bc4Td8eZ.js +1 -0
  80. package/dist/ui/assets/{chunk-2Q5K7J3B-CaIvwVWl.js → chunk-2Q5K7J3B-LxvQ-G67.js} +1 -1
  81. package/dist/ui/assets/{chunk-32BRIVSS-C7oMpoeu.js → chunk-32BRIVSS-DxzKK6Aw.js} +1 -1
  82. package/dist/ui/assets/{chunk-5VM5RSS4-BQ0aVGl-.js → chunk-5VM5RSS4-CZEoYJ2W.js} +1 -1
  83. package/dist/ui/assets/{chunk-EX3LRPZG-D-_EqojZ.js → chunk-EX3LRPZG-DS2PytrN.js} +1 -1
  84. package/dist/ui/assets/{chunk-JWPE2WC7-B0OLx2rk.js → chunk-JWPE2WC7-UX0Sr1Ie.js} +1 -1
  85. package/dist/ui/assets/{chunk-MOJQB5TN-Be8IXTUE.js → chunk-MOJQB5TN-YbJgT9t4.js} +1 -1
  86. package/dist/ui/assets/{chunk-RYQCIY6F-DceCW2mS.js → chunk-RYQCIY6F-DS2VH_U9.js} +1 -1
  87. package/dist/ui/assets/{chunk-V7JOEXUC-Cbhq5qgO.js → chunk-V7JOEXUC-CZr0pkI1.js} +1 -1
  88. package/dist/ui/assets/{chunk-VR4S4FIN-D6WJuaS1.js → chunk-VR4S4FIN-50opPAD3.js} +1 -1
  89. package/dist/ui/assets/{chunk-XXDRQBXY-CKrih4pC.js → chunk-XXDRQBXY-DAAX9l7U.js} +1 -1
  90. package/dist/ui/assets/classDiagram-OUVF2IWQ-BicxhZFq.js +1 -0
  91. package/dist/ui/assets/classDiagram-v2-EOCWNBFH-BicxhZFq.js +1 -0
  92. package/dist/ui/assets/{clean-0frlVN_A.js → clean-C4X7dSkh.js} +1 -1
  93. package/dist/ui/assets/{clojure-D0q_yQDf.js → clojure-DSg9gUa7.js} +1 -1
  94. package/dist/ui/assets/{clojure-repl-DgYhEzOe.js → clojure-repl-CagRYx7h.js} +1 -1
  95. package/dist/ui/assets/{cmake-WF5tF5xU.js → cmake-CFdBn53c.js} +1 -1
  96. package/dist/ui/assets/{coffeescript-CyWYgeyv.js → coffeescript-CJZtMOPx.js} +1 -1
  97. package/dist/ui/assets/{c-DarYnPBd.js → coq-IDMIFfem.js} +1 -1
  98. package/dist/ui/assets/{cos-C5i3_TIB.js → cos-Bx2VJuzG.js} +1 -1
  99. package/dist/ui/assets/{cose-bilkent-JH36ORCC-BCwilS6I.js → cose-bilkent-JH36ORCC-zWRLsZpZ.js} +1 -1
  100. package/dist/ui/assets/{cpp-F1mRQFyw.js → cpp-CsG6DlC4.js} +1 -1
  101. package/dist/ui/assets/{crmsh-BAkHUu-B.js → crmsh-DTy9MnmJ.js} +1 -1
  102. package/dist/ui/assets/{crystal-CwUaomfj.js → crystal-BwgrLrZ1.js} +1 -1
  103. package/dist/ui/assets/{csharp-B1gHIdjK.js → csharp-B2VeTPAF.js} +1 -1
  104. package/dist/ui/assets/{csp-CblCTMvV.js → csp-CTpydNhH.js} +1 -1
  105. package/dist/ui/assets/{css-CXg7kJV3.js → css-B0mMUbpY.js} +1 -1
  106. package/dist/ui/assets/{cynefin-VYW2F7L2-BdgMlR5e.js → cynefin-VYW2F7L2-BmjQEj6q.js} +1 -1
  107. package/dist/ui/assets/{cynefinDiagram-TSTJHNR4-Bozdux8p.js → cynefinDiagram-TSTJHNR4-Dr0Zrke0.js} +1 -1
  108. package/dist/ui/assets/{d-Cs5yNCaM.js → d-DjuDZnbI.js} +1 -1
  109. package/dist/ui/assets/{dagre-VKFMJZFB-tI_mjNMn.js → dagre-VKFMJZFB-xoTPT2Uu.js} +1 -1
  110. package/dist/ui/assets/{dart-BqgylVkh.js → dart-xR3GU9TJ.js} +1 -1
  111. package/dist/ui/assets/{delphi-CbnfHpIi.js → delphi-bJas5QnG.js} +1 -1
  112. package/dist/ui/assets/{diagram-FQU43EPY-DmyL3OJT.js → diagram-FQU43EPY-rL_IU7gU.js} +1 -1
  113. package/dist/ui/assets/{diagram-G47NLZAW-BEi9GZlZ.js → diagram-G47NLZAW-EcDiCVGj.js} +1 -1
  114. package/dist/ui/assets/{diagram-NH7WQ7WH-Bct44Oh1.js → diagram-NH7WQ7WH-CGGXOjev.js} +1 -1
  115. package/dist/ui/assets/{diagram-OA4YK3LP-VWAgZxPK.js → diagram-OA4YK3LP-DnE7hDjD.js} +1 -1
  116. package/dist/ui/assets/{diagram-WEI45ONY-CxcHsE6q.js → diagram-WEI45ONY-CTJH5eD8.js} +1 -1
  117. package/dist/ui/assets/{diff-CMJ2hGQW.js → diff-doJFF3fv.js} +1 -1
  118. package/dist/ui/assets/{django-Cq_XIhVZ.js → django-D3b-owa_.js} +1 -1
  119. package/dist/ui/assets/{dns-CJs3z6-E.js → dns-C42KYV-Z.js} +1 -1
  120. package/dist/ui/assets/{dockerfile-ehs0ogry.js → dockerfile-9KUINc2j.js} +1 -1
  121. package/dist/ui/assets/{dos-DXOYESf1.js → dos-CxnlJ6qp.js} +1 -1
  122. package/dist/ui/assets/{dsconfig-Cs2hs3Bl.js → dsconfig-6CMMCwmY.js} +1 -1
  123. package/dist/ui/assets/{dts-Dk8yoweb.js → dts-D78rdUIB.js} +1 -1
  124. package/dist/ui/assets/{dust-BMK9e-Ss.js → dust-Dv1uTfJU.js} +1 -1
  125. package/dist/ui/assets/{ebnf-DlyBI5m6.js → ebnf-BGbG1cFK.js} +1 -1
  126. package/dist/ui/assets/{ebnfDiagram-CCIWWBDH-DBp9JHEq.js → ebnfDiagram-CCIWWBDH-z2VgRSUV.js} +1 -1
  127. package/dist/ui/assets/{elixir-BThlsblT.js → elixir-ZgAQVY1J.js} +1 -1
  128. package/dist/ui/assets/{elm-DrmZwmcc.js → elm-CudiFuNu.js} +1 -1
  129. package/dist/ui/assets/{erDiagram-Q63AITRT-BhK4NKvx.js → erDiagram-Q63AITRT-X1TODuRv.js} +1 -1
  130. package/dist/ui/assets/{erb-BQM7j3K9.js → erb-Bz_NZh6W.js} +1 -1
  131. package/dist/ui/assets/{erlang-CuUaWEXv.js → erlang-DNuj1nb2.js} +1 -1
  132. package/dist/ui/assets/{erlang-repl-DB0uphao.js → erlang-repl-SP1Gan9W.js} +1 -1
  133. package/dist/ui/assets/{excel-DmsuWUss.js → excel-0K77uECF.js} +1 -1
  134. package/dist/ui/assets/{fix-D-Uzxpz_.js → fix-CalJq7JD.js} +1 -1
  135. package/dist/ui/assets/{flix-B_7EHWiA.js → flix-BlIs11_w.js} +1 -1
  136. package/dist/ui/assets/{flowDiagram-23GEKE2U-DtMG1G-h.js → flowDiagram-23GEKE2U-DA2dnmc0.js} +1 -1
  137. package/dist/ui/assets/{fortran-Djp5tH9W.js → fortran-ZCobXY2R.js} +1 -1
  138. package/dist/ui/assets/{fsharp-Pj_2ZEa4.js → fsharp-Be8rwUtc.js} +1 -1
  139. package/dist/ui/assets/{gams-B2i3v2ec.js → gams-DUat8frQ.js} +1 -1
  140. package/dist/ui/assets/{ganttDiagram-NO4QXBWP-C7M-JA0W.js → ganttDiagram-NO4QXBWP-DdFwaIGZ.js} +1 -1
  141. package/dist/ui/assets/{gauss-DaV8sHLU.js → gauss-BB4U88dy.js} +1 -1
  142. package/dist/ui/assets/{gcode-0Jvrh6HY.js → gcode-DzeUZuZg.js} +1 -1
  143. package/dist/ui/assets/{gherkin-DoOl28D6.js → gherkin-B_8vW_BO.js} +1 -1
  144. package/dist/ui/assets/{gitGraphDiagram-IHSO6WYX-D3HB5mow.js → gitGraphDiagram-IHSO6WYX-B-Dn8x6I.js} +1 -1
  145. package/dist/ui/assets/{glsl-DEbk7rH5.js → glsl-DGHGjPC1.js} +1 -1
  146. package/dist/ui/assets/{gml-CBcqXBNV.js → gml-BYEku8Yh.js} +1 -1
  147. package/dist/ui/assets/{go-DqesmqF8.js → go-D8aSgQMc.js} +1 -1
  148. package/dist/ui/assets/{golo-9U1oO0b5.js → golo-CDjCU_jh.js} +1 -1
  149. package/dist/ui/assets/{gradle-DZliBXTY.js → gradle-BeUw7tl_.js} +1 -1
  150. package/dist/ui/assets/{groovy-Dys3GQwv.js → groovy-5iCQOtR3.js} +1 -1
  151. package/dist/ui/assets/{haml-CrtAODl1.js → haml-BEdL8FJi.js} +1 -1
  152. package/dist/ui/assets/{handlebars-CueXuqSj.js → handlebars-BuYQNzoK.js} +1 -1
  153. package/dist/ui/assets/{haskell-CRungOQt.js → haskell-I4FCBcW0.js} +1 -1
  154. package/dist/ui/assets/{haxe-aMz7L4gD.js → haxe-yigyKfFr.js} +1 -1
  155. package/dist/ui/assets/{hsp-Cw75yqGb.js → hsp-ZUk4j7d1.js} +1 -1
  156. package/dist/ui/assets/{htmlbars-e_mpUZNH.js → htmlbars-QYP3lT3u.js} +1 -1
  157. package/dist/ui/assets/{http-Di7E_m1o.js → http-BJpD1O71.js} +1 -1
  158. package/dist/ui/assets/{hy-CwlvsNj6.js → hy-CIJ1bP6S.js} +1 -1
  159. package/dist/ui/assets/{index-BdSumlU0.js → index-BDXWttnT.js} +3 -3
  160. package/dist/ui/assets/index-C0fxlU9d.css +10 -0
  161. package/dist/ui/assets/{index-BVM6YOjH.js → index-COAgrx1J.js} +256 -256
  162. package/dist/ui/assets/{infoDiagram-FWYZ7A6U-_r-6eAzx.js → infoDiagram-FWYZ7A6U-fTg9eLNt.js} +1 -1
  163. package/dist/ui/assets/{inform7-dwg1imm1.js → inform7-DAsu-lC2.js} +1 -1
  164. package/dist/ui/assets/{ini-DEXL1rCA.js → ini-Bhz-zHCg.js} +1 -1
  165. package/dist/ui/assets/{irpf90-Ccs_8Sp-.js → irpf90-BunhbwBl.js} +1 -1
  166. package/dist/ui/assets/{isbl-B9d1nYmL.js → isbl-q9L6hOhP.js} +1 -1
  167. package/dist/ui/assets/{ishikawaDiagram-FXEZZL3T-lNCezpU4.js → ishikawaDiagram-FXEZZL3T-B8G0sdgd.js} +1 -1
  168. package/dist/ui/assets/{java-5fv2smM6.js → java-Iks5Pkau.js} +1 -1
  169. package/dist/ui/assets/{javascript-TAWm0NK8.js → javascript-C4vltXPw.js} +1 -1
  170. package/dist/ui/assets/{jboss-cli-dM1kcsbR.js → jboss-cli-BQBvd2X2.js} +1 -1
  171. package/dist/ui/assets/{journeyDiagram-5HDEW3XC-CBYHux8i.js → journeyDiagram-5HDEW3XC-Crbzgrum.js} +1 -1
  172. package/dist/ui/assets/{json-CtCzm6jF.js → json-DXK0_jUK.js} +1 -1
  173. package/dist/ui/assets/{julia-Co7H3kzk.js → julia-CCYoBiYK.js} +1 -1
  174. package/dist/ui/assets/{julia-repl-BT1ar5VS.js → julia-repl-y8v2Oorl.js} +1 -1
  175. package/dist/ui/assets/{kanban-definition-HUTT4EX6-B8x8eQyo.js → kanban-definition-HUTT4EX6-C8sCOsBX.js} +1 -1
  176. package/dist/ui/assets/{kotlin-W6mVKIj9.js → kotlin-Bnjk7_fw.js} +1 -1
  177. package/dist/ui/assets/{lasso-DJG4luGz.js → lasso-B-al6x63.js} +1 -1
  178. package/dist/ui/assets/{latex-DbBOxO7u.js → latex-BUmqlb9r.js} +1 -1
  179. package/dist/ui/assets/{ldif-CVS189JA.js → ldif-D42RWj6Q.js} +1 -1
  180. package/dist/ui/assets/{leaf-eYNiXTKP.js → leaf-CrH4BZ0m.js} +1 -1
  181. package/dist/ui/assets/{less-DxhvWM95.js → less-upmRlQQW.js} +1 -1
  182. package/dist/ui/assets/{lisp-SC7AwnXC.js → lisp-DHYS22SA.js} +1 -1
  183. package/dist/ui/assets/{livecodeserver-CR2eHihF.js → livecodeserver-CeQNmFP3.js} +1 -1
  184. package/dist/ui/assets/{livescript-DBZ-GaVK.js → livescript-PJWpY1JI.js} +1 -1
  185. package/dist/ui/assets/{llvm-BzURO4tt.js → llvm-BKtKWwCt.js} +1 -1
  186. package/dist/ui/assets/{lsl-DGoJxEUu.js → lsl-RWRLRjk7.js} +1 -1
  187. package/dist/ui/assets/{lua-qgG9gdiw.js → lua-BFUDiPGm.js} +1 -1
  188. package/dist/ui/assets/{makefile-D0kZ6SOe.js → makefile-CUDyOz5D.js} +1 -1
  189. package/dist/ui/assets/{markdown-DRQWgMxk.js → markdown-zZCLypc6.js} +1 -1
  190. package/dist/ui/assets/{mathematica-DIBvZyEZ.js → mathematica-BHbxKxnq.js} +1 -1
  191. package/dist/ui/assets/{matlab-BNg0BR0b.js → matlab-DlGtg--p.js} +1 -1
  192. package/dist/ui/assets/{maxima-Bpga3G1G.js → maxima-BBBeS3Ra.js} +1 -1
  193. package/dist/ui/assets/{mel-CMOJa9Mg.js → mel-nh8j7W_6.js} +1 -1
  194. package/dist/ui/assets/{mercury-uvrRzupw.js → mercury-DyyD-pqr.js} +1 -1
  195. package/dist/ui/assets/{mindmap-definition-LN4V7U3C-DK8j_8Ap.js → mindmap-definition-LN4V7U3C-CJlhDHqM.js} +1 -1
  196. package/dist/ui/assets/{mipsasm-p1gWpDuw.js → mipsasm-hiEhRRiq.js} +1 -1
  197. package/dist/ui/assets/{mizar-DV1ENOOU.js → mizar-BZa3iAAL.js} +1 -1
  198. package/dist/ui/assets/{mojolicious-tg5XQSro.js → mojolicious-BCIm2V_y.js} +1 -1
  199. package/dist/ui/assets/{monkey-D8mYa31Q.js → monkey-zmK-7N8b.js} +1 -1
  200. package/dist/ui/assets/{moonscript-1d_rtlyv.js → moonscript-BsS_Mn3D.js} +1 -1
  201. package/dist/ui/assets/{n1ql-C5srRxme.js → n1ql-D7xVgDP0.js} +1 -1
  202. package/dist/ui/assets/{nginx-xS1muaWm.js → nginx-ct2q4dtd.js} +1 -1
  203. package/dist/ui/assets/{nim-CGGiMQfp.js → nim-RO0UOmW3.js} +1 -1
  204. package/dist/ui/assets/{nix-C77HsR7m.js → nix-BcRJxPKH.js} +1 -1
  205. package/dist/ui/assets/{node-repl-CSeYusSM.js → node-repl-DgIefwxW.js} +1 -1
  206. package/dist/ui/assets/{nsis-BffC7mSW.js → nsis-DqHs9QhB.js} +1 -1
  207. package/dist/ui/assets/{objectivec-WpjnmlJB.js → objectivec-BBcWqc7Y.js} +1 -1
  208. package/dist/ui/assets/{ocaml-CHUkJkjB.js → ocaml-BExfw7D6.js} +1 -1
  209. package/dist/ui/assets/{openscad-BvImqFT0.js → openscad-CHPRELQb.js} +1 -1
  210. package/dist/ui/assets/{oxygene-BMBykbf5.js → oxygene-DpS9uMJW.js} +1 -1
  211. package/dist/ui/assets/{parser3-lRbuZW0M.js → parser3-CjJ_QdBp.js} +1 -1
  212. package/dist/ui/assets/{pegDiagram-2B236MQR-C4DWmrja.js → pegDiagram-2B236MQR-GM70woGy.js} +1 -1
  213. package/dist/ui/assets/{perl-B0DjfKoO.js → perl-BSNM2Kt8.js} +1 -1
  214. package/dist/ui/assets/{pf-Aor6NyYJ.js → pf-Z-hKf_88.js} +1 -1
  215. package/dist/ui/assets/{pgsql-CVKcjjNR.js → pgsql-DDgznxBg.js} +1 -1
  216. package/dist/ui/assets/{php-CZ7geHZt.js → php-BzAhxF-l.js} +1 -1
  217. package/dist/ui/assets/{php-template-DiFuW2dF.js → php-template-DkgcKHRc.js} +1 -1
  218. package/dist/ui/assets/{pieDiagram-ENE6RG2P-BO7AmF5j.js → pieDiagram-ENE6RG2P-Bst7mPyz.js} +1 -1
  219. package/dist/ui/assets/{plaintext-DcvmOuNc.js → plaintext-BYEppD0R.js} +1 -1
  220. package/dist/ui/assets/{pony-DGPeAcOc.js → pony-BT_kQd1K.js} +1 -1
  221. package/dist/ui/assets/{powershell-DsrPyJdK.js → powershell-BfRsuSsf.js} +1 -1
  222. package/dist/ui/assets/{processing-Co2VRXN1.js → processing-DpzWe5Iu.js} +1 -1
  223. package/dist/ui/assets/{profile-D4PjpLUf.js → profile-BCOhS5cM.js} +1 -1
  224. package/dist/ui/assets/{prolog-DEbkeg9r.js → prolog-OxaCCaW8.js} +1 -1
  225. package/dist/ui/assets/{properties-Cxqcuj1s.js → properties-DMFlA2Ca.js} +1 -1
  226. package/dist/ui/assets/{protobuf-C-zdlrww.js → protobuf-CRDFkXvZ.js} +1 -1
  227. package/dist/ui/assets/{puppet-BPX3SrOx.js → puppet-DnrVyLzx.js} +1 -1
  228. package/dist/ui/assets/{purebasic-BdQnNJS3.js → purebasic-Dht4Hniv.js} +1 -1
  229. package/dist/ui/assets/{python-D067_Gj8.js → python-B0aMirWu.js} +1 -1
  230. package/dist/ui/assets/{python-repl-DCqNVlc0.js → python-repl-BlYDBGa7.js} +1 -1
  231. package/dist/ui/assets/{q-kABXYW-8.js → q-DzrtW9kT.js} +1 -1
  232. package/dist/ui/assets/{qml-Iao-Whg7.js → qml-DnfQsR3i.js} +1 -1
  233. package/dist/ui/assets/{quadrantDiagram-ABIIQ3AL-DetQn-0l.js → quadrantDiagram-ABIIQ3AL-DNRYurBT.js} +1 -1
  234. package/dist/ui/assets/{r-BnwpapnO.js → r-DGI_ZuTD.js} +1 -1
  235. package/dist/ui/assets/{railroadDiagram-RFXS5EU6-DFaFKHAH.js → railroadDiagram-RFXS5EU6-CmbC3Vz4.js} +1 -1
  236. package/dist/ui/assets/{reasonml-Cn_Y03uT.js → reasonml-3SohMgh2.js} +1 -1
  237. package/dist/ui/assets/{requirementDiagram-TGXJPOKE-Dg1LrT-T.js → requirementDiagram-TGXJPOKE-8CxrXHco.js} +1 -1
  238. package/dist/ui/assets/{rib-ByAqQn0v.js → rib-DfRSd4Qa.js} +1 -1
  239. package/dist/ui/assets/{roboconf-BJPu6NC5.js → roboconf-CQczGdGW.js} +1 -1
  240. package/dist/ui/assets/{routeros-CL3Jm0Zq.js → routeros-DCka-T2i.js} +1 -1
  241. package/dist/ui/assets/{rsl-DaXy7KaD.js → rsl-Dr8MOwMo.js} +1 -1
  242. package/dist/ui/assets/{ruby-DI6awte_.js → ruby-C2zFSkh_.js} +1 -1
  243. package/dist/ui/assets/{ruleslanguage-DoTVEZE9.js → ruleslanguage-C97YsgQq.js} +1 -1
  244. package/dist/ui/assets/{rust-ULEd75wO.js → rust-H3h8kd9A.js} +1 -1
  245. package/dist/ui/assets/{sankeyDiagram-HTMAVEWB-DQtFl110.js → sankeyDiagram-HTMAVEWB-DBXLWjEq.js} +1 -1
  246. package/dist/ui/assets/{sas-f7ATFuJk.js → sas-04z0Xu8P.js} +1 -1
  247. package/dist/ui/assets/{scala-Dha1zro2.js → scala-DyB9Aoiv.js} +1 -1
  248. package/dist/ui/assets/{scheme-BcaFHKeF.js → scheme-DBj6nxUi.js} +1 -1
  249. package/dist/ui/assets/{scilab-CIiiyD4z.js → scilab-Btj7AD9s.js} +1 -1
  250. package/dist/ui/assets/{scss-CkBomL0n.js → scss-BXZJyXt7.js} +1 -1
  251. package/dist/ui/assets/{sequenceDiagram-DBY2YBRQ-DIbNQtCn.js → sequenceDiagram-DBY2YBRQ-DXIkBFKC.js} +1 -1
  252. package/dist/ui/assets/{shell-Cxu8Py1z.js → shell-BsreQR1Z.js} +1 -1
  253. package/dist/ui/assets/{sizeCapture-X5ZJPWSS-Cj7PglQv.js → sizeCapture-X5ZJPWSS-ocS9jxAQ.js} +1 -1
  254. package/dist/ui/assets/{smali-C4EYyWYz.js → smali-D9wQw9zm.js} +1 -1
  255. package/dist/ui/assets/{smalltalk-BlPTprP4.js → smalltalk-Dku6G_H3.js} +1 -1
  256. package/dist/ui/assets/{sml-DEPzhlr4.js → sml-BknyU6ya.js} +1 -1
  257. package/dist/ui/assets/{sqf-CRu3asu9.js → sqf-DRYMaOg8.js} +1 -1
  258. package/dist/ui/assets/{sql-DK-YfQqg.js → sql-Cw3Ax4KA.js} +1 -1
  259. package/dist/ui/assets/{sql_more-BuMEOcjj.js → sql_more-vWdslLE0.js} +1 -1
  260. package/dist/ui/assets/{stan-DMr13kyD.js → stan-8XH5bDS6.js} +1 -1
  261. package/dist/ui/assets/{stata-Bt6E2zQi.js → stata-4e77wgfe.js} +1 -1
  262. package/dist/ui/assets/{stateDiagram-2N3HPSRC-Bk-gF72D.js → stateDiagram-2N3HPSRC-RMmL9jMG.js} +1 -1
  263. package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-QvaEO5U6.js +1 -0
  264. package/dist/ui/assets/{step21-Bi954ur4.js → step21-ByIeDMY3.js} +1 -1
  265. package/dist/ui/assets/{stylus-CQwwMaLm.js → stylus-ZAhJyWsw.js} +1 -1
  266. package/dist/ui/assets/{subunit-BkixDEMH.js → subunit-pPW2UGkj.js} +1 -1
  267. package/dist/ui/assets/{swift-DS1DWNAE.js → swift-CX3BB5az.js} +1 -1
  268. package/dist/ui/assets/{swimlanes-5IMT3BWC-C-AZKO5z.js → swimlanes-5IMT3BWC-C2zAuJ56.js} +2 -2
  269. package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DPgCOY0D.js +8 -0
  270. package/dist/ui/assets/{taggerscript-DZHi1hoc.js → taggerscript-BHcjbWIC.js} +1 -1
  271. package/dist/ui/assets/{tap-CXxSD8bM.js → tap-BOl1lBlS.js} +1 -1
  272. package/dist/ui/assets/{tcl-CdoAAMbn.js → tcl-DZjeOBDh.js} +1 -1
  273. package/dist/ui/assets/{thrift-DM086HVt.js → thrift-BxboWg4x.js} +1 -1
  274. package/dist/ui/assets/{timeline-definition-FHXFAJF6-DcrcjFwq.js → timeline-definition-FHXFAJF6-BOxsxyq_.js} +1 -1
  275. package/dist/ui/assets/{tp-Y-w3S3ES.js → tp-BNM6ql3J.js} +1 -1
  276. package/dist/ui/assets/{twig-C5c_nAus.js → twig-Dj9ZiXD4.js} +1 -1
  277. package/dist/ui/assets/{typescript-fc7SMhJu.js → typescript-7MEJlu_6.js} +1 -1
  278. package/dist/ui/assets/{vala-BV-GlwLI.js → vala-DNqOAgHJ.js} +1 -1
  279. package/dist/ui/assets/{vbnet-BIqQmnKr.js → vbnet-T0mNKVc_.js} +1 -1
  280. package/dist/ui/assets/{vbscript-h186Lnrz.js → vbscript-CeuwVMAI.js} +1 -1
  281. package/dist/ui/assets/{vbscript-html-DcuP7lTb.js → vbscript-html-BbJSt2w6.js} +1 -1
  282. package/dist/ui/assets/{vennDiagram-L72KCM5P-Dnh11y2e.js → vennDiagram-L72KCM5P-BX9mWeiT.js} +1 -1
  283. package/dist/ui/assets/{verilog-Cbgb_XnR.js → verilog-DYuhYfkX.js} +1 -1
  284. package/dist/ui/assets/{vhdl-COP7w5IC.js → vhdl-Cf9aT-t7.js} +1 -1
  285. package/dist/ui/assets/{vim-COGwKzgS.js → vim-DciP44K1.js} +1 -1
  286. package/dist/ui/assets/{wardleyDiagram-EHGQE667-BeiD8fPz.js → wardleyDiagram-EHGQE667-CDj2rOzu.js} +1 -1
  287. package/dist/ui/assets/{x86asm-BdBqPPf4.js → x86asm-E-AN_LXO.js} +1 -1
  288. package/dist/ui/assets/{xl-BmCQT7Vj.js → xl-CxYLJelN.js} +1 -1
  289. package/dist/ui/assets/{xml-DM0NxGiJ.js → xml-yz1SRLuU.js} +1 -1
  290. package/dist/ui/assets/{xquery-BUaYHDJM.js → xquery-BLzBF3tV.js} +1 -1
  291. package/dist/ui/assets/{xychartDiagram-FW5EYKEG-CnwvTrkm.js → xychartDiagram-FW5EYKEG-Czapk9-Z.js} +1 -1
  292. package/dist/ui/assets/{yaml-DMs8lGDt.js → yaml-Cv4Y7iN_.js} +1 -1
  293. package/dist/ui/assets/{zephir-BvjoPdmg.js → zephir-KRcdQfEX.js} +1 -1
  294. package/dist/ui/index.html +2 -2
  295. package/dist/utils/__tests__/knowledge-store.test.js +86 -5
  296. package/dist/utils/__tests__/pi-browser-tools.test.d.ts +1 -0
  297. package/dist/utils/__tests__/pi-browser-tools.test.js +30 -0
  298. package/dist/utils/__tests__/pi-crawl-tools.test.d.ts +1 -0
  299. package/dist/utils/__tests__/pi-crawl-tools.test.js +315 -0
  300. package/dist/utils/__tests__/pi-dedup-reconcile.test.d.ts +1 -0
  301. package/dist/utils/__tests__/pi-dedup-reconcile.test.js +89 -0
  302. package/dist/utils/__tests__/pi-dedup.test.d.ts +1 -0
  303. package/dist/utils/__tests__/pi-dedup.test.js +106 -0
  304. package/dist/utils/__tests__/pi-learn-orchestrator.test.d.ts +1 -0
  305. package/dist/utils/__tests__/pi-learn-orchestrator.test.js +885 -0
  306. package/dist/utils/__tests__/pi-runtime-json.test.d.ts +1 -0
  307. package/dist/utils/__tests__/pi-runtime-json.test.js +11 -0
  308. package/dist/utils/__tests__/web-crawler.test.d.ts +1 -0
  309. package/dist/utils/__tests__/web-crawler.test.js +69 -0
  310. package/dist/utils/db.d.ts +1 -0
  311. package/dist/utils/db.js +18 -0
  312. package/dist/utils/knowledge-store.d.ts +9 -0
  313. package/dist/utils/knowledge-store.js +85 -11
  314. package/dist/utils/pi-browser-tools.d.ts +2 -0
  315. package/dist/utils/pi-browser-tools.js +9 -2
  316. package/dist/utils/pi-crawl-tools.d.ts +62 -0
  317. package/dist/utils/pi-crawl-tools.js +298 -0
  318. package/dist/utils/pi-dedup.d.ts +62 -0
  319. package/dist/utils/pi-dedup.js +218 -0
  320. package/dist/utils/pi-learn-orchestrator.d.ts +44 -0
  321. package/dist/utils/pi-learn-orchestrator.js +431 -0
  322. package/dist/utils/pi-runtime.d.ts +23 -1
  323. package/dist/utils/pi-runtime.js +255 -68
  324. package/dist/utils/request-writer.d.ts +1 -0
  325. package/dist/utils/request-writer.js +5 -4
  326. package/dist/utils/web-crawler.d.ts +13 -0
  327. package/dist/utils/web-crawler.js +64 -0
  328. package/package.json +1 -1
  329. package/dist/docs/assets/chunks/@localSearchIndexroot.CHyuB7c8.js +0 -1
  330. package/dist/ui/assets/channel-BdcV3Ykv.js +0 -1
  331. package/dist/ui/assets/classDiagram-OUVF2IWQ-CAZR5rAv.js +0 -1
  332. package/dist/ui/assets/classDiagram-v2-EOCWNBFH-CAZR5rAv.js +0 -1
  333. package/dist/ui/assets/index-WPLwx8h5.css +0 -10
  334. package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-BFJCYsLY.js +0 -1
  335. package/dist/ui/assets/swimlanesDiagram-G3AALYLV-BZd1Gt4_.js +0 -8
@@ -0,0 +1,431 @@
1
+ // pi-learn-orchestrator: outline/refine/tag 三阶段 learn 流水线
2
+ // - outline: url 模式先由 crawl agent 在阶段内自己驱动渐进抓取(crawl_open/crawl_visit/
3
+ // save_source)写 sources/,再由单次 outline session read_source + add_outline
4
+ // 写 outline.json + seed topic;file 模式直接把上传正文写 sources/
5
+ // - refine: 对 outline.items 逐项开新 refine session,写 chunks/chunk-NNN.md
6
+ // - tag: 单次 tag session,读 chunks 后调 add_topic 写富 tags
7
+ //
8
+ // "轮次" = 一次 assistant 交互(assistant message_start → message_end);
9
+ // slug 由入口 URL / 文件名确定性生成。
10
+ import fs from 'node:fs';
11
+ import path from 'node:path';
12
+ import { dataDir } from './paths.js';
13
+ import { createPiSession } from './pi-runtime.js';
14
+ import { CrawlGuard } from './pi-crawl-tools.js';
15
+ import { slugFromUrl, slugFromLabel } from './web-crawler.js';
16
+ import { assertNoOldDirs, readAllTopics, readSidecarDetail, readTopicDetail, reconcileTopics, mergeTopics, mintSlug } from './pi-dedup.js';
17
+ // 每阶段(含 S2 每个 item prompt)独立超时:5 分钟。
18
+ // 防止 pi session 在 stuck LLM 响应上无限挂起,导致 SSE 通道常开、前端永久转圈。
19
+ const STAGE_TIMEOUT_MS = 5 * 60 * 1000;
20
+ /**
21
+ * Promise.race 包一层超时。超时触发时调用 abortFn(session.abort()),
22
+ * 然后 reject;正常 settle 时清掉 timer,避免泄漏。
23
+ */
24
+ function withTimeout(p, ms, abortFn) {
25
+ let timer;
26
+ const timeoutP = new Promise((_, reject) => {
27
+ timer = setTimeout(() => {
28
+ // 触发 abort,尽量让底层 fetch/pi session 提前收尾;reject 用明确错误
29
+ abortFn().catch(() => { });
30
+ reject(new Error(`stage 超时 ${ms}ms`));
31
+ }, ms);
32
+ });
33
+ return Promise.race([
34
+ p.finally(() => {
35
+ if (timer)
36
+ clearTimeout(timer);
37
+ }),
38
+ timeoutP,
39
+ ]);
40
+ }
41
+ /**
42
+ * 跑一次 prompt,透传 text/tool 事件到 events;resolve 当 prompt 自然结束。
43
+ * 同时返回本 session 内关键工具调用的标志位(用于 S3 成功判定)。
44
+ */
45
+ async function runPrompt(session, promptText, events, roundCounter) {
46
+ const result = { addTopicCalled: false, readSourceOk: false };
47
+ // Finding 1:tool_execution_start 时只记录「即将调 add_topic 且 tags 非空」,
48
+ // 真正置位必须等 tool_execution_end 且 isError=false。否则工具执行失败(upsert
49
+ // 抛错/非法 slug/JSON 写失败)时重试循环会误判成功。
50
+ let pendingAddTopicWithTags = false;
51
+ // 当前轮次索引:message_start 时记录,message_end 透传同一个值
52
+ let currentRound = 0;
53
+ // 轮次是否在途:pi abort 时在途 assistant message 不发 message_end,
54
+ // finally 需据此补发 roundEnd,保证任何退出路径轮次闭合
55
+ let roundOpen = false;
56
+ const unsub = session.subscribe((ev) => {
57
+ try {
58
+ if (ev.type === 'message_start' && ev.message?.role === 'assistant') {
59
+ currentRound = roundCounter.index;
60
+ roundCounter.index += 1;
61
+ roundOpen = true;
62
+ events.roundStart(currentRound);
63
+ }
64
+ else if (ev.type === 'message_end' && ev.message?.role === 'assistant') {
65
+ roundOpen = false;
66
+ events.roundEnd(currentRound);
67
+ }
68
+ else if (ev.type === 'message_update') {
69
+ const ae = ev.assistantMessageEvent;
70
+ if (ae?.type === 'text_delta' && typeof ae.delta === 'string') {
71
+ events.textDelta(ae.delta);
72
+ }
73
+ else if (ae?.type === 'thinking_delta' && typeof ae.delta === 'string') {
74
+ events.thinkingDelta(ae.delta);
75
+ }
76
+ }
77
+ else if (ev.type === 'tool_execution_start') {
78
+ events.toolStart({
79
+ toolCallId: ev.toolCallId,
80
+ toolName: ev.toolName,
81
+ args: ev.args,
82
+ });
83
+ if (ev.toolName === 'add_topic') {
84
+ const tags = ev.args?.tags;
85
+ pendingAddTopicWithTags = Array.isArray(tags) && tags.length > 0;
86
+ }
87
+ }
88
+ else if (ev.type === 'tool_execution_end') {
89
+ const resultText = Array.isArray(ev.result?.content)
90
+ ? ev.result.content.map((c) => (c?.type === 'text' ? c.text : '')).join('\n')
91
+ : '';
92
+ if (ev.toolName === 'add_topic' && pendingAddTopicWithTags && !ev.isError) {
93
+ result.addTopicCalled = true;
94
+ }
95
+ if (ev.toolName === 'read_source' && !ev.isError) {
96
+ result.readSourceOk = true;
97
+ }
98
+ events.toolEnd({
99
+ toolCallId: ev.toolCallId,
100
+ toolName: ev.toolName,
101
+ isError: !!ev.isError,
102
+ durationMs: ev.durationMs ?? 0,
103
+ result: resultText,
104
+ });
105
+ }
106
+ }
107
+ catch {
108
+ // 事件转发失败不中断流水线
109
+ }
110
+ });
111
+ try {
112
+ // Finding 3:整个 prompt + waitForIdle 包 5 分钟超时;超时 abort 并抛错。
113
+ await withTimeout((async () => {
114
+ await session.prompt(promptText);
115
+ await session.waitForIdle();
116
+ })(), STAGE_TIMEOUT_MS, () => session.abort());
117
+ }
118
+ finally {
119
+ unsub();
120
+ // 在途轮次补闭合(abort/超时/异常导致 message_end 缺失);回调异常不外泄
121
+ if (roundOpen) {
122
+ try {
123
+ events.roundEnd(currentRound);
124
+ }
125
+ catch { /* 忽略 */ }
126
+ }
127
+ }
128
+ return result;
129
+ }
130
+ // ============================================================
131
+ // 原料准备 + outline 阶段
132
+ // ============================================================
133
+ /** 重建 topic 目录:sources/(抓取/上传原料)+ chunks/(后续产物) */
134
+ function prepareTopicDir(docsDir, slug) {
135
+ const dir = path.join(docsDir, slug);
136
+ fs.rmSync(dir, { recursive: true, force: true });
137
+ fs.mkdirSync(path.join(dir, 'sources'), { recursive: true });
138
+ fs.mkdirSync(path.join(dir, 'chunks'), { recursive: true });
139
+ }
140
+ /** 写一份原料到 <slug>/sources/source-NNN.md */
141
+ function writeSourceFile(docsDir, slug, index, url, text) {
142
+ const name = `source-${String(index + 1).padStart(3, '0')}.md`;
143
+ fs.writeFileSync(path.join(docsDir, slug, 'sources', name), `Source: ${url}\n\n${text}`, 'utf8');
144
+ }
145
+ /** 数 <slug>/sources 下 .md 文件数量;目录不存在按 0 */
146
+ function countSourceFiles(docsDir, slug) {
147
+ try {
148
+ return fs.readdirSync(path.join(docsDir, slug, 'sources')).filter((f) => f.endsWith('.md')).length;
149
+ }
150
+ catch {
151
+ return 0;
152
+ }
153
+ }
154
+ async function runOutlineStage(opts, events, roundCounter) {
155
+ // 抓取必须在 stageStart 之后:crawl 的 round/tool 事件才能落进前端已建好的 outline 阶段
156
+ events.stageStart('outline');
157
+ let guard = null;
158
+ try {
159
+ if (opts.sourceType === 'url') {
160
+ // crawl agent 在阶段内自己驱动渐进抓取;0 页则全新 guard+session 重试 1 次
161
+ guard = new CrawlGuard({ entryUrl: opts.input, docsDir: opts.docsDir, slug: opts.slug });
162
+ let crawlSession = (await createPiSession({
163
+ port: opts.port,
164
+ mode: 'crawl',
165
+ crawlGuard: guard,
166
+ }));
167
+ const crawlPrompt = `Entry URL: ${opts.input}\n` +
168
+ `Topic slug: ${opts.slug}\n` +
169
+ `Call crawl_open to start, save every useful page with save_source, then call crawl_finish.`;
170
+ await runPrompt(crawlSession, crawlPrompt, events, roundCounter);
171
+ if (countSourceFiles(opts.docsDir, opts.slug) === 0) {
172
+ // 替换前关闭旧 guard(close 容错),再全新 guard + session 重试一次
173
+ await guard.close();
174
+ guard = new CrawlGuard({ entryUrl: opts.input, docsDir: opts.docsDir, slug: opts.slug });
175
+ crawlSession = (await createPiSession({
176
+ port: opts.port,
177
+ mode: 'crawl',
178
+ crawlGuard: guard,
179
+ }));
180
+ await runPrompt(crawlSession, crawlPrompt, events, roundCounter);
181
+ if (countSourceFiles(opts.docsDir, opts.slug) === 0) {
182
+ throw new Error('crawl 未收集到页面');
183
+ }
184
+ }
185
+ }
186
+ else {
187
+ writeSourceFile(opts.docsDir, opts.slug, 0, opts.label ?? 'uploaded-file', opts.input);
188
+ }
189
+ // crawl 完成后的 outline session(流程不变)
190
+ const session = (await createPiSession({ port: opts.port, mode: 'outline' }));
191
+ const prompt = `Topic slug: ${opts.slug}\n` +
192
+ `Call read_source(${JSON.stringify(opts.slug)}) to read the prepared sources, then call add_outline with this EXACT slug (${JSON.stringify(opts.slug)}). ` +
193
+ `Provide an appropriate title and the outline items.`;
194
+ await runPrompt(session, prompt, events, roundCounter);
195
+ const outlinePath = path.join(opts.docsDir, opts.slug, 'outline.json');
196
+ if (!fs.existsSync(outlinePath))
197
+ throw new Error('outline 未生成');
198
+ const outline = JSON.parse(fs.readFileSync(outlinePath, 'utf8'));
199
+ // title 取 S1 seed 的 index.json(查重门需要候选标题)
200
+ const seedIdx = JSON.parse(fs.readFileSync(path.join(opts.docsDir, opts.slug, 'index.json'), 'utf8'));
201
+ return { slug: opts.slug, items: outline.items, title: seedIdx.title };
202
+ }
203
+ finally {
204
+ // 兜底关闭当前 guard(crawl_finish 已关时 close 也安全)
205
+ await guard?.close();
206
+ events.stageEnd('outline');
207
+ }
208
+ }
209
+ // ============================================================
210
+ // refine 阶段
211
+ // ============================================================
212
+ async function runRefineStage(opts, slug, items, events, roundCounter,
213
+ /** chunk id 起始偏移:合并进已有主题时从目标现有 chunk 数后续号 */
214
+ startOffset = 0) {
215
+ events.stageStart('refine', items.length);
216
+ let chunksWritten = 0;
217
+ let itemsFailed = 0;
218
+ try {
219
+ for (let i = 0; i < items.length; i++) {
220
+ const item = items[i];
221
+ const chunkId = `chunk-${String(startOffset + i + 1).padStart(3, '0')}`;
222
+ events.stageItemStart(i, items.length, item.title);
223
+ try {
224
+ const prompt = `主题 slug: ${slug}\n` +
225
+ `概念: ${item.title}\n` +
226
+ `说明: ${item.oneLine}\n` +
227
+ `请读 source.md 相关段落,写 chunks/${chunkId}.md,然后调 add_chunk 带 tags`;
228
+ let ok = false;
229
+ let failReason = 'chunk 文件未生成';
230
+ for (let attempt = 0; attempt < 2 && !ok; attempt++) {
231
+ const session = (await createPiSession({ port: opts.port, mode: 'refine' }));
232
+ const res = await runPrompt(session, prompt, events, roundCounter);
233
+ if (!res.readSourceOk) {
234
+ failReason = 'read_source 未成功读取';
235
+ continue;
236
+ }
237
+ const chunkPath = path.join(opts.docsDir, slug, 'chunks', `${chunkId}.md`);
238
+ try {
239
+ const stat = fs.statSync(chunkPath);
240
+ if (stat.size > 0)
241
+ ok = true;
242
+ }
243
+ catch {
244
+ // 不存在 → 重试
245
+ }
246
+ }
247
+ // Finding 2:chunk 文件非空不等于 add_chunk 被调。校验 index.json.chunks
248
+ // 里真的有这个 chunkId,否则文件是孤儿(tag 阶段从 index.json 读 chunk 列表会静默跳过)。
249
+ if (ok) {
250
+ let chunkRegistered = false;
251
+ try {
252
+ const idxPath = path.join(opts.docsDir, slug, 'index.json');
253
+ const idx = JSON.parse(fs.readFileSync(idxPath, 'utf8'));
254
+ chunkRegistered = (idx.chunks ?? []).some((c) => c.id === chunkId);
255
+ }
256
+ catch {
257
+ // index.json 读失败/JSON 坏 → 当作未注册
258
+ chunkRegistered = false;
259
+ }
260
+ if (!chunkRegistered) {
261
+ ok = false;
262
+ failReason = 'add_chunk 未调用';
263
+ }
264
+ }
265
+ if (ok) {
266
+ chunksWritten++;
267
+ events.stageItemEnd(i, chunkId);
268
+ }
269
+ else {
270
+ itemsFailed++;
271
+ events.stageItemFailed(i, item.title, failReason);
272
+ }
273
+ }
274
+ catch (e) {
275
+ // per-item 任意错误(createPiSession 失败、prompt 抛错等)→ 不中断整个 refine 阶段
276
+ itemsFailed++;
277
+ events.stageItemFailed(i, item.title, e?.message || String(e));
278
+ }
279
+ }
280
+ }
281
+ finally {
282
+ events.stageEnd('refine');
283
+ }
284
+ return { chunksWritten, itemsFailed };
285
+ }
286
+ // ============================================================
287
+ // tag 阶段
288
+ // ============================================================
289
+ async function runTagStage(opts, slug, events, roundCounter,
290
+ /** 合并场景:查重门裁定的合并后 title/summary,要求 add_topic 设置为该精确值 */
291
+ override) {
292
+ events.stageStart('tag');
293
+ try {
294
+ const topicIdxPath = path.join(opts.docsDir, slug, 'index.json');
295
+ const topicIdx = JSON.parse(fs.readFileSync(topicIdxPath, 'utf8'));
296
+ // 合并后重跑 tag:title/summary 取 override 精确值;否则沿用现有值
297
+ const title = override?.title ?? topicIdx.title;
298
+ const summary = override?.summary ?? topicIdx.summary;
299
+ const chunkListing = (topicIdx.chunks ?? [])
300
+ .map((c) => `- ${c.id}: ${c.title} — ${c.summary}`)
301
+ .join('\n');
302
+ const prompt = `主题 slug: ${slug}\n` +
303
+ `现有 title: ${title}\n` +
304
+ `现有 summary: ${summary}\n` +
305
+ `已有 chunks:\n${chunkListing}\n\n` +
306
+ `请用 read_chunk 读 chunks 实际内容,为该主题生成 5 类富 tags(同义/上位/触发场景/易混淆/典型提问,共 10-20 个小写连字符),` +
307
+ (override
308
+ ? `然后调 add_topic({ slug, title, summary, tags }) 覆盖主题元数据。title/summary 必须使用上面给出的精确值,不要改动。`
309
+ : `然后调 add_topic({ slug, title, summary, tags }) 覆盖主题元数据。title/summary 复用现有值,不要改。`);
310
+ let tagged = false;
311
+ for (let attempt = 0; attempt < 2 && !tagged; attempt++) {
312
+ const session = (await createPiSession({ port: opts.port, mode: 'tag' }));
313
+ const res = await runPrompt(session, prompt, events, roundCounter);
314
+ if (res.addTopicCalled) {
315
+ tagged = true;
316
+ break;
317
+ }
318
+ }
319
+ if (!tagged) {
320
+ throw new Error('add_topic 未调用');
321
+ }
322
+ }
323
+ finally {
324
+ events.stageEnd('tag');
325
+ }
326
+ }
327
+ // ============================================================
328
+ // 主编排
329
+ // ============================================================
330
+ export async function runLearnPipeline(opts) {
331
+ const docsDir = opts.docsDir ?? path.join(dataDir, 'docs');
332
+ const slug = opts.sourceType === 'url' ? slugFromUrl(opts.input) : slugFromLabel(opts.label ?? 'topic');
333
+ // 阻断:存在未清理的 .old 旁挂目录时直接拒绝,必须在一切写入之前
334
+ assertNoOldDirs(docsDir);
335
+ // 全局轮次计数器:所有 session 共享,轮次索引全流水线单调递增
336
+ const roundCounter = { index: 0 };
337
+ // activeSlug:门0 slug 碰撞另铸后,下游各门/阶段实际操作的 slug
338
+ let activeSlug = slug;
339
+ let outline;
340
+ // 门0:slug 精确命中——已有同 slug 主题时先旁挂旧 topic(含点号不被识别为 topic),再全新建并跑 S1
341
+ const collision = (await readAllTopics(docsDir)).some((t) => t.slug === slug);
342
+ if (collision) {
343
+ fs.renameSync(path.join(docsDir, slug), path.join(docsDir, `${slug}.old`));
344
+ prepareTopicDir(docsDir, slug);
345
+ outline = await runOutlineStage({ ...opts, docsDir, slug }, opts.events, roundCounter);
346
+ const sidecar = await readSidecarDetail(docsDir, slug);
347
+ const r0 = await reconcileTopics({
348
+ port: opts.port,
349
+ docsDir,
350
+ candidate: { slug, title: outline.title, tags: [], items: outline.items },
351
+ targets: sidecar ? [sidecar] : [],
352
+ wantItems: true,
353
+ });
354
+ if (r0.match) {
355
+ // dst=canonical:旧 chunks 续号并入,再补新增条目,最后带 merged 打 tag
356
+ const off = mergeTopics(docsDir, `${slug}.old`, slug);
357
+ const refine = await runRefineStage({ port: opts.port, docsDir }, slug, r0.itemsToAdd, opts.events, roundCounter, off);
358
+ await runTagStage({ port: opts.port, docsDir }, slug, opts.events, roundCounter, { title: r0.mergedTitle, summary: r0.mergedSummary });
359
+ return { slug, chunksWritten: refine.chunksWritten, itemsFailed: refine.itemsFailed };
360
+ }
361
+ // slug 真碰撞:新内容另铸 ns,旧 topic 还原
362
+ const ns = await mintSlug({
363
+ port: opts.port,
364
+ title: outline.title,
365
+ existing: (await readAllTopics(docsDir)).map((t) => t.slug),
366
+ });
367
+ // 新 canonical → ns,更正其 index.slug
368
+ fs.renameSync(path.join(docsDir, slug), path.join(docsDir, ns));
369
+ const nsIdxPath = path.join(docsDir, ns, 'index.json');
370
+ const nsIdx = JSON.parse(fs.readFileSync(nsIdxPath, 'utf8'));
371
+ nsIdx.slug = ns;
372
+ fs.writeFileSync(nsIdxPath, JSON.stringify(nsIdx, null, 2), 'utf8');
373
+ // 根 index:把 S1 为新内容登记的 slug 条目改挂 ns
374
+ const rootPath = path.join(docsDir, 'index.json');
375
+ const rootIdx = JSON.parse(fs.readFileSync(rootPath, 'utf8'));
376
+ const newEntry = rootIdx.topics.find((t) => t.slug === slug);
377
+ if (newEntry)
378
+ newEntry.slug = ns;
379
+ // 旧 topic 还原:.old → slug
380
+ fs.renameSync(path.join(docsDir, `${slug}.old`), path.join(docsDir, slug));
381
+ const oldIdx = JSON.parse(fs.readFileSync(path.join(docsDir, slug, 'index.json'), 'utf8'));
382
+ const oldRoot = rootIdx.topics.find((t) => t.slug === slug);
383
+ if (oldRoot) {
384
+ oldRoot.title = oldIdx.title;
385
+ oldRoot.summary = oldIdx.summary;
386
+ oldRoot.tags = oldIdx.tags;
387
+ }
388
+ else {
389
+ rootIdx.topics.push({ slug, title: oldIdx.title, summary: oldIdx.summary, tags: oldIdx.tags });
390
+ }
391
+ fs.writeFileSync(rootPath, JSON.stringify(rootIdx, null, 2), 'utf8');
392
+ activeSlug = ns;
393
+ }
394
+ else {
395
+ prepareTopicDir(docsDir, slug);
396
+ outline = await runOutlineStage({ ...opts, docsDir, slug }, opts.events, roundCounter);
397
+ }
398
+ // 门1:outline 后、refine 前,基于大纲条目查重(命中则只要需新增的条目)
399
+ const r1 = await reconcileTopics({
400
+ port: opts.port,
401
+ docsDir,
402
+ candidate: { slug: activeSlug, title: outline.title, tags: [], items: outline.items },
403
+ wantItems: true,
404
+ });
405
+ if (r1.match) {
406
+ const targetSlug = r1.targetSlug;
407
+ // 先物理并入(返回目标现有 chunk 总数作为续号偏移),再只写新增条目,最后带 override 打 tag
408
+ const off = mergeTopics(docsDir, activeSlug, targetSlug);
409
+ const refine = await runRefineStage({ port: opts.port, docsDir }, targetSlug, r1.itemsToAdd, opts.events, roundCounter, off);
410
+ await runTagStage({ port: opts.port, docsDir }, targetSlug, opts.events, roundCounter, { title: r1.mergedTitle, summary: r1.mergedSummary });
411
+ return { slug: targetSlug, chunksWritten: refine.chunksWritten, itemsFailed: refine.itemsFailed };
412
+ }
413
+ // 门1 未命中:常规 refine(从头编号)+ 常规 tag
414
+ const refine = await runRefineStage({ port: opts.port, docsDir }, activeSlug, outline.items, opts.events, roundCounter, 0);
415
+ await runTagStage({ port: opts.port, docsDir }, activeSlug, opts.events, roundCounter);
416
+ // 门2:tag 后基于富 tags 再查一次(不需要新增条目)
417
+ const detail = await readTopicDetail(docsDir, activeSlug);
418
+ const r2 = await reconcileTopics({
419
+ port: opts.port,
420
+ docsDir,
421
+ candidate: { slug: activeSlug, title: outline.title, tags: detail?.tags ?? [], items: undefined },
422
+ wantItems: false,
423
+ });
424
+ if (r2.match) {
425
+ const targetSlug = r2.targetSlug;
426
+ mergeTopics(docsDir, activeSlug, targetSlug);
427
+ await runTagStage({ port: opts.port, docsDir }, targetSlug, opts.events, roundCounter, { title: r2.mergedTitle, summary: r2.mergedSummary });
428
+ return { slug: targetSlug, chunksWritten: refine.chunksWritten, itemsFailed: refine.itemsFailed };
429
+ }
430
+ return { slug: activeSlug, chunksWritten: refine.chunksWritten, itemsFailed: refine.itemsFailed };
431
+ }
@@ -1,8 +1,30 @@
1
1
  import { type AgentSession } from '@earendil-works/pi-coding-agent';
2
- export type PiSessionMode = 'chat' | 'learn';
2
+ import { type CrawlGuard } from './pi-crawl-tools.js';
3
+ export type PiSessionMode = 'chat' | 'outline' | 'refine' | 'tag' | 'crawl' | 'reconcile';
3
4
  export interface CreatePiSessionOptions {
4
5
  cwd?: string;
5
6
  port: number;
6
7
  mode: PiSessionMode;
8
+ /** mode='crawl' 时必填:渐进抓取状态守卫 */
9
+ crawlGuard?: CrawlGuard;
7
10
  }
11
+ export declare const CHAT_SYSTEM_PROMPT = "You are a knowledge management AI operating inside a sandbox.\nYour knowledge directory (~/.cc-monitoring/docs) stores a **dictionary**: concise, distilled entries a future reader can look up. You do NOT copy source text \u2014 you digest it.\n\nSTRUCTURE (all paths below are RELATIVE TO the knowledge root ~/.cc-monitoring/docs \u2014 the write tool's working directory IS this root, so NEVER prefix a path with \"docs/\"):\n- Each topic is a subfolder: <topic-slug>/\n- Each topic has <slug>/index.json (metadata + chunk list, NO body)\n- Bodies live in <topic-slug>/chunks/chunk-NNN.md\n- Root index.json lists all topics as JSON\n- Fetched source pages for a topic are already prepared in <slug>/sources/ \u2014 you only READ them, never write or modify them\n\nANSWERING QUESTIONS:\n1. Call list_topics to see available topics\n2. If topic is unclear, call search_chunks(query) to find relevant chunks across topics\n3. Call get_topic(topic) to see that topic's chunk list\n4. Call read_chunk(topic, chunk_id) for relevant chunks \u2014 only read chunks you need\n5. Prefer answering from knowledge base chunks when relevant content exists; cite which chunks you used\n6. If no relevant chunk exists, answer from your general knowledge; if you truly don't know, say so";
12
+ export declare const OUTLINE_SYSTEM_PROMPT = "You are an outline-phase worker. The relevant web pages have ALREADY been fetched and saved to sources/ for your assigned topic. Your job: read them and propose an outline of dictionary entries. Do NOT write chunks.\n\nYour knowledge directory (~/.cc-monitoring/docs) stores a **dictionary**: concise, distilled entries a future reader can look up. You do NOT copy source text \u2014 you digest it.\n\nSTRUCTURE (all paths below are RELATIVE TO the knowledge root ~/.cc-monitoring/docs \u2014 the write tool's working directory IS this root, so NEVER prefix a path with \"docs/\"):\n- Each topic is a subfolder: <topic-slug>/\n- Each topic has <slug>/index.json (metadata + chunk list, NO body)\n- Bodies live in <topic-slug>/chunks/chunk-NNN.md\n- Root index.json lists all topics as JSON\n- Fetched source pages for a topic are already prepared in <slug>/sources/ \u2014 you only READ them, never write or modify them\n\nWORKFLOW:\n1. Call read_source(topic) to load ALL fetched source pages (multiple pages are separated by ---).\n2. Outline the DISTINCT concepts actually present across these pages. One concept = one future chunk. Do not bundle unrelated ideas.\n3. Call add_outline(slug, title, items) ONCE at the end:\n - slug: the EXACT slug given in your task\n - title: human-readable topic title\n - items: array of { id, title, oneLine } \u2014 id is a short stable slug per item (e.g. \"use-state\"), oneLine is a single-sentence definition\n\nHARD RULES:\n- Use ONLY content present in the fetched sources. Do NOT add concepts from training-data memory. If the sources are thin, outline only what is there.\n- read_source MUST be your first call. If it returns an error, STOP and report it immediately.\n- Do NOT write chunk files, source files, or index.json.\n- Do NOT summarize prematurely \u2014 outline only; distillation happens later.\n- After add_outline succeeds, print the returned slug and item count. Stop.";
13
+ export declare const CRAWL_SYSTEM_PROMPT = "You are a crawl-phase worker. You drive the browser YOURSELF to incrementally fetch web pages for your assigned topic and save every useful page into sources/. Do NOT outline or write chunks.\n\nWORKFLOW:\n1. Call crawl_open to open the entry URL given in your task.\n2. Call save_source(url) to save the CURRENT page.\n3. From the page's links, pick same-site, valuable CONTENT pages \u2014 skip login/signup, navigation chrome, language switchers, pagination, and pure anchors. Call crawl_visit(url), then save_source(url) for each page.\n4. When there are no more useful links, or the page/depth limit is reached, call crawl_finish, print the returned stats, and stop.\n\nHARD RULES:\n- Write ONLY into sources/ via save_source. Never write other files.\n- Never visit cross-site URLs.\n- If a tool returns an error, do NOT retry the same URL; pick another link or finish.\n- At most ~20 pages. Prefer a few dense pages over many thin ones.\n- After crawl_finish succeeds, stop.";
14
+ export declare const REFINE_SYSTEM_PROMPT = "You are a refine-phase worker. For ONE item from the topic's outline, produce a single dictionary chunk.\n\nYour knowledge directory (~/.cc-monitoring/docs) stores a **dictionary**: concise, distilled entries a future reader can look up. You do NOT copy source text \u2014 you digest it.\n\nSTRUCTURE (all paths below are RELATIVE TO the knowledge root ~/.cc-monitoring/docs \u2014 the write tool's working directory IS this root, so NEVER prefix a path with \"docs/\"):\n- Each topic is a subfolder: <topic-slug>/\n- Each topic has <slug>/index.json (metadata + chunk list, NO body)\n- Bodies live in <topic-slug>/chunks/chunk-NNN.md\n- Root index.json lists all topics as JSON\n- Fetched source pages for a topic are already prepared in <slug>/sources/ \u2014 you only READ them, never write or modify them\n\nWORKFLOW:\n1. Call read_source(topic) to load ALL fetched source pages (multiple pages separated by ---).\n2. Focus on your assigned item. Do NOT distill other items.\n3. Write ONE chunk file <topic>/chunks/chunk-NNN.md (number sequentially from 001; path RELATIVE TO the knowledge root, no \"docs/\" prefix) using the write tool, in the source document's language, with this structure:\n\n```\n# <term or concept name>\n\n- \u5B9A\u4E49 / Definition: <one sentence, in your own words>\n- \u662F\u4EC0\u4E48 / What it is: <2-4 bullets, the core idea>\n- \u4E0D\u662F\u4EC0\u4E48 / What it is NOT: <common confusions, if any>\n- \u5173\u952E\u70B9 / Key points: <3-6 bullets, the load-bearing facts>\n- \u9002\u7528\u573A\u666F / When to use: <where this applies>\n- \u8BEF\u533A / Pitfalls: <common mistakes, edge cases>\n- \u6765\u6E90 / Source: <url(s) of the page(s) you actually used \u2014 copy them from the \"Source:\" headers at the top of each fetched page; list several URLs if the chunk draws on several pages>\n```\n\n4. Call add_chunk(topic, chunk_id, title, summary, tags) to register it.\n - tags: 3-6 lowercase hyphenated tags describing the concept (synonyms, key terms).\n\nHARD RULES:\n- read_source MUST be your first call. If it returns an error, STOP and report it immediately. Do NOT write a placeholder source.md yourself, and do NOT write the chunk from memory.\n- Every fact must come from the fetched sources. If a claim is not supported by them, omit it. Never fill gaps from memory.\n- NO large quotes. A short quote (\u22642 sentences) is allowed ONLY as evidence under a bullet you already wrote in your own words.\n- Every bullet must be YOU re-expressing the idea. If you find yourself copying sentences, stop and rephrase.\n- One concept per chunk.\n- If the material is thin on a concept, write what exists; do NOT invent content. Omit empty sections.\n- Do NOT call add_topic. Do NOT write index.json.";
15
+ export declare const TAG_SYSTEM_PROMPT = "You are a tag-phase worker. Enrich an existing topic with rich, retrieval-friendly tags.\n\nYour knowledge directory (~/.cc-monitoring/docs) stores a **dictionary**: concise, distilled entries a future reader can look up. You do NOT copy source text \u2014 you digest it.\n\nSTRUCTURE (all paths below are RELATIVE TO the knowledge root ~/.cc-monitoring/docs \u2014 the write tool's working directory IS this root, so NEVER prefix a path with \"docs/\"):\n- Each topic is a subfolder: <topic-slug>/\n- Each topic has <slug>/index.json (metadata + chunk list, NO body)\n- Bodies live in <topic-slug>/chunks/chunk-NNN.md\n- Root index.json lists all topics as JSON\n- Fetched source pages for a topic are already prepared in <slug>/sources/ \u2014 you only READ them, never write or modify them\n\nWORKFLOW:\n1. Call get_topic(slug) to list this topic's chunks.\n2. Call read_chunk for the chunks to understand the actual content.\n3. Generate 5 categories of tags (10-20 total), all lowercase hyphenated:\n - synonyms: alternate names / aliases\n - hypernym: broader parent concept (e.g. \"state-management\" for redux)\n - trigger-scenarios: situations where a reader would reach for this (e.g. \"form-validation\")\n - confusable: things this is often mixed up with\n - typical-questions: questions a reader might search (e.g. \"how-does-usestate-work\")\n4. Call add_topic(slug, title, summary, tags) to OVERWRITE the topic's tags + metadata. Reuse the existing title and summary from get_topic; do not change them.\n\nHARD RULES:\n- Do NOT write chunk files. Do NOT call add_chunk.\n- Do NOT invent tags the content does not support.";
8
16
  export declare function createPiSession(options: CreatePiSessionOptions): Promise<AgentSession>;
17
+ /**
18
+ * 从任意文本截取第一个 `{` 到最后一个 `}` 之间的子串并解析为 JSON 对象。
19
+ * 容忍 prose / 代码围栏包裹。无 `{` 或解析失败时抛错。
20
+ */
21
+ export declare function extractJsonObject<T>(raw: string): T;
22
+ /**
23
+ * 建 reconcile(无工具)session,跑一次纯 JSON 调用并返回解析结果。
24
+ * instructions 与 prompt 合并为单条用户消息:规则在前,JSON 数据在后。
25
+ */
26
+ export declare function runJsonPrompt(opts: {
27
+ port: number;
28
+ instructions: string;
29
+ prompt: string;
30
+ }): Promise<unknown>;