@cc-monitoring/proxy-core 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/__tests__/commands.test.js +20 -1
- package/dist/cli/commands/exec.js +31 -42
- package/dist/cli/commands/repair.d.ts +1 -0
- package/dist/cli/commands/repair.js +15 -0
- package/dist/cli/index.js +30 -0
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.B9A39uFv.js → app.g7N9jkzn.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.IHxQqfJH.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DdhC696L.js → VPLocalSearchBox.BHwI475_.js} +1 -1
- package/dist/docs/assets/chunks/{theme.CfB2tOFi.js → theme.FhAJSNDh.js} +2 -2
- package/dist/docs/assets/{proxy-cli_data-hooks.md.w9Oe1OD3.js → proxy-cli_data-hooks.md.Bz8CVbxO.js} +1 -1
- package/dist/docs/assets/{proxy-core_ui-routes.md.Dyqkeoiv.js → proxy-core_ui-routes.md.B21t1p7R.js} +1 -1
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/index.html +3 -3
- package/dist/docs/overview.html +3 -3
- package/dist/docs/packages-utils.html +3 -3
- package/dist/docs/proxy-admin/env-and-build.html +3 -3
- package/dist/docs/proxy-admin/index.html +3 -3
- package/dist/docs/proxy-admin/layout-and-menu.html +3 -3
- package/dist/docs/proxy-admin/pages.html +3 -3
- package/dist/docs/proxy-admin/routing-and-auth.html +3 -3
- package/dist/docs/proxy-admin/services-and-mock.html +3 -3
- package/dist/docs/proxy-cli/api-layer.html +3 -3
- package/dist/docs/proxy-cli/app-shell.html +3 -3
- package/dist/docs/proxy-cli/components-common.html +3 -3
- package/dist/docs/proxy-cli/components-config.html +3 -3
- package/dist/docs/proxy-cli/components-requests.html +3 -3
- package/dist/docs/proxy-cli/components-stats.html +3 -3
- package/dist/docs/proxy-cli/components-status.html +3 -3
- package/dist/docs/proxy-cli/data-hooks.html +5 -5
- package/dist/docs/proxy-cli/index.html +3 -3
- package/dist/docs/proxy-cli/utils-and-i18n.html +3 -3
- package/dist/docs/proxy-core/chat-api.html +3 -3
- package/dist/docs/proxy-core/cli.html +3 -3
- package/dist/docs/proxy-core/config.html +3 -3
- package/dist/docs/proxy-core/data-layer.html +3 -3
- package/dist/docs/proxy-core/entry.html +3 -3
- package/dist/docs/proxy-core/index.html +3 -3
- package/dist/docs/proxy-core/pm2.html +3 -3
- package/dist/docs/proxy-core/providers.html +3 -3
- package/dist/docs/proxy-core/proxy.html +3 -3
- package/dist/docs/proxy-core/stats.html +3 -3
- package/dist/docs/proxy-core/tool.html +3 -3
- package/dist/docs/proxy-core/ui-routes.html +5 -5
- package/dist/docs/proxy-core/utilities.html +3 -3
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/request-flow.html +3 -3
- package/dist/logger/index.d.ts +0 -3
- package/dist/logger/index.js +0 -1
- package/dist/mcp-server/tools.js +8 -9
- package/dist/server/__tests__/data-push.test.js +44 -0
- package/dist/server/__tests__/providers-route.test.js +1 -0
- package/dist/server/__tests__/proxy.test.js +281 -2
- package/dist/server/__tests__/server.test.js +15 -10
- package/dist/server/__tests__/ui-route.test.js +43 -0
- package/dist/server/auth.d.ts +0 -1
- package/dist/server/auth.js +1 -1
- package/dist/server/chat-route.js +48 -162
- package/dist/server/data-push.d.ts +2 -1
- package/dist/server/data-push.js +22 -7
- package/dist/server/index.js +4 -3
- package/dist/server/proxy.js +193 -229
- package/dist/server/ui-route.js +84 -60
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +1 -1
- package/dist/tools/registry.d.ts +0 -4
- package/dist/tools/registry.js +0 -8
- package/dist/types/config.d.ts +0 -13
- package/dist/types/pm2.d.ts +1 -2
- package/dist/ui/assets/{1c-DAu68mP4.js → 1c-CaPSZBmB.js} +1 -1
- package/dist/ui/assets/{abnf-Cu8RHCHK.js → abnf-DBDOsmne.js} +1 -1
- package/dist/ui/assets/{abnfDiagram-VRR7QNED-BUBToPXF.js → abnfDiagram-VRR7QNED-D8zK__Mj.js} +1 -1
- package/dist/ui/assets/{accesslog-BG-34XOy.js → accesslog-BOLs2Kig.js} +1 -1
- package/dist/ui/assets/{actionscript-iw0HHMGM.js → actionscript-BZYKhS1B.js} +1 -1
- package/dist/ui/assets/{ada-qRqj6VGQ.js → ada-DyacnMpg.js} +1 -1
- package/dist/ui/assets/{angelscript-BeaXyx_P.js → angelscript-CAN6j0H3.js} +1 -1
- package/dist/ui/assets/{apache-CU8d-z9X.js → apache-BE4vouiQ.js} +1 -1
- package/dist/ui/assets/{applescript-d1Wxkqz1.js → applescript-CS88I1yz.js} +1 -1
- package/dist/ui/assets/{arc-BMsPIm3j.js → arc-CTMmdrSV.js} +1 -1
- package/dist/ui/assets/{arcade-CtbgrWTM.js → arcade-B0f0f5SD.js} +1 -1
- package/dist/ui/assets/{architectureDiagram-ZJ3FMSHR-CVjC5TrS.js → architectureDiagram-ZJ3FMSHR-Dtvpnopp.js} +1 -1
- package/dist/ui/assets/{arduino-Bc9L39Hr.js → arduino-Bhm-OSb2.js} +1 -1
- package/dist/ui/assets/{armasm-DuWmpjWR.js → armasm-CEy-mDHc.js} +1 -1
- package/dist/ui/assets/{asciidoc-CDIhFTnx.js → asciidoc-CrZqQBTj.js} +1 -1
- package/dist/ui/assets/{aspectj-SYj-57Es.js → aspectj-B4IlFyyJ.js} +1 -1
- package/dist/ui/assets/{autohotkey-hBi5dq37.js → autohotkey-Cihy-FjA.js} +1 -1
- package/dist/ui/assets/{autoit-BSawXzhg.js → autoit-Dis_JVJq.js} +1 -1
- package/dist/ui/assets/{avrasm-CwYom8Np.js → avrasm-CVhMycHj.js} +1 -1
- package/dist/ui/assets/{awk-BvBRfGo2.js → awk-BCViwLf5.js} +1 -1
- package/dist/ui/assets/{axapta-CqUavA8k.js → axapta-pWB4JVB_.js} +1 -1
- package/dist/ui/assets/{bash-BS_ZnmEu.js → bash-B6Giryub.js} +1 -1
- package/dist/ui/assets/{basic-xbP4IXrN.js → basic-DcrjcHB0.js} +1 -1
- package/dist/ui/assets/{blockDiagram-677ZJIJ3-CmpI3f5p.js → blockDiagram-677ZJIJ3-DfhtgI1r.js} +1 -1
- package/dist/ui/assets/{bnf-BECwu6uW.js → bnf-cpKU0967.js} +1 -1
- package/dist/ui/assets/{brainfuck-QQgu4j4N.js → brainfuck-CFFdk4cM.js} +1 -1
- package/dist/ui/assets/{coq-IDMIFfem.js → c-CW6KPMeI.js} +1 -1
- package/dist/ui/assets/{c-like-DYrFOtXy.js → c-like-CWn59vrg.js} +1 -1
- package/dist/ui/assets/{c4Diagram-LMCZKHZV-B6Hgngz9.js → c4Diagram-LMCZKHZV-D1Oh6k37.js} +1 -1
- package/dist/ui/assets/{cal-CNMrJ6v5.js → cal-8i26_L39.js} +1 -1
- package/dist/ui/assets/{capnproto-DYCKl6oY.js → capnproto-CviwnFBf.js} +1 -1
- package/dist/ui/assets/{ceylon-mb8tRPl0.js → ceylon-CQyc4rWs.js} +1 -1
- package/dist/ui/assets/channel-Da2MvpNG.js +1 -0
- package/dist/ui/assets/{chunk-2Q5K7J3B-LxvQ-G67.js → chunk-2Q5K7J3B-oswPBwIn.js} +1 -1
- package/dist/ui/assets/{chunk-32BRIVSS-DxzKK6Aw.js → chunk-32BRIVSS-B5pU_9b9.js} +1 -1
- package/dist/ui/assets/{chunk-5VM5RSS4-CZEoYJ2W.js → chunk-5VM5RSS4-gvtfMc4w.js} +1 -1
- package/dist/ui/assets/{chunk-EX3LRPZG-DS2PytrN.js → chunk-EX3LRPZG-BkBaDMy4.js} +1 -1
- package/dist/ui/assets/{chunk-JWPE2WC7-UX0Sr1Ie.js → chunk-JWPE2WC7-Ch-C75ar.js} +1 -1
- package/dist/ui/assets/{chunk-MOJQB5TN-YbJgT9t4.js → chunk-MOJQB5TN-BfYhj1jN.js} +1 -1
- package/dist/ui/assets/{chunk-RYQCIY6F-DS2VH_U9.js → chunk-RYQCIY6F-D8izfruP.js} +1 -1
- package/dist/ui/assets/{chunk-V7JOEXUC-CZr0pkI1.js → chunk-V7JOEXUC-CbzHnW90.js} +1 -1
- package/dist/ui/assets/{chunk-VR4S4FIN-50opPAD3.js → chunk-VR4S4FIN-Dr4M5qZA.js} +1 -1
- package/dist/ui/assets/{chunk-XXDRQBXY-DAAX9l7U.js → chunk-XXDRQBXY-QE-R8dRe.js} +1 -1
- package/dist/ui/assets/classDiagram-OUVF2IWQ-mHUiWjcC.js +1 -0
- package/dist/ui/assets/classDiagram-v2-EOCWNBFH-mHUiWjcC.js +1 -0
- package/dist/ui/assets/{clean-C4X7dSkh.js → clean-DZeAtQ7H.js} +1 -1
- package/dist/ui/assets/{clojure-DSg9gUa7.js → clojure-U4ebZ7NQ.js} +1 -1
- package/dist/ui/assets/{clojure-repl-CagRYx7h.js → clojure-repl-B4QSIzUI.js} +1 -1
- package/dist/ui/assets/{cmake-CFdBn53c.js → cmake-UHexZySb.js} +1 -1
- package/dist/ui/assets/{coffeescript-CJZtMOPx.js → coffeescript-Dg56H9Mr.js} +1 -1
- package/dist/ui/assets/{c-BRJEPYra.js → coq-C1g3mm0X.js} +1 -1
- package/dist/ui/assets/{cos-Bx2VJuzG.js → cos-BL4DdyGh.js} +1 -1
- package/dist/ui/assets/{cose-bilkent-JH36ORCC-zWRLsZpZ.js → cose-bilkent-JH36ORCC-BHQslHP3.js} +1 -1
- package/dist/ui/assets/{cpp-CsG6DlC4.js → cpp-keZI-XAd.js} +1 -1
- package/dist/ui/assets/{crmsh-DTy9MnmJ.js → crmsh-DdXYVeeA.js} +1 -1
- package/dist/ui/assets/{crystal-BwgrLrZ1.js → crystal-C4AN0m0I.js} +1 -1
- package/dist/ui/assets/{csharp-B2VeTPAF.js → csharp-COUyKsNR.js} +1 -1
- package/dist/ui/assets/{csp-CTpydNhH.js → csp-DBc-rgSJ.js} +1 -1
- package/dist/ui/assets/{css-B0mMUbpY.js → css-B8m6O_Pw.js} +1 -1
- package/dist/ui/assets/{cynefin-VYW2F7L2-BmjQEj6q.js → cynefin-VYW2F7L2-B3L-WcKn.js} +1 -1
- package/dist/ui/assets/{cynefinDiagram-TSTJHNR4-Dr0Zrke0.js → cynefinDiagram-TSTJHNR4-fzaM4qcZ.js} +1 -1
- package/dist/ui/assets/{d-DjuDZnbI.js → d-dgQN4Rko.js} +1 -1
- package/dist/ui/assets/{dagre-VKFMJZFB-xoTPT2Uu.js → dagre-VKFMJZFB-DJHj16mR.js} +1 -1
- package/dist/ui/assets/{dart-xR3GU9TJ.js → dart-D2Y7LOq-.js} +1 -1
- package/dist/ui/assets/{delphi-bJas5QnG.js → delphi-DaGcSk5A.js} +1 -1
- package/dist/ui/assets/{diagram-FQU43EPY-rL_IU7gU.js → diagram-FQU43EPY-iZEZ1f-R.js} +1 -1
- package/dist/ui/assets/{diagram-G47NLZAW-EcDiCVGj.js → diagram-G47NLZAW-rkQb3r-C.js} +1 -1
- package/dist/ui/assets/{diagram-NH7WQ7WH-CGGXOjev.js → diagram-NH7WQ7WH-B4Fy72tP.js} +1 -1
- package/dist/ui/assets/{diagram-OA4YK3LP-DnE7hDjD.js → diagram-OA4YK3LP-BndmuIBq.js} +1 -1
- package/dist/ui/assets/{diagram-WEI45ONY-CTJH5eD8.js → diagram-WEI45ONY-CwlAiqOe.js} +1 -1
- package/dist/ui/assets/{diff-doJFF3fv.js → diff-prcRV1Y3.js} +1 -1
- package/dist/ui/assets/{django-D3b-owa_.js → django-B1zIoGSx.js} +1 -1
- package/dist/ui/assets/{dns-C42KYV-Z.js → dns-ZxI_aTwc.js} +1 -1
- package/dist/ui/assets/{dockerfile-9KUINc2j.js → dockerfile-Dp_fT6E-.js} +1 -1
- package/dist/ui/assets/{dos-CxnlJ6qp.js → dos-Cuu5c8vv.js} +1 -1
- package/dist/ui/assets/{dsconfig-6CMMCwmY.js → dsconfig-DcGTOhbS.js} +1 -1
- package/dist/ui/assets/{dts-D78rdUIB.js → dts-DCF8VaRk.js} +1 -1
- package/dist/ui/assets/{dust-Dv1uTfJU.js → dust-DeCmZWMK.js} +1 -1
- package/dist/ui/assets/{ebnf-BGbG1cFK.js → ebnf-BHQQcuF_.js} +1 -1
- package/dist/ui/assets/{ebnfDiagram-CCIWWBDH-z2VgRSUV.js → ebnfDiagram-CCIWWBDH-DJ_RuhTm.js} +1 -1
- package/dist/ui/assets/{elixir-ZgAQVY1J.js → elixir-BHmweJ4d.js} +1 -1
- package/dist/ui/assets/{elm-CudiFuNu.js → elm-v76Hd2B3.js} +1 -1
- package/dist/ui/assets/{erDiagram-Q63AITRT-X1TODuRv.js → erDiagram-Q63AITRT-DVZkY5RZ.js} +1 -1
- package/dist/ui/assets/{erb-Bz_NZh6W.js → erb-xvWF5bfx.js} +1 -1
- package/dist/ui/assets/{erlang-DNuj1nb2.js → erlang-CKBMURym.js} +1 -1
- package/dist/ui/assets/{erlang-repl-SP1Gan9W.js → erlang-repl-BjcfXt3Z.js} +1 -1
- package/dist/ui/assets/{excel-0K77uECF.js → excel-Cdrtxhml.js} +1 -1
- package/dist/ui/assets/{fix-CalJq7JD.js → fix-CB-So5So.js} +1 -1
- package/dist/ui/assets/{flix-BlIs11_w.js → flix-VM9AOrq6.js} +1 -1
- package/dist/ui/assets/{flowDiagram-23GEKE2U-DA2dnmc0.js → flowDiagram-23GEKE2U-vyGW67Xm.js} +1 -1
- package/dist/ui/assets/{fortran-ZCobXY2R.js → fortran-CcwJVO8H.js} +1 -1
- package/dist/ui/assets/{fsharp-Be8rwUtc.js → fsharp-DiATpw1u.js} +1 -1
- package/dist/ui/assets/{gams-DUat8frQ.js → gams-Csg9YNPz.js} +1 -1
- package/dist/ui/assets/{ganttDiagram-NO4QXBWP-DdFwaIGZ.js → ganttDiagram-NO4QXBWP-C2TRbwLw.js} +1 -1
- package/dist/ui/assets/{gauss-BB4U88dy.js → gauss-Bc4TC8Wh.js} +1 -1
- package/dist/ui/assets/{gcode-DzeUZuZg.js → gcode-Rig_2OoA.js} +1 -1
- package/dist/ui/assets/{gherkin-B_8vW_BO.js → gherkin-ByBU06QB.js} +1 -1
- package/dist/ui/assets/{gitGraphDiagram-IHSO6WYX-B-Dn8x6I.js → gitGraphDiagram-IHSO6WYX-CEiqfFIF.js} +1 -1
- package/dist/ui/assets/{glsl-DGHGjPC1.js → glsl-C8D6y2Tn.js} +1 -1
- package/dist/ui/assets/{gml-BYEku8Yh.js → gml-PHpGPHbT.js} +1 -1
- package/dist/ui/assets/{go-D8aSgQMc.js → go-BL_o_3ez.js} +1 -1
- package/dist/ui/assets/{golo-CDjCU_jh.js → golo-CWQ6dTUz.js} +1 -1
- package/dist/ui/assets/{gradle-BeUw7tl_.js → gradle-Y_I2KN2z.js} +1 -1
- package/dist/ui/assets/{groovy-5iCQOtR3.js → groovy-JnIv8p2l.js} +1 -1
- package/dist/ui/assets/{haml-BEdL8FJi.js → haml-B8W_h6mZ.js} +1 -1
- package/dist/ui/assets/{handlebars-BuYQNzoK.js → handlebars-DVm8mJuD.js} +1 -1
- package/dist/ui/assets/{haskell-I4FCBcW0.js → haskell-DlDi2Ty7.js} +1 -1
- package/dist/ui/assets/{haxe-yigyKfFr.js → haxe-CftFNVE-.js} +1 -1
- package/dist/ui/assets/{hsp-ZUk4j7d1.js → hsp-C67xnq9C.js} +1 -1
- package/dist/ui/assets/{htmlbars-QYP3lT3u.js → htmlbars-CmJCm67U.js} +1 -1
- package/dist/ui/assets/{http-BJpD1O71.js → http-b-FPEcHP.js} +1 -1
- package/dist/ui/assets/{hy-CIJ1bP6S.js → hy-BWD3ncpN.js} +1 -1
- package/dist/ui/assets/{index-COAgrx1J.js → index-C7s1zgJb.js} +242 -242
- package/dist/ui/assets/{index-BDXWttnT.js → index-D2UBwfSG.js} +3 -3
- package/dist/ui/assets/index-DlsVXaHT.css +10 -0
- package/dist/ui/assets/{infoDiagram-FWYZ7A6U-fTg9eLNt.js → infoDiagram-FWYZ7A6U-C0Px17IN.js} +1 -1
- package/dist/ui/assets/{inform7-DAsu-lC2.js → inform7-C-OYaMO5.js} +1 -1
- package/dist/ui/assets/{ini-Bhz-zHCg.js → ini-CVyYmykw.js} +1 -1
- package/dist/ui/assets/{irpf90-BunhbwBl.js → irpf90-BcpjWXIz.js} +1 -1
- package/dist/ui/assets/{isbl-q9L6hOhP.js → isbl-ZraBBeEr.js} +1 -1
- package/dist/ui/assets/{ishikawaDiagram-FXEZZL3T-B8G0sdgd.js → ishikawaDiagram-FXEZZL3T-BjmTMgpO.js} +1 -1
- package/dist/ui/assets/{java-Iks5Pkau.js → java-D_mE2DT6.js} +1 -1
- package/dist/ui/assets/{javascript-C4vltXPw.js → javascript-akXESsox.js} +1 -1
- package/dist/ui/assets/{jboss-cli-BQBvd2X2.js → jboss-cli-CFe3gTDt.js} +1 -1
- package/dist/ui/assets/{journeyDiagram-5HDEW3XC-Crbzgrum.js → journeyDiagram-5HDEW3XC-BpgJUvs6.js} +1 -1
- package/dist/ui/assets/{json-DXK0_jUK.js → json-sjN7AzRC.js} +1 -1
- package/dist/ui/assets/{julia-CCYoBiYK.js → julia-BJJYbUMV.js} +1 -1
- package/dist/ui/assets/{julia-repl-y8v2Oorl.js → julia-repl-BwruD8Ix.js} +1 -1
- package/dist/ui/assets/{kanban-definition-HUTT4EX6-C8sCOsBX.js → kanban-definition-HUTT4EX6-DFlE9edA.js} +1 -1
- package/dist/ui/assets/{kotlin-Bnjk7_fw.js → kotlin-CAIQsLCF.js} +1 -1
- package/dist/ui/assets/{lasso-B-al6x63.js → lasso-sU67h-5u.js} +1 -1
- package/dist/ui/assets/{latex-BUmqlb9r.js → latex-CVX-jP88.js} +1 -1
- package/dist/ui/assets/{ldif-D42RWj6Q.js → ldif-DGM9xbFZ.js} +1 -1
- package/dist/ui/assets/{leaf-CrH4BZ0m.js → leaf-AlB_zmwz.js} +1 -1
- package/dist/ui/assets/{less-upmRlQQW.js → less-CKwfEdZQ.js} +1 -1
- package/dist/ui/assets/{lisp-DHYS22SA.js → lisp-CXYLaAPw.js} +1 -1
- package/dist/ui/assets/{livecodeserver-CeQNmFP3.js → livecodeserver-C02fGGTS.js} +1 -1
- package/dist/ui/assets/{livescript-PJWpY1JI.js → livescript-CBMa8QF_.js} +1 -1
- package/dist/ui/assets/{llvm-BKtKWwCt.js → llvm-WXTIohTC.js} +1 -1
- package/dist/ui/assets/{lsl-RWRLRjk7.js → lsl-4obd2U_I.js} +1 -1
- package/dist/ui/assets/{lua-BFUDiPGm.js → lua-DTSy-TjF.js} +1 -1
- package/dist/ui/assets/{makefile-CUDyOz5D.js → makefile-Bf2UEO0i.js} +1 -1
- package/dist/ui/assets/{markdown-zZCLypc6.js → markdown-BgoGmFfJ.js} +1 -1
- package/dist/ui/assets/{mathematica-BHbxKxnq.js → mathematica-CSiA8KQh.js} +1 -1
- package/dist/ui/assets/{matlab-DlGtg--p.js → matlab-DoMvLsGB.js} +1 -1
- package/dist/ui/assets/{maxima-BBBeS3Ra.js → maxima-BFO4dfZO.js} +1 -1
- package/dist/ui/assets/{mel-nh8j7W_6.js → mel-DyBpmDxt.js} +1 -1
- package/dist/ui/assets/{mercury-DyyD-pqr.js → mercury-OL5G5uU6.js} +1 -1
- package/dist/ui/assets/{mindmap-definition-LN4V7U3C-CJlhDHqM.js → mindmap-definition-LN4V7U3C-s-nUZuCs.js} +1 -1
- package/dist/ui/assets/{mipsasm-hiEhRRiq.js → mipsasm-KQwdm39j.js} +1 -1
- package/dist/ui/assets/{mizar-BZa3iAAL.js → mizar-BqndJ30I.js} +1 -1
- package/dist/ui/assets/{mojolicious-BCIm2V_y.js → mojolicious-Bvc1uJd-.js} +1 -1
- package/dist/ui/assets/{monkey-zmK-7N8b.js → monkey-Dl_gLm7-.js} +1 -1
- package/dist/ui/assets/{moonscript-BsS_Mn3D.js → moonscript-BL6R6eAz.js} +1 -1
- package/dist/ui/assets/{n1ql-D7xVgDP0.js → n1ql-C09iOJfQ.js} +1 -1
- package/dist/ui/assets/{nginx-ct2q4dtd.js → nginx-C7W01nBr.js} +1 -1
- package/dist/ui/assets/{nim-RO0UOmW3.js → nim-Dj78szvD.js} +1 -1
- package/dist/ui/assets/{nix-BcRJxPKH.js → nix-BOtGyPmd.js} +1 -1
- package/dist/ui/assets/{node-repl-DgIefwxW.js → node-repl-19nZvZ4A.js} +1 -1
- package/dist/ui/assets/{nsis-DqHs9QhB.js → nsis-ByCl1zIm.js} +1 -1
- package/dist/ui/assets/{objectivec-BBcWqc7Y.js → objectivec-BhdaT_Jr.js} +1 -1
- package/dist/ui/assets/{ocaml-BExfw7D6.js → ocaml-D_NXvSO7.js} +1 -1
- package/dist/ui/assets/{openscad-CHPRELQb.js → openscad-DOhagvnA.js} +1 -1
- package/dist/ui/assets/{oxygene-DpS9uMJW.js → oxygene-5BnkqMRH.js} +1 -1
- package/dist/ui/assets/{parser3-CjJ_QdBp.js → parser3-jSWlxi8m.js} +1 -1
- package/dist/ui/assets/{pegDiagram-2B236MQR-GM70woGy.js → pegDiagram-2B236MQR-CideH-XT.js} +1 -1
- package/dist/ui/assets/{perl-BSNM2Kt8.js → perl-CfsqjZ4b.js} +1 -1
- package/dist/ui/assets/{pf-Z-hKf_88.js → pf-kOewxO29.js} +1 -1
- package/dist/ui/assets/{pgsql-DDgznxBg.js → pgsql-CXm2Xd-Z.js} +1 -1
- package/dist/ui/assets/{php-BzAhxF-l.js → php-CRiA_dH8.js} +1 -1
- package/dist/ui/assets/{php-template-DkgcKHRc.js → php-template-ByMrxqSd.js} +1 -1
- package/dist/ui/assets/{pieDiagram-ENE6RG2P-Bst7mPyz.js → pieDiagram-ENE6RG2P-CJkCdB38.js} +1 -1
- package/dist/ui/assets/{plaintext-BYEppD0R.js → plaintext-BJx0R6A5.js} +1 -1
- package/dist/ui/assets/{pony-BT_kQd1K.js → pony-CozCHtz4.js} +1 -1
- package/dist/ui/assets/{powershell-BfRsuSsf.js → powershell-BT7gMMgn.js} +1 -1
- package/dist/ui/assets/{processing-DpzWe5Iu.js → processing-FOIxn_W_.js} +1 -1
- package/dist/ui/assets/{profile-BCOhS5cM.js → profile-BsoUuD9w.js} +1 -1
- package/dist/ui/assets/{prolog-OxaCCaW8.js → prolog-Bd3gvQ2N.js} +1 -1
- package/dist/ui/assets/{properties-DMFlA2Ca.js → properties-BWGFdny9.js} +1 -1
- package/dist/ui/assets/{protobuf-CRDFkXvZ.js → protobuf-pQSKoOOY.js} +1 -1
- package/dist/ui/assets/{puppet-DnrVyLzx.js → puppet-DnEN_mgS.js} +1 -1
- package/dist/ui/assets/{purebasic-Dht4Hniv.js → purebasic-BqoOGoRw.js} +1 -1
- package/dist/ui/assets/{python-B0aMirWu.js → python-TeVYomkE.js} +1 -1
- package/dist/ui/assets/{python-repl-BlYDBGa7.js → python-repl-zqu5igFS.js} +1 -1
- package/dist/ui/assets/{q-DzrtW9kT.js → q-CZC9Dltd.js} +1 -1
- package/dist/ui/assets/{qml-DnfQsR3i.js → qml-ZNInP45Q.js} +1 -1
- package/dist/ui/assets/{quadrantDiagram-ABIIQ3AL-DNRYurBT.js → quadrantDiagram-ABIIQ3AL-Dd7PwxsF.js} +1 -1
- package/dist/ui/assets/{r-DGI_ZuTD.js → r-B39DAmkC.js} +1 -1
- package/dist/ui/assets/{railroadDiagram-RFXS5EU6-CmbC3Vz4.js → railroadDiagram-RFXS5EU6-DtO5PVFZ.js} +1 -1
- package/dist/ui/assets/{reasonml-3SohMgh2.js → reasonml-B-ZWFJt_.js} +1 -1
- package/dist/ui/assets/{requirementDiagram-TGXJPOKE-8CxrXHco.js → requirementDiagram-TGXJPOKE-DihF4OTj.js} +1 -1
- package/dist/ui/assets/{rib-DfRSd4Qa.js → rib-CnGG0qMF.js} +1 -1
- package/dist/ui/assets/{roboconf-CQczGdGW.js → roboconf-Ewtfps4u.js} +1 -1
- package/dist/ui/assets/{routeros-DCka-T2i.js → routeros-CPcmP1c7.js} +1 -1
- package/dist/ui/assets/{rsl-Dr8MOwMo.js → rsl-NbjWFbPH.js} +1 -1
- package/dist/ui/assets/{ruby-C2zFSkh_.js → ruby-DWDdy5yE.js} +1 -1
- package/dist/ui/assets/{ruleslanguage-C97YsgQq.js → ruleslanguage-Cv_DZe2r.js} +1 -1
- package/dist/ui/assets/{rust-H3h8kd9A.js → rust-NZnsfER5.js} +1 -1
- package/dist/ui/assets/{sankeyDiagram-HTMAVEWB-DBXLWjEq.js → sankeyDiagram-HTMAVEWB-D6i-Mzte.js} +1 -1
- package/dist/ui/assets/{sas-04z0Xu8P.js → sas-C4wv0P6G.js} +1 -1
- package/dist/ui/assets/{scala-DyB9Aoiv.js → scala-DUdTOIgx.js} +1 -1
- package/dist/ui/assets/{scheme-DBj6nxUi.js → scheme-DEdFa14t.js} +1 -1
- package/dist/ui/assets/{scilab-Btj7AD9s.js → scilab-xY51J2bR.js} +1 -1
- package/dist/ui/assets/{scss-BXZJyXt7.js → scss-BEYp1sXc.js} +1 -1
- package/dist/ui/assets/{sequenceDiagram-DBY2YBRQ-DXIkBFKC.js → sequenceDiagram-DBY2YBRQ-njQlqy_J.js} +1 -1
- package/dist/ui/assets/{shell-BsreQR1Z.js → shell-fq6bkhOw.js} +1 -1
- package/dist/ui/assets/{sizeCapture-X5ZJPWSS-ocS9jxAQ.js → sizeCapture-X5ZJPWSS-tLn70-Fb.js} +1 -1
- package/dist/ui/assets/{smali-D9wQw9zm.js → smali-CsSAuSYg.js} +1 -1
- package/dist/ui/assets/{smalltalk-Dku6G_H3.js → smalltalk-DJ7zrd87.js} +1 -1
- package/dist/ui/assets/{sml-BknyU6ya.js → sml-CnDwl0nH.js} +1 -1
- package/dist/ui/assets/{sqf-DRYMaOg8.js → sqf-Cc2SX4Zy.js} +1 -1
- package/dist/ui/assets/{sql-Cw3Ax4KA.js → sql-DUQA_V_4.js} +1 -1
- package/dist/ui/assets/{sql_more-vWdslLE0.js → sql_more-BHoH-8oO.js} +1 -1
- package/dist/ui/assets/{stan-8XH5bDS6.js → stan-D-7F5jH6.js} +1 -1
- package/dist/ui/assets/{stata-4e77wgfe.js → stata-xKD_DnDE.js} +1 -1
- package/dist/ui/assets/{stateDiagram-2N3HPSRC-RMmL9jMG.js → stateDiagram-2N3HPSRC-B4O8weor.js} +1 -1
- package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-CO881_ht.js +1 -0
- package/dist/ui/assets/{step21-ByIeDMY3.js → step21-obc_kzQY.js} +1 -1
- package/dist/ui/assets/{stylus-ZAhJyWsw.js → stylus-CkAUSRd-.js} +1 -1
- package/dist/ui/assets/{subunit-pPW2UGkj.js → subunit-BDv8PGo1.js} +1 -1
- package/dist/ui/assets/{swift-CX3BB5az.js → swift-CHsYyW-p.js} +1 -1
- package/dist/ui/assets/{swimlanes-5IMT3BWC-C2zAuJ56.js → swimlanes-5IMT3BWC-DSr9Ty4A.js} +2 -2
- package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DFMCDs8b.js +8 -0
- package/dist/ui/assets/{taggerscript-BHcjbWIC.js → taggerscript-C_2JQgO9.js} +1 -1
- package/dist/ui/assets/{tap-BOl1lBlS.js → tap-Bi497Z2c.js} +1 -1
- package/dist/ui/assets/{tcl-DZjeOBDh.js → tcl-B1XMvLaD.js} +1 -1
- package/dist/ui/assets/{thrift-BxboWg4x.js → thrift-D9X0Hmmc.js} +1 -1
- package/dist/ui/assets/{timeline-definition-FHXFAJF6-BOxsxyq_.js → timeline-definition-FHXFAJF6-C4_gj50B.js} +1 -1
- package/dist/ui/assets/{tp-BNM6ql3J.js → tp-CJG4Odbx.js} +1 -1
- package/dist/ui/assets/{twig-Dj9ZiXD4.js → twig-flj72_wc.js} +1 -1
- package/dist/ui/assets/{typescript-7MEJlu_6.js → typescript-CWPwVoLd.js} +1 -1
- package/dist/ui/assets/{vala-DNqOAgHJ.js → vala-LuCNWNuU.js} +1 -1
- package/dist/ui/assets/{vbnet-T0mNKVc_.js → vbnet-CGUT6ss0.js} +1 -1
- package/dist/ui/assets/{vbscript-CeuwVMAI.js → vbscript-CNiUBJhn.js} +1 -1
- package/dist/ui/assets/{vbscript-html-BbJSt2w6.js → vbscript-html-CJGgjjbc.js} +1 -1
- package/dist/ui/assets/{vennDiagram-L72KCM5P-BX9mWeiT.js → vennDiagram-L72KCM5P-BxcAUnYo.js} +1 -1
- package/dist/ui/assets/{verilog-DYuhYfkX.js → verilog-C4f9ZBTK.js} +1 -1
- package/dist/ui/assets/{vhdl-Cf9aT-t7.js → vhdl-CyDQIZve.js} +1 -1
- package/dist/ui/assets/{vim-DciP44K1.js → vim-XAUBqa0M.js} +1 -1
- package/dist/ui/assets/{wardleyDiagram-EHGQE667-CDj2rOzu.js → wardleyDiagram-EHGQE667-DlwSH77q.js} +1 -1
- package/dist/ui/assets/{x86asm-E-AN_LXO.js → x86asm-Cp6vHuUx.js} +1 -1
- package/dist/ui/assets/{xl-CxYLJelN.js → xl-BHgDofIM.js} +1 -1
- package/dist/ui/assets/{xml-yz1SRLuU.js → xml-QloVn4s_.js} +1 -1
- package/dist/ui/assets/{xquery-BLzBF3tV.js → xquery-spJZLmyM.js} +1 -1
- package/dist/ui/assets/{xychartDiagram-FW5EYKEG-Czapk9-Z.js → xychartDiagram-FW5EYKEG-BxGVZcnb.js} +1 -1
- package/dist/ui/assets/{yaml-Cv4Y7iN_.js → yaml-CUju4iq0.js} +1 -1
- package/dist/ui/assets/{zephir-KRcdQfEX.js → zephir-ChVpmD0Y.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/utils/__tests__/abort-signals.test.js +67 -0
- package/dist/utils/__tests__/db-maintenance.test.js +55 -0
- package/dist/utils/__tests__/db-migration.test.js +79 -1
- package/dist/utils/__tests__/inject-loop.test.js +1 -53
- package/dist/utils/__tests__/learn-tasks-db.test.js +82 -0
- package/dist/utils/__tests__/openai-converter.test.js +25 -0
- package/dist/utils/__tests__/pi-crawl-tools.test.js +15 -4
- package/dist/utils/__tests__/pi-dedup-reconcile.test.js +11 -9
- package/dist/utils/__tests__/pi-events.test.d.ts +1 -0
- package/dist/utils/__tests__/pi-events.test.js +172 -0
- package/dist/utils/__tests__/pi-learn-orchestrator.test.js +216 -6
- package/dist/utils/__tests__/pi-runtime-json.test.js +38 -3
- package/dist/utils/__tests__/providers-db.test.js +40 -2
- package/dist/utils/__tests__/request-writer.test.js +532 -39
- package/dist/utils/__tests__/sse-protocol.test.d.ts +1 -0
- package/dist/utils/__tests__/sse-protocol.test.js +115 -0
- package/dist/utils/__tests__/stats-aggregator.test.d.ts +1 -0
- package/dist/utils/__tests__/stats-aggregator.test.js +114 -0
- package/dist/utils/__tests__/vault.test.d.ts +1 -0
- package/dist/utils/__tests__/{knowledge-store.test.js → vault.test.js} +16 -16
- package/dist/utils/abort-signals.d.ts +13 -0
- package/dist/utils/abort-signals.js +33 -0
- package/dist/utils/db-maintenance.d.ts +8 -0
- package/dist/utils/db-maintenance.js +18 -0
- package/dist/utils/db.d.ts +2 -0
- package/dist/utils/db.js +86 -0
- package/dist/utils/esm-dirname.d.ts +0 -15
- package/dist/utils/esm-dirname.js +0 -4
- package/dist/utils/inject-loop.d.ts +0 -27
- package/dist/utils/inject-loop.js +2 -56
- package/dist/utils/learn-tasks-db.d.ts +15 -0
- package/dist/utils/learn-tasks-db.js +35 -0
- package/dist/utils/openai-converter.js +88 -78
- package/dist/utils/pi-browser-tools.d.ts +0 -2
- package/dist/utils/pi-browser-tools.js +0 -174
- package/dist/utils/pi-crawl-tools.d.ts +2 -1
- package/dist/utils/pi-crawl-tools.js +16 -11
- package/dist/utils/pi-dedup.d.ts +8 -30
- package/dist/utils/pi-dedup.js +32 -67
- package/dist/utils/pi-events.d.ts +65 -0
- package/dist/utils/pi-events.js +98 -0
- package/dist/utils/pi-learn-orchestrator.d.ts +6 -5
- package/dist/utils/pi-learn-orchestrator.js +71 -106
- package/dist/utils/pi-runtime.d.ts +5 -6
- package/dist/utils/pi-runtime.js +38 -42
- package/dist/utils/pi-sandbox-ops.d.ts +0 -36
- package/dist/utils/pi-sandbox-ops.js +5 -190
- package/dist/utils/providers-db.d.ts +3 -0
- package/dist/utils/providers-db.js +21 -7
- package/dist/utils/request-writer.d.ts +77 -26
- package/dist/utils/request-writer.js +362 -56
- package/dist/utils/sse-protocol.d.ts +34 -0
- package/dist/utils/sse-protocol.js +121 -0
- package/dist/utils/sse-stream-processor.d.ts +4 -9
- package/dist/utils/sse-stream-processor.js +13 -104
- package/dist/utils/sse-writer.d.ts +1 -1
- package/dist/utils/sse-writer.js +3 -2
- package/dist/utils/stats-aggregator.d.ts +1 -1
- package/dist/utils/stats-aggregator.js +44 -24
- package/dist/utils/tool-injector.js +7 -0
- package/dist/utils/vault.d.ts +111 -0
- package/dist/utils/vault.js +434 -0
- package/ecosystem.config.cjs +2 -1
- package/package.json +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.B6Qfxe6W.js +0 -1
- package/dist/server/middleware/__tests__/request-id.test.js +0 -28
- package/dist/server/middleware/request-id.d.ts +0 -2
- package/dist/server/middleware/request-id.js +0 -12
- package/dist/types/api.d.ts +0 -20
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.js +0 -4
- package/dist/types/log.d.ts +0 -13
- package/dist/ui/assets/channel-Bc4Td8eZ.js +0 -1
- package/dist/ui/assets/classDiagram-OUVF2IWQ-BicxhZFq.js +0 -1
- package/dist/ui/assets/classDiagram-v2-EOCWNBFH-BicxhZFq.js +0 -1
- package/dist/ui/assets/index-C0fxlU9d.css +0 -10
- package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-QvaEO5U6.js +0 -1
- package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DPgCOY0D.js +0 -8
- package/dist/utils/__tests__/sse-accumulator.test.js +0 -83
- package/dist/utils/knowledge-store.d.ts +0 -51
- package/dist/utils/knowledge-store.js +0 -241
- package/dist/utils/migrate-files-to-db.d.ts +0 -1
- package/dist/utils/migrate-files-to-db.js +0 -138
- package/dist/utils/sse-accumulator.d.ts +0 -9
- package/dist/utils/sse-accumulator.js +0 -59
- /package/dist/docs/assets/{proxy-cli_data-hooks.md.w9Oe1OD3.lean.js → proxy-cli_data-hooks.md.Bz8CVbxO.lean.js} +0 -0
- /package/dist/docs/assets/{proxy-core_ui-routes.md.Dyqkeoiv.lean.js → proxy-core_ui-routes.md.B21t1p7R.lean.js} +0 -0
- /package/dist/server/{middleware/__tests__/request-id.test.d.ts → __tests__/data-push.test.d.ts} +0 -0
- /package/dist/{types/api.js → utils/__tests__/abort-signals.test.d.ts} +0 -0
- /package/dist/{types/log.js → utils/__tests__/db-maintenance.test.d.ts} +0 -0
- /package/dist/utils/__tests__/{knowledge-store.test.d.ts → learn-tasks-db.test.d.ts} +0 -0
- /package/dist/utils/__tests__/{sse-accumulator.test.d.ts → openai-converter.test.d.ts} +0 -0
|
@@ -1,22 +1,4 @@
|
|
|
1
1
|
import { findEnabledTool } from '../tools/index.js';
|
|
2
|
-
/** 解析上游 SSE 全文 -> 事件数组(收集 data: 行的 JSON) */
|
|
3
|
-
export function parseSSEText(text) {
|
|
4
|
-
const events = [];
|
|
5
|
-
for (const line of text.split('\n')) {
|
|
6
|
-
if (line.startsWith('data:')) {
|
|
7
|
-
const d = line.slice(5).trim();
|
|
8
|
-
if (d && d !== '[DONE]') {
|
|
9
|
-
try {
|
|
10
|
-
events.push(JSON.parse(d));
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
// 非 JSON 行跳过
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return events;
|
|
19
|
-
}
|
|
20
2
|
/** 从事件数组重建有序内容块 + stop_reason + usage */
|
|
21
3
|
export function parseUpstreamEvents(events) {
|
|
22
4
|
const blocks = new Map();
|
|
@@ -82,42 +64,6 @@ function blocksToAssistantContent(blocks) {
|
|
|
82
64
|
}
|
|
83
65
|
return content;
|
|
84
66
|
}
|
|
85
|
-
function collectText(parsed) {
|
|
86
|
-
return parsed.blocks
|
|
87
|
-
.filter((b) => b.type === 'text' && b.text)
|
|
88
|
-
.map((b) => b.text)
|
|
89
|
-
.join('');
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* SSE 内部循环:命中已启用 tool -> 执行 exec -> 追加对话 -> 再调上游 -> 直到 end_turn。
|
|
93
|
-
* opts.body 会被原地追加 messages。
|
|
94
|
-
*
|
|
95
|
-
* @param opts.events 首次上游响应事件(已确认命中注入 tool)
|
|
96
|
-
* @param opts.callUpstream 用给定 body 再次调上游,返回事件数组
|
|
97
|
-
* @param opts.maxIterations 死循环护栏(tool 描述可能诱导模型反复调用)
|
|
98
|
-
*/
|
|
99
|
-
export async function runInjectLoop(opts) {
|
|
100
|
-
const maxIterations = opts.maxIterations ?? 3;
|
|
101
|
-
let parsed = parseUpstreamEvents(opts.events);
|
|
102
|
-
let iterations = 0;
|
|
103
|
-
while (iterations < maxIterations) {
|
|
104
|
-
const call = findInjectedCall(parsed);
|
|
105
|
-
if (!call || parsed.stopReason !== 'tool_use') {
|
|
106
|
-
return { text: collectText(parsed), iterations, stoppedByLimit: false };
|
|
107
|
-
}
|
|
108
|
-
const tool = findEnabledTool(call.name);
|
|
109
|
-
const result = await tool.exec(call.input);
|
|
110
|
-
opts.body.messages.push({ role: 'assistant', content: blocksToAssistantContent(parsed.blocks) });
|
|
111
|
-
opts.body.messages.push({
|
|
112
|
-
role: 'user',
|
|
113
|
-
content: [{ type: 'tool_result', tool_use_id: call.id, content: result }]
|
|
114
|
-
});
|
|
115
|
-
const nextEvents = await opts.callUpstream(opts.body);
|
|
116
|
-
parsed = parseUpstreamEvents(nextEvents);
|
|
117
|
-
iterations++;
|
|
118
|
-
}
|
|
119
|
-
return { text: collectText(parsed) || '(内部循环达到最大轮次)', iterations, stoppedByLimit: true };
|
|
120
|
-
}
|
|
121
67
|
export async function runStreamingInjectLoop(opts) {
|
|
122
68
|
const maxIterations = opts.maxIterations ?? 3;
|
|
123
69
|
let parsed = opts.initialParsed;
|
|
@@ -144,8 +90,9 @@ export async function runStreamingInjectLoop(opts) {
|
|
|
144
90
|
const { processor, statusCode } = await opts.streamAndParse(response);
|
|
145
91
|
// 保存这次迭代到 DB
|
|
146
92
|
await opts.saveIterationDB(requestId, processor, statusCode, opts.body);
|
|
147
|
-
|
|
93
|
+
// 先收尾残帧再取解析结果,保证最后一帧参与解析
|
|
148
94
|
processor.flushLeftover();
|
|
95
|
+
parsed = processor.getParsedUpstream();
|
|
149
96
|
iterations++;
|
|
150
97
|
}
|
|
151
98
|
const stoppedByLimit = iterations >= (opts.maxIterations ?? 3) &&
|
|
@@ -155,7 +102,6 @@ export async function runStreamingInjectLoop(opts) {
|
|
|
155
102
|
}
|
|
156
103
|
/**
|
|
157
104
|
* JSON 内部循环:非流式请求中命中 MCP tool -> 执行 exec -> 追加对话 -> 再调上游 -> 直到 end_turn。
|
|
158
|
-
* 与 SSE 版 runInjectLoop 对称,但处理 parsed JSON response body 而非 SSE event 数组。
|
|
159
105
|
*
|
|
160
106
|
* @param opts.initialBody 首次上游 JSON 响应(已确认命中 MCP tool)
|
|
161
107
|
* @param opts.requestBody 请求体(messages 会被原地追加)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
export interface InsertRunningArgs {
|
|
3
|
+
slug: string;
|
|
4
|
+
sourceType: 'url' | 'file';
|
|
5
|
+
label: string;
|
|
6
|
+
}
|
|
7
|
+
/** 落 running 行;撞同 slug 唯一约束时错误原样抛出(SQLITE_CONSTRAINT_UNIQUE) */
|
|
8
|
+
export declare function insertRunning(db: Database.Database, args: InsertRunningArgs): {
|
|
9
|
+
taskId: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function markCompleted(db: Database.Database, taskId: string): void;
|
|
12
|
+
export declare function markFailed(db: Database.Database, taskId: string, error: string): void;
|
|
13
|
+
export declare function markAborted(db: Database.Database, taskId: string): void;
|
|
14
|
+
/** 回收无主 running 行为 crashed(服务启动时调用),返回回收行数 */
|
|
15
|
+
export declare function recoverCrashedTasks(db: Database.Database): number;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// learn_tasks 数据层:learn 流水线状态机落库
|
|
2
|
+
// running → completed / failed / aborted;启动回收的无主 running → crashed。
|
|
3
|
+
// 同 slug 并发运行由 partial unique index idx_learn_tasks_running_slug 硬守。
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
/** 落 running 行;撞同 slug 唯一约束时错误原样抛出(SQLITE_CONSTRAINT_UNIQUE) */
|
|
6
|
+
export function insertRunning(db, args) {
|
|
7
|
+
const taskId = randomUUID();
|
|
8
|
+
db.prepare(`
|
|
9
|
+
INSERT INTO learn_tasks (task_id, slug, source_type, label, status)
|
|
10
|
+
VALUES (?, ?, ?, ?, 'running')
|
|
11
|
+
`).run(taskId, args.slug, args.sourceType, args.label);
|
|
12
|
+
return { taskId };
|
|
13
|
+
}
|
|
14
|
+
export function markCompleted(db, taskId) {
|
|
15
|
+
db.prepare(`
|
|
16
|
+
UPDATE learn_tasks SET status = 'completed', ended_at = ? WHERE task_id = ?
|
|
17
|
+
`).run(new Date().toISOString(), taskId);
|
|
18
|
+
}
|
|
19
|
+
export function markFailed(db, taskId, error) {
|
|
20
|
+
db.prepare(`
|
|
21
|
+
UPDATE learn_tasks SET status = 'failed', error = ?, ended_at = ? WHERE task_id = ?
|
|
22
|
+
`).run(error, new Date().toISOString(), taskId);
|
|
23
|
+
}
|
|
24
|
+
export function markAborted(db, taskId) {
|
|
25
|
+
db.prepare(`
|
|
26
|
+
UPDATE learn_tasks SET status = 'aborted', ended_at = ? WHERE task_id = ?
|
|
27
|
+
`).run(new Date().toISOString(), taskId);
|
|
28
|
+
}
|
|
29
|
+
/** 回收无主 running 行为 crashed(服务启动时调用),返回回收行数 */
|
|
30
|
+
export function recoverCrashedTasks(db) {
|
|
31
|
+
const info = db.prepare(`
|
|
32
|
+
UPDATE learn_tasks SET status = 'crashed', ended_at = ? WHERE status = 'running'
|
|
33
|
+
`).run(new Date().toISOString());
|
|
34
|
+
return info.changes;
|
|
35
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Transform } from 'stream';
|
|
2
|
+
import { createSSEDecoder, encodeSSEFrame } from './sse-protocol.js';
|
|
2
3
|
/**
|
|
3
4
|
* Recursively cleans a JSON Schema for OpenAI API compatibility.
|
|
4
5
|
* Removes '$schema' and 'additionalProperties'.
|
|
@@ -175,12 +176,16 @@ export function buildOpenAIHeaders(apiKey) {
|
|
|
175
176
|
*/
|
|
176
177
|
export function createStreamTransformer(model) {
|
|
177
178
|
let initialized = false;
|
|
178
|
-
let buffer = '';
|
|
179
179
|
const messageId = `msg_${Math.random().toString(36).substr(2, 9)}`;
|
|
180
180
|
const toolCalls = {};
|
|
181
181
|
let contentBlockIndex = 0;
|
|
182
|
+
// 上一帧的原始 data 字符串(帧驱动下对应原 lines[length-2] 的数据来源)
|
|
183
|
+
let lastDataRaw = '';
|
|
184
|
+
let decoder = null;
|
|
185
|
+
// [DONE] 已在 decoder 回调内收尾,transform 末尾不再重复 callback
|
|
186
|
+
let doneHandled = false;
|
|
182
187
|
const sendEvent = (event, data) => {
|
|
183
|
-
return
|
|
188
|
+
return encodeSSEFrame({ event, data: JSON.stringify(data) });
|
|
184
189
|
};
|
|
185
190
|
return new Transform({
|
|
186
191
|
transform(chunk, _encoding, callback) {
|
|
@@ -204,89 +209,94 @@ export function createStreamTransformer(model) {
|
|
|
204
209
|
}));
|
|
205
210
|
initialized = true;
|
|
206
211
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
212
|
+
if (!decoder) {
|
|
213
|
+
decoder = createSSEDecoder((frame) => {
|
|
214
|
+
const data = frame.data.join('\n');
|
|
215
|
+
if (data.trim() === '[DONE]') {
|
|
216
|
+
// Send closing events
|
|
217
|
+
this.push(sendEvent('content_block_stop', { type: 'content_block_stop', index: 0 }));
|
|
218
|
+
Object.values(toolCalls).forEach(tc => {
|
|
219
|
+
if (tc.started) {
|
|
220
|
+
this.push(sendEvent('content_block_stop', { type: 'content_block_stop', index: tc.claudeIndex }));
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
let finalStopReason = 'end_turn';
|
|
224
|
+
try {
|
|
225
|
+
const lastChunk = JSON.parse(lastDataRaw);
|
|
226
|
+
const finishReason = lastChunk.choices[0].finish_reason;
|
|
227
|
+
if (finishReason === 'tool_calls')
|
|
228
|
+
finalStopReason = 'tool_use';
|
|
229
|
+
if (finishReason === 'length')
|
|
230
|
+
finalStopReason = 'max_tokens';
|
|
220
231
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (finishReason === 'tool_calls')
|
|
227
|
-
finalStopReason = 'tool_use';
|
|
228
|
-
if (finishReason === 'length')
|
|
229
|
-
finalStopReason = 'max_tokens';
|
|
230
|
-
}
|
|
231
|
-
catch { }
|
|
232
|
-
this.push(sendEvent('message_delta', {
|
|
233
|
-
type: 'message_delta',
|
|
234
|
-
delta: { stop_reason: finalStopReason, stop_sequence: null },
|
|
235
|
-
usage: { output_tokens: 0 }
|
|
236
|
-
}));
|
|
237
|
-
this.push(sendEvent('message_stop', { type: 'message_stop' }));
|
|
238
|
-
callback();
|
|
239
|
-
this.destroy();
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
try {
|
|
243
|
-
const openaiChunk = JSON.parse(data);
|
|
244
|
-
const delta = openaiChunk.choices[0]?.delta;
|
|
245
|
-
if (!delta)
|
|
246
|
-
continue;
|
|
247
|
-
if (delta.content) {
|
|
248
|
-
this.push(sendEvent('content_block_delta', {
|
|
249
|
-
type: 'content_block_delta',
|
|
250
|
-
index: 0,
|
|
251
|
-
delta: { type: 'text_delta', text: delta.content }
|
|
232
|
+
catch { }
|
|
233
|
+
this.push(sendEvent('message_delta', {
|
|
234
|
+
type: 'message_delta',
|
|
235
|
+
delta: { stop_reason: finalStopReason, stop_sequence: null },
|
|
236
|
+
usage: { output_tokens: 0 }
|
|
252
237
|
}));
|
|
238
|
+
this.push(sendEvent('message_stop', { type: 'message_stop' }));
|
|
239
|
+
doneHandled = true;
|
|
240
|
+
callback();
|
|
241
|
+
this.destroy();
|
|
242
|
+
return;
|
|
253
243
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
244
|
+
lastDataRaw = data;
|
|
245
|
+
try {
|
|
246
|
+
const openaiChunk = JSON.parse(data);
|
|
247
|
+
const delta = openaiChunk.choices[0]?.delta;
|
|
248
|
+
if (!delta)
|
|
249
|
+
return;
|
|
250
|
+
if (delta.content) {
|
|
251
|
+
this.push(sendEvent('content_block_delta', {
|
|
252
|
+
type: 'content_block_delta',
|
|
253
|
+
index: 0,
|
|
254
|
+
delta: { type: 'text_delta', text: delta.content }
|
|
255
|
+
}));
|
|
256
|
+
}
|
|
257
|
+
if (delta.tool_calls) {
|
|
258
|
+
for (const tc_delta of delta.tool_calls) {
|
|
259
|
+
const index = tc_delta.index;
|
|
260
|
+
if (!toolCalls[index]) {
|
|
261
|
+
toolCalls[index] = { id: '', name: '', args: '', claudeIndex: 0, started: false };
|
|
262
|
+
}
|
|
263
|
+
if (tc_delta.id)
|
|
264
|
+
toolCalls[index].id = tc_delta.id;
|
|
265
|
+
if (tc_delta.function?.name)
|
|
266
|
+
toolCalls[index].name = tc_delta.function.name;
|
|
267
|
+
if (tc_delta.function?.arguments)
|
|
268
|
+
toolCalls[index].args += tc_delta.function.arguments;
|
|
269
|
+
if (toolCalls[index].id && toolCalls[index].name && !toolCalls[index].started) {
|
|
270
|
+
contentBlockIndex++;
|
|
271
|
+
toolCalls[index].claudeIndex = contentBlockIndex;
|
|
272
|
+
toolCalls[index].started = true;
|
|
273
|
+
this.push(sendEvent('content_block_start', {
|
|
274
|
+
type: 'content_block_start',
|
|
275
|
+
index: contentBlockIndex,
|
|
276
|
+
content_block: { type: 'tool_use', id: toolCalls[index].id, name: toolCalls[index].name, input: {} }
|
|
277
|
+
}));
|
|
278
|
+
}
|
|
279
|
+
if (toolCalls[index].started && tc_delta.function?.arguments) {
|
|
280
|
+
this.push(sendEvent('content_block_delta', {
|
|
281
|
+
type: 'content_block_delta',
|
|
282
|
+
index: toolCalls[index].claudeIndex,
|
|
283
|
+
delta: { type: 'input_json_delta', partial_json: tc_delta.function.arguments }
|
|
284
|
+
}));
|
|
285
|
+
}
|
|
282
286
|
}
|
|
283
287
|
}
|
|
284
288
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
+
catch {
|
|
290
|
+
// Ignore JSON parse errors in SSE chunks
|
|
291
|
+
}
|
|
292
|
+
});
|
|
289
293
|
}
|
|
294
|
+
decoder.write(chunk);
|
|
295
|
+
if (!doneHandled)
|
|
296
|
+
callback();
|
|
297
|
+
},
|
|
298
|
+
flush(callback) {
|
|
299
|
+
decoder?.end();
|
|
290
300
|
callback();
|
|
291
301
|
}
|
|
292
302
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ToolDefinition } from '@earendil-works/pi-coding-agent';
|
|
2
1
|
/**
|
|
3
2
|
* 统一封装 ego-browser CLI:spawn 子进程 + 写入 Node 脚本 stdin,返回 cliLog 文本。
|
|
4
3
|
* 每次调用独立进程,靠 useOrCreateTaskSpace 在同一 task space 复用 tab。
|
|
@@ -9,4 +8,3 @@ export declare function runEgoBrowser(scriptBody: string, opts?: {
|
|
|
9
8
|
}): Promise<string>;
|
|
10
9
|
/** 过滤 ego-browser 自身打到输出流的横幅行(如升级 notice),保留脚本 cliLog 的真实输出 */
|
|
11
10
|
export declare function stripCliBanners(text: string): string;
|
|
12
|
-
export declare const browserTools: ToolDefinition[];
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
-
import { Type } from 'typebox';
|
|
3
2
|
/**
|
|
4
3
|
* 统一封装 ego-browser CLI:spawn 子进程 + 写入 Node 脚本 stdin,返回 cliLog 文本。
|
|
5
4
|
* 每次调用独立进程,靠 useOrCreateTaskSpace 在同一 task space 复用 tab。
|
|
@@ -80,176 +79,3 @@ export function stripCliBanners(text) {
|
|
|
80
79
|
.filter((line) => !line.startsWith('[ego-browser:notice]'))
|
|
81
80
|
.join('\n');
|
|
82
81
|
}
|
|
83
|
-
// ---------- 工具实现辅助 ----------
|
|
84
|
-
/** 把字符串参数安全注入脚本:JSON.stringify 自动处理引号 / 反斜杠 / 换行 */
|
|
85
|
-
const jsLit = (v) => JSON.stringify(v);
|
|
86
|
-
/** 构造 pi AgentToolResult(content + details 字段) */
|
|
87
|
-
const ok = (text) => ({
|
|
88
|
-
content: [{ type: 'text', text }],
|
|
89
|
-
details: undefined,
|
|
90
|
-
});
|
|
91
|
-
const navigateSchema = Type.Object({
|
|
92
|
-
url: Type.String({ description: '目标 URL,必须是 http(s) 完整地址' }),
|
|
93
|
-
wait: Type.Optional(Type.Boolean({ description: '是否等待页面加载完成,默认 true' })),
|
|
94
|
-
});
|
|
95
|
-
const snapshotSchema = Type.Object({
|
|
96
|
-
scope: Type.Optional(Type.String({
|
|
97
|
-
description: "snapshotText 的 scope:'full_page'(默认)或 'only_within_viewport'",
|
|
98
|
-
})),
|
|
99
|
-
});
|
|
100
|
-
const screenshotSchema = Type.Object({});
|
|
101
|
-
const clickSchema = Type.Object({
|
|
102
|
-
target: Type.String({
|
|
103
|
-
description: "点击目标:@N / CSS / 'xpath=...' / 'loc=...',或 [x,y] 视口坐标数组",
|
|
104
|
-
}),
|
|
105
|
-
label: Type.Optional(Type.String({ description: '可选 3-6 字动作描述,用于高亮' })),
|
|
106
|
-
});
|
|
107
|
-
const typeSchema = Type.Object({
|
|
108
|
-
target: Type.String({ description: '输入框定位:@N / CSS / xpath=... / loc=...' }),
|
|
109
|
-
text: Type.String({ description: '要填入的文本内容' }),
|
|
110
|
-
submit: Type.Optional(Type.Boolean({ description: 'true 则填完后按 Enter,默认 false' })),
|
|
111
|
-
});
|
|
112
|
-
const scrollSchema = Type.Object({
|
|
113
|
-
direction: Type.String({
|
|
114
|
-
enum: ['down', 'up', 'bottom'],
|
|
115
|
-
description: "滚动方向:'down' / 'up' / 'bottom'(滚到底并触发懒加载)",
|
|
116
|
-
}),
|
|
117
|
-
amount: Type.Optional(Type.Number({ description: 'down/up 时的滚动像素量,默认 900' })),
|
|
118
|
-
});
|
|
119
|
-
const evaluateSchema = Type.Object({
|
|
120
|
-
expression: Type.String({
|
|
121
|
-
description: '页面内 JS 字符串。复杂逻辑用 IIFE:(() => { ... })()',
|
|
122
|
-
}),
|
|
123
|
-
});
|
|
124
|
-
const fetchSchema = Type.Object({
|
|
125
|
-
url: Type.String({ description: '要抓取的 URL' }),
|
|
126
|
-
});
|
|
127
|
-
const pressKeySchema = Type.Object({
|
|
128
|
-
key: Type.String({ description: "CDP 键名,如 'Enter' / 'Escape' / 'ArrowDown'" }),
|
|
129
|
-
});
|
|
130
|
-
export const browserTools = [
|
|
131
|
-
{
|
|
132
|
-
name: 'browser_navigate',
|
|
133
|
-
label: 'browser_navigate',
|
|
134
|
-
description: '在 ego-browser 的 knowledge-learn task space 中打开或复用 tab 到给定 URL。wait=true(默认)会等页面加载,timeout 20s。',
|
|
135
|
-
parameters: navigateSchema,
|
|
136
|
-
async execute(_id, params, signal) {
|
|
137
|
-
const url = jsLit(params.url);
|
|
138
|
-
const wait = params.wait ?? true;
|
|
139
|
-
const body = `
|
|
140
|
-
await openOrReuseTab(${url}, { wait: ${wait}, timeout: 20 })
|
|
141
|
-
const info = await pageInfo()
|
|
142
|
-
cliLog(JSON.stringify(info))
|
|
143
|
-
`;
|
|
144
|
-
return ok(await runEgoBrowser(body, { signal }));
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
name: 'browser_snapshot',
|
|
149
|
-
label: 'browser_snapshot',
|
|
150
|
-
description: '获取当前页面的可访问性语义树(含 @N / loc= 引用),是后续 click/fillInput 定位元素的依据。默认 scope=full_page 覆盖整页。',
|
|
151
|
-
parameters: snapshotSchema,
|
|
152
|
-
async execute(_id, params, signal) {
|
|
153
|
-
const scope = params.scope ?? 'full_page';
|
|
154
|
-
const body = `cliLog(await snapshotText({ scope: ${jsLit(scope)} }))`;
|
|
155
|
-
return ok(await runEgoBrowser(body, { signal }));
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
name: 'browser_screenshot',
|
|
160
|
-
label: 'browser_screenshot',
|
|
161
|
-
description: '对当前页面视口截图。返回 ego 输出的图片说明 / 路径文本。',
|
|
162
|
-
parameters: screenshotSchema,
|
|
163
|
-
async execute(_id, _params, signal) {
|
|
164
|
-
return ok(await runEgoBrowser('cliLog(await captureScreenshot())', { signal }));
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
name: 'browser_click',
|
|
169
|
-
label: 'browser_click',
|
|
170
|
-
description: '点击元素。target 支持 @N(来自最近一次 snapshotText)、CSS 选择器、xpath=...、loc=...(推荐长期稳定引用)。label 是 3-6 字动作描述,会触发高亮动画。',
|
|
171
|
-
parameters: clickSchema,
|
|
172
|
-
async execute(_id, params, signal) {
|
|
173
|
-
const target = jsLit(params.target);
|
|
174
|
-
const label = params.label ? `, { label: ${jsLit(params.label)} }` : '';
|
|
175
|
-
const body = `await click(${target}${label})\ncliLog('clicked: ${params.target}')`;
|
|
176
|
-
return ok(await runEgoBrowser(body, { signal }));
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
name: 'browser_type',
|
|
181
|
-
label: 'browser_type',
|
|
182
|
-
description: '向输入框填充文本。target 同 browser_click(@N / CSS / xpath / loc)。submit=true 时填完后按 Enter(常用于搜索框)。',
|
|
183
|
-
parameters: typeSchema,
|
|
184
|
-
async execute(_id, params, signal) {
|
|
185
|
-
const target = jsLit(params.target);
|
|
186
|
-
const text = jsLit(params.text);
|
|
187
|
-
const submitBlock = params.submit ? `\nawait pressKey('Enter')` : '';
|
|
188
|
-
const body = `
|
|
189
|
-
await fillInput(${target}, ${text})${submitBlock}
|
|
190
|
-
cliLog('filled: ${params.target}')
|
|
191
|
-
`;
|
|
192
|
-
return ok(await runEgoBrowser(body, { signal }));
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
name: 'browser_scroll',
|
|
197
|
-
label: 'browser_scroll',
|
|
198
|
-
description: '滚动页面。direction=down/up 按 amount 像素滚动;direction=bottom 自动滚到底并尝试触发懒加载(最多 20 步)。',
|
|
199
|
-
parameters: scrollSchema,
|
|
200
|
-
async execute(_id, params, signal) {
|
|
201
|
-
let body;
|
|
202
|
-
if (params.direction === 'bottom') {
|
|
203
|
-
body = `
|
|
204
|
-
await scrollToBottomUntil(
|
|
205
|
-
async () => false,
|
|
206
|
-
{ step: 900, wait: 1, maxSteps: 20 }
|
|
207
|
-
)
|
|
208
|
-
cliLog('scrolled to bottom')
|
|
209
|
-
`;
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
const amount = params.amount ?? 900;
|
|
213
|
-
const signed = params.direction === 'down' ? amount : -amount;
|
|
214
|
-
body = `
|
|
215
|
-
await scrollBy(${signed})
|
|
216
|
-
cliLog('scrolled ${params.direction} ${amount}px')
|
|
217
|
-
`;
|
|
218
|
-
}
|
|
219
|
-
return ok(await runEgoBrowser(body, { signal }));
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
name: 'browser_evaluate',
|
|
224
|
-
label: 'browser_evaluate',
|
|
225
|
-
description: '在页面上下文执行 JS 字符串(等价于 Runtime.evaluate),返回序列化结果。多步逻辑请包成 IIFE:(() => { ... })()。不要把它当 Puppeteer page.evaluate(fn, ...args) 用。',
|
|
226
|
-
parameters: evaluateSchema,
|
|
227
|
-
async execute(_id, params, signal) {
|
|
228
|
-
const expr = jsLit(params.expression);
|
|
229
|
-
const body = `cliLog(JSON.stringify(await js(${expr})))`;
|
|
230
|
-
return ok(await runEgoBrowser(body, { signal }));
|
|
231
|
-
},
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
name: 'browser_fetch',
|
|
235
|
-
label: 'browser_fetch',
|
|
236
|
-
description: '在当前浏览器页面上下文发起 fetch(复用登录态 / Cookie),返回响应正文文本。适合抓取需要鉴权的页面 JSON 或 HTML。',
|
|
237
|
-
parameters: fetchSchema,
|
|
238
|
-
async execute(_id, params, signal) {
|
|
239
|
-
const url = jsLit(params.url);
|
|
240
|
-
const body = `cliLog(await browserFetch(${url}))`;
|
|
241
|
-
return ok(await runEgoBrowser(body, { signal }));
|
|
242
|
-
},
|
|
243
|
-
},
|
|
244
|
-
{
|
|
245
|
-
name: 'browser_press_key',
|
|
246
|
-
label: 'browser_press_key',
|
|
247
|
-
description: '在当前焦点元素按下键盘按键。key 用 CDP 键名,如 "Enter" / "Escape" / "Tab" / "ArrowDown" / "Control+A"。',
|
|
248
|
-
parameters: pressKeySchema,
|
|
249
|
-
async execute(_id, params, signal) {
|
|
250
|
-
const key = jsLit(params.key);
|
|
251
|
-
const body = `await pressKey(${key})\ncliLog('pressed: ${params.key}')`;
|
|
252
|
-
return ok(await runEgoBrowser(body, { signal }));
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
];
|
|
@@ -25,6 +25,7 @@ export declare class CrawlGuard {
|
|
|
25
25
|
private readonly maxPages;
|
|
26
26
|
private readonly maxDepth;
|
|
27
27
|
private readonly navigate;
|
|
28
|
+
private readonly vault;
|
|
28
29
|
private entry;
|
|
29
30
|
private readonly seen;
|
|
30
31
|
private readonly depthByUrl;
|
|
@@ -58,5 +59,5 @@ export declare class CrawlGuard {
|
|
|
58
59
|
*/
|
|
59
60
|
close(): Promise<void>;
|
|
60
61
|
}
|
|
61
|
-
export declare function createCrawlTools(guard: CrawlGuard): ToolDefinition[];
|
|
62
|
+
export declare function createCrawlTools(guard: CrawlGuard, signal: AbortSignal): ToolDefinition[];
|
|
62
63
|
export {};
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
// saveSource 落盘到 <slug>/sources/source-NNN.md
|
|
4
4
|
// - createCrawlTools:挂给 pi session 的 4 个工具(crawl_open/crawl_visit/
|
|
5
5
|
// save_source/crawl_finish),错误以文本返回,LLM 可读可恢复
|
|
6
|
-
import fs from 'node:fs';
|
|
7
|
-
import path from 'node:path';
|
|
8
6
|
import { Type } from 'typebox';
|
|
9
7
|
import { runEgoBrowser } from './pi-browser-tools.js';
|
|
10
8
|
import { CRAWL_MAX_PAGES, CRAWL_MAX_DEPTH, isSameSite, normalizeCandidate } from './web-crawler.js';
|
|
9
|
+
import { createVault } from './vault.js';
|
|
11
10
|
/** 单页浏览器脚本:task space 取 tab → goto → networkidle 缓冲 → 稳定性轮询 → 提取标题/正文/链接 */
|
|
12
11
|
function buildCrawlScript(url) {
|
|
13
12
|
return `const pages = await task.pages()
|
|
@@ -65,6 +64,12 @@ export class CrawlGuard {
|
|
|
65
64
|
writable: true,
|
|
66
65
|
value: void 0
|
|
67
66
|
});
|
|
67
|
+
Object.defineProperty(this, "vault", {
|
|
68
|
+
enumerable: true,
|
|
69
|
+
configurable: true,
|
|
70
|
+
writable: true,
|
|
71
|
+
value: void 0
|
|
72
|
+
});
|
|
68
73
|
Object.defineProperty(this, "entry", {
|
|
69
74
|
enumerable: true,
|
|
70
75
|
configurable: true,
|
|
@@ -108,6 +113,7 @@ export class CrawlGuard {
|
|
|
108
113
|
writable: true,
|
|
109
114
|
value: 0
|
|
110
115
|
});
|
|
116
|
+
this.vault = createVault(opts.docsDir);
|
|
111
117
|
this.maxPages = opts.maxPages ?? CRAWL_MAX_PAGES;
|
|
112
118
|
this.maxDepth = opts.maxDepth ?? CRAWL_MAX_DEPTH;
|
|
113
119
|
this.navigate = opts.navigate ?? ((url, signal) => this.defaultNavigate(url, signal));
|
|
@@ -208,10 +214,7 @@ export class CrawlGuard {
|
|
|
208
214
|
// 对齐旧 crawlSite:trim 后为空的页面判失败,不产生空原料
|
|
209
215
|
if (page.text.trim() === '')
|
|
210
216
|
throw new Error(`save_source reject empty page: ${key}`);
|
|
211
|
-
|
|
212
|
-
fs.mkdirSync(sourcesDir, { recursive: true });
|
|
213
|
-
const name = `source-${String(this._savedCount + 1).padStart(3, '0')}.md`;
|
|
214
|
-
fs.writeFileSync(path.join(sourcesDir, name), `Source: ${key}\n\n${page.text}`, 'utf8');
|
|
217
|
+
this.vault.writeSourceFile(this.opts.slug, this._savedCount, key, page.text);
|
|
215
218
|
this.savedUrls.add(key);
|
|
216
219
|
this._savedCount += 1;
|
|
217
220
|
return { savedCount: this._savedCount, reused: false };
|
|
@@ -234,16 +237,18 @@ const ok = (text) => ({
|
|
|
234
237
|
details: undefined,
|
|
235
238
|
});
|
|
236
239
|
const errAsText = (e) => ok(`error: ${e instanceof Error ? e.message : String(e)}`);
|
|
237
|
-
export function createCrawlTools(guard) {
|
|
240
|
+
export function createCrawlTools(guard, signal) {
|
|
241
|
+
// SDK 传入 tool signal 时用它(session 中止时随之中止);否则用外部 pipeline signal
|
|
242
|
+
const pickSignal = (toolSignal) => toolSignal ?? signal;
|
|
238
243
|
return [
|
|
239
244
|
{
|
|
240
245
|
name: 'crawl_open',
|
|
241
246
|
label: 'crawl_open',
|
|
242
247
|
description: '打开本次任务的入口 URL,返回标题、正文与同站链接。抓取第一步调用。',
|
|
243
248
|
parameters: Type.Object({}),
|
|
244
|
-
async execute(_id, _params,
|
|
249
|
+
async execute(_id, _params, toolSignal) {
|
|
245
250
|
try {
|
|
246
|
-
return ok(JSON.stringify(await guard.open(
|
|
251
|
+
return ok(JSON.stringify(await guard.open(pickSignal(toolSignal))));
|
|
247
252
|
}
|
|
248
253
|
catch (e) {
|
|
249
254
|
return errAsText(e);
|
|
@@ -255,9 +260,9 @@ export function createCrawlTools(guard) {
|
|
|
255
260
|
label: 'crawl_visit',
|
|
256
261
|
description: '访问入口同站的子页面(必须是 crawl_open/上一次 crawl_visit 返回链接中的 http(s) 页面)。',
|
|
257
262
|
parameters: Type.Object({ url: Type.String({ description: '要访问的同站完整 URL' }) }),
|
|
258
|
-
async execute(_id, params,
|
|
263
|
+
async execute(_id, params, toolSignal) {
|
|
259
264
|
try {
|
|
260
|
-
return ok(JSON.stringify(await guard.visit(params.url,
|
|
265
|
+
return ok(JSON.stringify(await guard.visit(params.url, pickSignal(toolSignal))));
|
|
261
266
|
}
|
|
262
267
|
catch (e) {
|
|
263
268
|
return errAsText(e);
|