@jshookmcp/jshook 0.3.2 → 0.3.3
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/README.md +3 -3
- package/README.zh.md +3 -3
- package/dist/{AntiCheatDetector-B6d4Qe9D.mjs → AntiCheatDetector-CUpZBh5O.mjs} +1 -1
- package/dist/{BrowserSessionCoordinator-BJ-HOxo0.mjs → BrowserSessionCoordinator-QIt3tetp.mjs} +1 -1
- package/dist/CodeInjector-Btj9upnf.mjs +1 -0
- package/dist/{ConsoleMonitor-CxDJV15E.mjs → ConsoleMonitor-DIjN5Afa.mjs} +5 -5
- package/dist/{DarwinAPI-ZfQdpLNI.mjs → DarwinAPI-BuMPGzHm.mjs} +1 -1
- package/dist/DetailedDataManager-Z77fDl9Z.mjs +5 -0
- package/dist/ExtensionManager.tools-CIGOWViz.mjs +1 -0
- package/dist/{FingerprintManager-DT0EAUEo.mjs → FingerprintManager-BkDSsjjP.mjs} +1 -1
- package/dist/{HardwareBreakpoint-BUfPdp0f.mjs → HardwareBreakpoint-DMAMcPyB.mjs} +1 -1
- package/dist/{HeapAnalyzer-B_aqY8oj.mjs → HeapAnalyzer-Yj348FYt.mjs} +1 -1
- package/dist/{ExtensionManager.tools-oVMJgPcN.mjs → MCPServer.activation.ttl-CEGNBycZ.mjs} +1 -1
- package/dist/MCPServer.search.helpers-Cs1JpKbu.mjs +1 -0
- package/dist/MCPServer.search.validation-DnifPCCv.mjs +1 -0
- package/dist/{MemoryController-X1XNSn1n.mjs → MemoryController-DjtgiING.mjs} +1 -1
- package/dist/{MemoryScanSession-DG_F-PjE.mjs → MemoryScanSession-zfoVZJB0.mjs} +1 -1
- package/dist/MemoryScanner-Dxd657li.mjs +1 -0
- package/dist/{NativeMemoryManager.utils-BHy1P_jM.mjs → NativeMemoryManager.utils-Bu8srMEF.mjs} +1 -1
- package/dist/{PEAnalyzer-yWQaGrcx.mjs → PEAnalyzer-CMu9Ua9T.mjs} +1 -1
- package/dist/PointerChainEngine-CaSC1Mry.mjs +1 -0
- package/dist/{ProcessRegistry-C-bN48oR.mjs → ProcessRegistry-D5y1yuP2.mjs} +1 -1
- package/dist/{ReverseEvidenceGraph-BhSYYdiI.mjs → ReverseEvidenceGraph-BksOpsPs.mjs} +1 -1
- package/dist/ServerRuntimeState-CgqBBwfd.mjs +1 -0
- package/dist/{Speedhack-yseDPSZ9.mjs → Speedhack-pwXTHxOY.mjs} +1 -1
- package/dist/{StructureAnalyzer-C5lpuZkg.mjs → StructureAnalyzer-BseGzsSl.mjs} +2 -2
- package/dist/ToolCatalog-DgmQXdsm.mjs +1 -0
- package/dist/ToolHandlerMap-7HWoIgQO.mjs +1 -0
- package/dist/{ToolProbe-C7ZU2x7M.mjs → ToolProbe-DQiREmNp.mjs} +1 -1
- package/dist/{ToolRegistry-C5oB8KP8.mjs → ToolRegistry-eMZEBiR1.mjs} +1 -1
- package/dist/ToolRouter.policy-UKBlFlbh.mjs +4 -0
- package/dist/{TraceRecorder-BiJWBXHX.mjs → TraceRecorder-B5ktv3nP.mjs} +2 -2
- package/dist/VersionDetector-CmPJmaJg.mjs +1 -0
- package/dist/{Win32API-eUCF57l_.mjs → Win32API-DoP3MMHS.mjs} +1 -1
- package/dist/{Win32Debug-CYrIQBvr.mjs → Win32Debug-DwF8mQGm.mjs} +1 -1
- package/dist/{WorkflowEngine-D876meOO.mjs → WorkflowEngine-CldHG5b4.mjs} +1 -1
- package/dist/{analysis-D4swdMvq.mjs → analysis-C-ln0Brh.mjs} +3 -3
- package/dist/antidebug-CsnpOR9z.mjs +1 -0
- package/dist/{artifactRetention-BCPQASm7.mjs → artifactRetention-DkYKLOvi.mjs} +1 -1
- package/dist/{artifacts-CkodUM4j.mjs → artifacts-D-4pSS_N.mjs} +1 -1
- package/dist/{betterSqlite3-Brtq-SIQ.mjs → betterSqlite3-Bdo_ifuJ.mjs} +1 -1
- package/dist/binary-instrument-BeZ224mZ.mjs +9 -0
- package/dist/{boringssl-inspector-BBaJwwkU.mjs → boringssl-inspector-ZOCkaipa.mjs} +2 -2
- package/dist/browser-BUaB25bk.mjs +11 -0
- package/dist/{handlers-yo_xYzT8.mjs → canvas-396ieNv5.mjs} +22 -22
- package/dist/collector-CB2syQEg.mjs +1 -0
- package/dist/constants-DMv3svps.mjs +2 -0
- package/dist/coordination-Dbohmj6D.mjs +1 -0
- package/dist/dart-inspector-LhEqRITQ.mjs +0 -0
- package/dist/debugger-CLzkObIO.mjs +1 -0
- package/dist/{definitions-OeLvmlQy.mjs → definitions-0hxnrDU72.mjs} +1 -1
- package/dist/definitions-B3a9QC2t.mjs +1 -0
- package/dist/{definitions-Ibci7e_L.mjs → definitions-BOvju5t2.mjs} +1 -1
- package/dist/{definitions-D4g-MS10.mjs → definitions-CXj_cEVt.mjs} +1 -1
- package/dist/{definitions-C3qNgSn1.mjs → definitions-Co6AvTjH.mjs} +1 -1
- package/dist/{definitions-DxFNRQNK2.mjs → definitions-Cv5r8xwq.mjs} +1 -1
- package/dist/definitions-DBYSxChX.mjs +1 -0
- package/dist/{definitions-CQd7yCQH.mjs → definitions-D_dTDX9B.mjs} +1 -1
- package/dist/{definitions-l7TjdE6V.mjs → definitions-Db9t2ddh.mjs} +1 -1
- package/dist/{definitions-BWxBke3r.mjs → definitions-DbN2CjI2.mjs} +1 -1
- package/dist/{definitions-DAQm1Xar.mjs → definitions-DlmmHmZc.mjs} +1 -1
- package/dist/{definitions-Bf3H1EwV.mjs → definitions-DnYpoGig.mjs} +1 -1
- package/dist/{definitions-BYwATKc-.mjs → definitions-DtZ6Ktx2.mjs} +1 -1
- package/dist/{definitions-D5wl_8HN.mjs → definitions-DuIPS8gq.mjs} +1 -1
- package/dist/{definitions-RZYGD_Ey.mjs → definitions-DywfwPMb.mjs} +1 -1
- package/dist/definitions-EGmqr85H.mjs +1 -0
- package/dist/{definitions-bybDvnG0.mjs → definitions-Fetw_Cge.mjs} +3 -3
- package/dist/{definitions-CB6vmOer.mjs → definitions-LdkeuOeA.mjs} +1 -1
- package/dist/{definitions-B_83XfNQ.mjs → definitions-Ym8niHDb.mjs} +1 -1
- package/dist/{definitions-Cenu6mxo.mjs → definitions-aeRd5DAR.mjs} +1 -1
- package/dist/{definitions-CT8ln6GQ.mjs → definitions-cnG6tj17.mjs} +1 -1
- package/dist/{encoding-ycOaz8Vr.mjs → encoding-B4xZWErf.mjs} +2 -2
- package/dist/ensure-browser-core-JHwDo5ql.mjs +285 -0
- package/dist/{factory-CKr4fAE1.mjs → factory-BxNdBiZa.mjs} +1 -1
- package/dist/{graphql-B2TiPEow.mjs → graphql-GBWsZ9xC.mjs} +4 -4
- package/dist/{handlers-D5E40ssn.mjs → handlers-5nzR8B0a.mjs} +2 -2
- package/dist/handlers-6iNsXOVT.mjs +7 -0
- package/dist/{handlers-BpDlVVVU.mjs → handlers-BZ8n6Hvf.mjs} +1 -1
- package/dist/{handlers-0yKLRIfo.mjs → handlers-BbLxNbbT.mjs} +1 -1
- package/dist/{handlers-DGbdQAgD.mjs → handlers-BbS4hssc.mjs} +2 -2
- package/dist/{handlers-l8QIKqBj.mjs → handlers-CIKOP4aI.mjs} +2 -2
- package/dist/handlers-CWKBBjai.mjs +1 -0
- package/dist/{handlers-B62K4FTc.mjs → handlers-Cmb6SoRC.mjs} +1 -1
- package/dist/handlers-CrJsKnEI.mjs +1 -0
- package/dist/{antidebug-7L3ygj_9.mjs → handlers-DB6xVVWq.mjs} +2 -2
- package/dist/{handlers-CMJK7m1c.mjs → handlers-DOOCWUNR.mjs} +3 -3
- package/dist/{handlers-D2ZOul9p.mjs → handlers-Z_B5aVaU.mjs} +2 -2
- package/dist/handlers-gVscChvl.mjs +1 -0
- package/dist/handlers-xFvI9P_y.mjs +1 -0
- package/dist/{handlers.impl-D9Hh8Bgl.mjs → handlers.impl-BsFTW6SD.mjs} +1 -1
- package/dist/{hooks-D4XLfgtV.mjs → hooks-DPouiS7I.mjs} +9 -9
- package/dist/index.mjs +11 -11
- package/dist/macro-p8kuJVcm.mjs +2 -0
- package/dist/maintenance-DAqADb6Z.mjs +302 -0
- package/dist/manifest-4lmM6MZR.mjs +1 -0
- package/dist/{manifest-DujQqEQR.mjs → manifest-AxaxRSt6.mjs} +2 -2
- package/dist/{manifest-DYpn8w_h.mjs → manifest-BIqRE1Qz.mjs} +1 -1
- package/dist/manifest-Box-jWfr.mjs +1 -0
- package/dist/manifest-Bp33di0Q.mjs +1 -0
- package/dist/{manifest-CQH9FhwI.mjs → manifest-BvRX4nRP.mjs} +1 -1
- package/dist/{manifest-0Jpt_AQa.mjs → manifest-C6KoB1XE.mjs} +1 -1
- package/dist/manifest-C7TdXCWY.mjs +1 -0
- package/dist/manifest-CM-n64K0.mjs +1 -0
- package/dist/{manifest-nXHmtMSp2.mjs → manifest-CUokxCUN.mjs} +1 -1
- package/dist/manifest-CWJS45iO.mjs +1 -0
- package/dist/{manifest-LLdI5m4T.mjs → manifest-Cdxdgo-D.mjs} +1 -1
- package/dist/{manifest-D_obs5F4.mjs → manifest-Cf6SmamD.mjs} +1 -1
- package/dist/manifest-Cgxu2qdv.mjs +1 -0
- package/dist/{manifest-ztWJoXy4.mjs → manifest-CowGSURa2.mjs} +1 -1
- package/dist/{manifest-DYzWI8Xs.mjs → manifest-CsGIrh34.mjs} +1 -1
- package/dist/manifest-CvDpVToN.mjs +1 -0
- package/dist/manifest-D8TL9RLE.mjs +1 -0
- package/dist/{manifest-DCx6w2XV.mjs → manifest-DIhtCBe6.mjs} +1 -1
- package/dist/{manifest-D9jUUJAu.mjs → manifest-DJbruNOg.mjs} +1 -1
- package/dist/manifest-DLGtZH-0.mjs +1 -0
- package/dist/manifest-DXHdPt2T.mjs +1 -0
- package/dist/{manifest-B3fZbSWR.mjs → manifest-Dg5ScOyW.mjs} +1 -1
- package/dist/{manifest-xWfu6iLo.mjs → manifest-DzGoTS0R.mjs} +1 -1
- package/dist/manifest-G2H52LKz.mjs +131 -0
- package/dist/{manifest-CctIumog.mjs → manifest-P0Futrgb.mjs} +1 -1
- package/dist/{manifest-YgVd8Sgz.mjs → manifest-Qw7xgvjv.mjs} +1 -1
- package/dist/{manifest-QYbQXJn0.mjs → manifest-W3qvVrP2.mjs} +1 -1
- package/dist/manifest-dG6MuR1U.mjs +1 -0
- package/dist/manifest-nWXtgq5Y2.mjs +1 -0
- package/dist/{manifest-LG42zPLY2.mjs → manifest-vp1upSSq.mjs} +1 -1
- package/dist/{modules-BPBcSaM-.mjs → modules-DO3jXCgj.mjs} +10 -10
- package/dist/{mojo-ipc-BhwsdVUW.mjs → mojo-ipc-Be-ccWrc.mjs} +1 -1
- package/dist/native-g095qhpK.mjs +961 -0
- package/dist/network-Dvxm7eEI.mjs +7 -0
- package/dist/outputPaths-D2ddHrOJ.mjs +2 -0
- package/dist/{parse-args-Bw413PlW.mjs → parse-args-ngRrvF9e.mjs} +1 -1
- package/dist/platform-DjWbuiF8.mjs +93 -0
- package/dist/process-Dq5I-KZW.mjs +2 -0
- package/dist/proxy-DPNgM7TE.mjs +2 -0
- package/dist/{registry-DH4sc1dt.mjs → registry-xB8Wgmyj.mjs} +1 -1
- package/dist/{renderer-pid-9tJnZ_9N.mjs → renderer-pid-7jbTR8f5.mjs} +1 -1
- package/dist/search-defaults-CJik67or.mjs +1 -0
- package/dist/server/plugin-api.mjs +1 -1
- package/dist/sourcemap-DqEW15Ao.mjs +1 -0
- package/dist/streaming-Dbk4eStJ.mjs +1 -0
- package/dist/{transform-DOxzeWPB.mjs → transform-D-peM3aO.mjs} +2 -2
- package/dist/{wasm-CZ_HTfKR.mjs → wasm-CZajRaad.mjs} +6 -6
- package/dist/{webcrack-C1iYG_EX.mjs → webcrack-phEfVt5y.mjs} +3 -3
- package/dist/{workflow-BdwQmARn.mjs → workflow-wkXb3x-U.mjs} +3 -3
- package/package.json +2 -2
- package/dist/CodeInjector-Cll_7bLJ.mjs +0 -1
- package/dist/DOMInspector-C19J4zeq.mjs +0 -95
- package/dist/DetailedDataManager-DmQ1LT-W.mjs +0 -1
- package/dist/ExtensionManager-BD724zkO.mjs +0 -1
- package/dist/MCPServer.search.handlers.domain-BbS-6LnX.mjs +0 -1
- package/dist/MemoryScanner-g1_L1ub5.mjs +0 -1
- package/dist/NativeMemoryManager.impl-DniBe2wf.mjs +0 -1
- package/dist/NetworkMonitor-B_-au6aV.mjs +0 -185
- package/dist/PageController-Dfsm1_o7.mjs +0 -1
- package/dist/PointerChainEngine-BhCUkmxY.mjs +0 -1
- package/dist/PrerequisiteError-BjCQA-gK.mjs +0 -1
- package/dist/ScriptManager-LWGPTdvD.mjs +0 -7
- package/dist/ServerRuntimeState-D2bWHqEE.mjs +0 -1
- package/dist/ToolCatalog-CYdD9F5f.mjs +0 -1
- package/dist/ToolRouter.policy-CfhJczkt.mjs +0 -4
- package/dist/VersionDetector-CHT36Az0.mjs +0 -9
- package/dist/apk-packer-BqXcInnX.mjs +0 -1
- package/dist/binary-instrument-DU7V6TUM.mjs +0 -7
- package/dist/binary-secrets-PdMVoyt0.mjs +0 -1
- package/dist/browser-Qqco2rOT.mjs +0 -11
- package/dist/collector-Bpl6qy2L.mjs +0 -1
- package/dist/constants-BYj8Xek8.mjs +0 -1
- package/dist/coordination-CWXW1o8K.mjs +0 -1
- package/dist/dart-inspector-7AkPeZ_Q.mjs +0 -0
- package/dist/debugger-DyALjYMk.mjs +0 -1
- package/dist/definitions-BftdXgXI.mjs +0 -1
- package/dist/definitions-Bio5XJYy.mjs +0 -1
- package/dist/definitions-CMZRSy3k.mjs +0 -1
- package/dist/definitions-DP1vgxEY.mjs +0 -1
- package/dist/definitions-Tls8c0A0.mjs +0 -1
- package/dist/ensure-browser-core-DxWC-NTp.mjs +0 -1
- package/dist/flat-target-session-DvcQX7J5.mjs +0 -1
- package/dist/handlers-8zN_vBIz.mjs +0 -1
- package/dist/handlers-DHO3rjsW.mjs +0 -1
- package/dist/handlers-FJ80VzUI.mjs +0 -2
- package/dist/handlers-VHWrxbM_.mjs +0 -1
- package/dist/handlers-mPFiNPe8.mjs +0 -302
- package/dist/jadx-search-B_Yse0Zh.mjs +0 -5
- package/dist/maintenance-BUpIukhg.mjs +0 -1
- package/dist/manifest-B7NB2rh2.mjs +0 -1
- package/dist/manifest-BDi4nbH1.mjs +0 -1
- package/dist/manifest-BLDfkE7n.mjs +0 -1
- package/dist/manifest-BcXbB4gf.mjs +0 -1
- package/dist/manifest-Bdnc_vrc.mjs +0 -1
- package/dist/manifest-BuYKgCnp.mjs +0 -1
- package/dist/manifest-CBfNnGPV.mjs +0 -1
- package/dist/manifest-CPS1Xv69.mjs +0 -1
- package/dist/manifest-CRryuZF4.mjs +0 -1
- package/dist/manifest-CvTe5ZGV2.mjs +0 -1
- package/dist/manifest-D-5GH0DV.mjs +0 -1
- package/dist/manifest-D3Ssf3IC.mjs +0 -1
- package/dist/manifest-D5ck3NvC.mjs +0 -1
- package/dist/manifest-DG19q-Ld.mjs +0 -1
- package/dist/manifest-DLMlD0Zc.mjs +0 -1
- package/dist/manifest-DwL2ik8P.mjs +0 -1
- package/dist/manifest-ItF5P8A12.mjs +0 -1
- package/dist/manifest-KZphqIyX.mjs +0 -1
- package/dist/manifest-RcpX_MyZ.mjs +0 -123
- package/dist/manifest-Zy7Odg5J.mjs +0 -1
- package/dist/manifest-ff1H7Pdp.mjs +0 -1
- package/dist/manifest-iuhF6pTL2.mjs +0 -1
- package/dist/manifest-yC16OhL2.mjs +0 -1
- package/dist/matchesWildcardPattern-BAG6LvX5.mjs +0 -1
- package/dist/native-j8l473zn.mjs +0 -961
- package/dist/network-T0VRwNPd.mjs +0 -7
- package/dist/outputPaths-B4Ic4RZh.mjs +0 -2
- package/dist/platform-CzaQtISh.mjs +0 -93
- package/dist/playwright-cdp-fallback-DqFdx9-s.mjs +0 -1
- package/dist/process-CWhsCWrf.mjs +0 -2
- package/dist/proxy-DZFlDsG3.mjs +0 -2
- package/dist/search-defaults-lYBVn_3L.mjs +0 -1
- package/dist/shared-state-board-BSjXLUV1.mjs +0 -1
- package/dist/sourcemap-Dh3Ai_ur.mjs +0 -1
- package/dist/streaming-BcJ0B6ao.mjs +0 -1
- package/dist/types-D9EiE5o9.mjs +0 -1
- /package/dist/{CacheAdapters-CsNtQIR8.mjs → CacheAdapters-BlDrQg8f.mjs} +0 -0
- /package/dist/{EventBus-DL8iLA09.mjs → EventBus-Cm-t-B65.mjs} +0 -0
- /package/dist/{EvidenceGraphBridge-BtbwXsLC.mjs → EvidenceGraphBridge-DBDc0wUA.mjs} +0 -0
- /package/dist/{HookGeneratorBuilders.core.generators.storage-DzD6dIJd.mjs → HookGeneratorBuilders.core.generators.storage-CWaWpOHa.mjs} +0 -0
- /package/dist/{InstrumentationSession-D_G1ZPyd.mjs → InstrumentationSession-c5qZyp7d.mjs} +0 -0
- /package/dist/{ResponseBuilder-BfWP-uaT.mjs → ResponseBuilder-nPXl_khE.mjs} +0 -0
- /package/dist/{RingBuffer-Dm54ELKT.mjs → RingBuffer-B6RTHmij.mjs} +0 -0
- /package/dist/{StealthVerifier-BmcxfwSF.mjs → StealthVerifier-DMBrtkhN.mjs} +0 -0
- /package/dist/{ToolError-DWU_z7gp.mjs → ToolError-g3rjWzhx.mjs} +0 -0
- /package/dist/{authorization-schema-BOFwSXUN.mjs → authorization-schema-Jtikc5Yt.mjs} +0 -0
- /package/dist/{bind-helpers-m2U8glkF.mjs → bind-helpers-D0mGAOof.mjs} +0 -0
- /package/dist/{capabilities-CyXuKUl1.mjs → capabilities-L1ax5EHS.mjs} +0 -0
- /package/dist/{chunk-C_pMuVsO.mjs → chunk-88NL7fhV.mjs} +0 -0
- /package/dist/{concurrency-DCr8WQ2M.mjs → concurrency-Dehnw4JC.mjs} +0 -0
- /package/dist/{evidence-graph-bridge-CV_UdYqj.mjs → evidence-graph-bridge-eT9icP6a.mjs} +0 -0
- /package/dist/{formatAddress-vLA_hOJt.mjs → formatAddress-DAcw4Ckg.mjs} +0 -0
- /package/dist/{logger-sBC6IdRT.mjs → logger-CCikqqvj.mjs} +0 -0
- /package/dist/{response-C7rKQst4.mjs → response-B1RuVVfD.mjs} +0 -0
- /package/dist/{ssrf-policy-CsIJGkpd.mjs → ssrf-policy-B72vdy23.mjs} +0 -0
- /package/dist/{tool-builder-qif8M9-K.mjs → tool-builder-CpLh-UQd.mjs} +0 -0
- /package/dist/{types-Fz69RzbZ.mjs → types-BzPBzmVB.mjs} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{an as e,in as t,nn as n,rn as r,tn as i}from"./constants-DMv3svps.mjs";import{t as a}from"./ToolError-g3rjWzhx.mjs";import{d as o,v as s}from"./ensure-browser-core-JHwDo5ql.mjs";import{a as c,o as l,r as u,t as d}from"./parse-args-ngRrvF9e.mjs";import{c as f}from"./ssrf-policy-B72vdy23.mjs";import"./definitions-D_dTDX9B.mjs";function p(e){return{content:[{type:`text`,text:JSON.stringify(e,null,2)}]}}function m(e,t){let n={success:!1,error:h(e)};e instanceof a&&(n.code=e.code,e.toolName&&(n.toolName=e.toolName),e.details&&(n.details=e.details)),t&&(n.context=t);let r=e instanceof s;return{content:[{type:`text`,text:JSON.stringify(n,null,2)}],...r?{}:{isError:!0}}}function h(e){return e instanceof Error?e.message:String(e)}function g(e,t,n,r,i){let a=e[t],o=n;if(typeof a==`number`&&Number.isFinite(a))o=a;else if(typeof a==`string`){let e=Number(a);Number.isFinite(e)&&(o=e)}return o<r?r:o>i?i:Math.trunc(o)}function _(e){if(!e||typeof e!=`object`||Array.isArray(e))return{};let t=new Set([`__proto__`,`constructor`,`prototype`]),n=Object.create(null);for(let[r,i]of Object.entries(e))t.has(r)||(typeof i==`string`?n[r]=i:(typeof i==`number`||typeof i==`boolean`)&&(n[r]=String(i)));return n}function v(e){let t;try{t=new URL(e)}catch{return{error:`Invalid endpoint URL: ${e}`}}return t.protocol!==`http:`&&t.protocol!==`https:`?{error:`Unsupported endpoint protocol: ${t.protocol} — only http/https allowed`}:{parsedEndpoint:t}}async function y(e){let t=v(e);return`error`in t?t.error:await f(t.parsedEndpoint.toString())?`Blocked: endpoint "${e}" resolves to a private/reserved address`:null}async function b(e,t){let n=v(e);if(`error`in n)return n.error;if(!await f(n.parsedEndpoint.toString()))return null;if(typeof t==`string`&&t.length>0)try{if(new URL(t).origin===n.parsedEndpoint.origin)return null}catch{}return`Blocked: endpoint "${e}" resolves to a private/reserved address`}function x(e,t){return e.length<=t?{preview:e,truncated:!1,totalLength:e.length}:{preview:`${e.slice(0,t)}\n... (truncated)`,truncated:!0,totalLength:e.length}}function S(e,t){let n;if(typeof e==`string`)n=e;else try{n=JSON.stringify(e,null,2)}catch{n=String(e)}return x(n,t)}function ee(e){return e===`exact`||e===`contains`||e===`regex`?e:`contains`}function C(){return`script_rule_${Date.now()}_${Math.random().toString(36).slice(2,8)}`}function w(e){if(typeof e.isInterceptResolutionHandled!=`function`)return!1;try{return e.isInterceptResolutionHandled()}catch{return!1}}async function T(e){if(!w(e))try{await e.continue()}catch{}}function te(e,t){if(e.matchType===`exact`)return t===e.url;if(e.matchType===`contains`)return t.includes(e.url);try{return new RegExp(e.url).test(t)}catch{return!1}}function E(e,t){for(let n=e.length-1;n>=0;--n){let r=e[n];if(r&&te(r,t))return r}return null}async function D(e,t){if(w(t))return;if(t.resourceType()!==`script`){await T(t);return}let n=E(e,t.url());if(!n){await T(t);return}n.hits+=1;try{await t.respond({status:200,contentType:`application/javascript; charset=utf-8`,headers:{"cache-control":`no-store`,"x-script-replaced-by":`script_replace_persist`},body:n.replacement})}catch{await T(t)}}async function ne(e,t,n){if(t.has(n))return;await n.setRequestInterception(!0);let r=t=>{D(e,t)},i=n;typeof i.prependListener==`function`?i.prependListener(`request`,r):i.on(`request`,r),t.add(n)}function O(e){let t=[`kind`,`name`];return e>0&&t.push(`ofType { ${O(e-1)} }`),t.join(`
|
|
2
2
|
`)}const k=`
|
|
3
3
|
query IntrospectionQuery {
|
|
4
4
|
__schema {
|
|
@@ -47,8 +47,8 @@ fragment InputValue on __InputValue {
|
|
|
47
47
|
fragment TypeRef on __Type {
|
|
48
48
|
${O(7)}
|
|
49
49
|
}
|
|
50
|
-
`.trim();var A=class{collector;constructor(e){this.collector=e}async handleCallGraphAnalyze(
|
|
51
|
-
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>{let t=e.match(/at\s+([^(<\s]+)/);if(t?.[1])return t[1];let n=e.match(/^([^(<\s]+)@/);return n?.[1]?n[1]:``}).filter(e=>e.length>0):[];if(f.length>1){let t=Math.min(e,f.length-1);for(let e=0;e<t;e+=1)d(f[e+1],f[e]);l=!0}else f.length===1&&i&&f[0]!==i&&(d(f[0],i),l=!0);l&&(o+=1)},p=n.__aiHooks;if(p&&typeof p==`object`){for(let[e,t]of Object.entries(p))if(Array.isArray(t))for(let n of t)n&&typeof n==`object`&&f(n,e)}for(let e of[`__functionTraceRecords`,`__functionTracerRecords`,`__functionCalls`,`__callTrace`,`__traceCalls`]){let t=n[e];if(Array.isArray(t))for(let n of t)n&&typeof n==`object`&&f(n,e)}let m=n.__functionTracer;if(m&&typeof m==`object`){let e=m.records;if(Array.isArray(e))for(let t of e)t&&typeof t==`object`&&f(t,`functionTracer.records`)}let h=Array.from(i.values()).toSorted((e,t)=>t.callCount-e.callCount),g=Array.from(r.values()).toSorted((e,t)=>t.count-e.count);return{nodes:h,edges:g,stats:{scannedRecords:a,acceptedRecords:o,nodeCount:h.length,edgeCount:g.length,maxDepth:e,filterPattern:t||null}}},{maxDepth:r,filterPattern:i}),o=a.nodes.length>n,c=a.edges.length>e;return p({success:!0,nodes:a.nodes.slice(0,n),edges:a.edges.slice(0,e),stats:{...a.stats,nodesReturned:Math.min(a.nodes.length,n),edgesReturned:Math.min(a.edges.length,e),nodesTruncated:o,edgesTruncated:c}})}catch(e){return m(e)}}},j=class{collector;scriptReplaceRules=[];interceptionInstalledPages=new WeakSet;constructor(e){this.collector=e}async handleScriptReplacePersist(e){try{let t=s(e,`url`)?.trim(),n=s(e,`replacement`),r=ee(e.matchType);if(!t)return m(`Missing required argument: url`);if(typeof n!=`string`||n.length===0)return m(`Missing required argument: replacement`);if(r===`regex`)try{RegExp(t)}catch(e){return m(`Invalid regex in url for matchType=regex`,{url:t,reason:h(e)})}let a=await this.collector.getActivePage(),o={id:C(),url:t,replacement:n,matchType:r,createdAt:Date.now(),hits:0};this.scriptReplaceRules.push(o),await ne(this.scriptReplaceRules,this.interceptionInstalledPages,a),await a.evaluateOnNewDocument(e=>{let t=window,n=`__scriptReplacePersistRules`,r=(Array.isArray(t[n])?t[n]:[]).filter(t=>t&&t.id!==e.id);r.push(e),t[n]=r},{id:o.id,url:o.url,matchType:o.matchType,createdAt:o.createdAt});let c=x(n,i);return p({success:!0,message:`Script replacement rule registered and interception enabled`,rule:{id:o.id,url:o.url,matchType:o.matchType,createdAt:o.createdAt},replacement:{length:n.length,preview:c.preview,truncated:c.truncated},activeRuleCount:this.scriptReplaceRules.length})}catch(e){return m(e)}}},re=class{collector;constructor(e){this.collector=e}async handleGraphqlIntrospect(e){try{let t=s(e,`endpoint`)?.trim();if(!t)return m(`Missing required argument: endpoint`);let n=_(e.headers);if(u(e,`useBrowser`,!0)){let e=await this.collector.getActivePage(),r=await b(t,typeof e.url==`function`?e.url():null);return r?m(r):await this.introspectViaBrowser(e,t,n)}let r=await y(t);return r?m(r):await this.introspectViaNode(t,n)}catch(e){return m(e)}}async introspectViaNode(e,t){let n={"content-type":`application/json`,...t},i,a;try{let t=new AbortController,r=setTimeout(()=>t.abort(),1e4);try{i=await fetch(e,{method:`POST`,headers:n,body:JSON.stringify({query:k,operationName:`IntrospectionQuery`}),signal:t.signal}),a=await i.text()}finally{clearTimeout(r)}}catch(t){return p({success:!1,endpoint:e,status:0,statusText:`FETCH_ERROR`,error:t instanceof Error?t.message:String(t)})}let o={};i.headers.forEach((e,t)=>{o[t]=e});let s=null;try{s=JSON.parse(a)}catch{}if(a=``,!i.ok&&!s)return p({success:!1,endpoint:e,status:i.status,statusText:i.statusText,error:`Introspection request failed`});let c=s&&typeof s==`object`?s:null,l=c&&`data`in c?c.data:s,u=s!=null&&l!==void 0?S(l,r):{preview:``,truncated:!1,totalLength:0},d={success:i.ok,endpoint:e,status:i.status,statusText:i.statusText,schemaLength:u.totalLength,schemaPreview:u.preview,schemaTruncated:u.truncated,responseHeaders:o};return u.truncated||(d.schema=l),c&&Array.isArray(c.errors)&&(d.errors=c.errors),p(d)}async introspectViaBrowser(e,t,n){let a=await d(e,async e=>{let t={"content-type":`application/json`,...e.headers};try{let n=new AbortController,r=setTimeout(()=>n.abort(),1e4),i,a;try{a=await fetch(e.endpoint,{method:`POST`,headers:t,body:JSON.stringify({query:e.query,operationName:`IntrospectionQuery`}),signal:n.signal}),i=await a.text()}finally{clearTimeout(r)}let o={};a.headers.forEach((e,t)=>{o[t]=e});let s=i.length,c=null;try{c=JSON.parse(i)}catch{}let l=c===null?i:``;return i=``,{ok:a.ok,status:a.status,statusText:a.statusText,responseHeaders:o,totalLength:s,preview:l,truncated:!1,json:c}}catch(e){return{ok:!1,status:0,statusText:`FETCH_ERROR`,responseHeaders:{},totalLength:0,preview:``,truncated:!1,json:null,error:e instanceof Error?e.message:String(e)}}},{endpoint:t,headers:n,query:k,maxSchemaChars:r});if(!a.ok&&!a.json)return p({success:!1,endpoint:t,status:a.status,statusText:a.statusText,error:a.error??`Introspection request failed`,responsePreview:x(a.preview||``,i)});let o=a.json&&typeof a.json==`object`?a.json:null,s=o&&`data`in o?o.data:a.json,c=a.json!==null&&a.json!==void 0&&s!==void 0?S(s,r):{preview:a.preview??``,truncated:a.truncated??!1,totalLength:a.totalLength??0},l={success:a.ok,endpoint:t,status:a.status,statusText:a.statusText,schemaLength:c.totalLength,schemaPreview:c.preview,schemaTruncated:c.truncated,responseHeaders:a.responseHeaders??{}};return c.truncated||(l.schema=s),o&&Array.isArray(o.errors)&&(l.errors=o.errors),a.error&&(l.error=a.error),p(l)}};function M(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function N(e,t,n){if(!t)return;let r=t.query;if(typeof r!=`string`||r.trim().length===0)return;let i=t.operationName,a=typeof i==`string`&&i.trim().length>0?i:r.match(/^\s*(query|mutation|subscription)\s+([A-Za-z0-9_]+)/)?.[2]??null;e.push({source:n.source,url:n.url,method:n.method,operationName:a,query:r,variables:t.variables??null,timestamp:n.timestamp,contentType:n.contentType})}function P(e){let t=e.trim();if(!t)return null;try{let e=JSON.parse(t);if(M(e))return e}catch{}if(t.includes(`query=`))try{let e=new URLSearchParams(t),n=e.get(`query`);if(n){let t=e.get(`operationName`),r=e.get(`variables`),i=null;if(r)try{i=JSON.parse(r)}catch{i=r}return{query:n,operationName:t,variables:i}}}catch{}return t.startsWith(`query `)||t.startsWith(`mutation `)||t.startsWith(`subscription `)?{query:t}:null}function F(e){return M(e.headers)?e.headers:M(e.requestHeaders)?e.requestHeaders:{}}function I(e){let t=F(e);for(let[e,n]of Object.entries(t))if(e.toLowerCase()===`content-type`)return typeof n==`string`?n.toLowerCase():String(n).toLowerCase();return``}function L(e){let t=[e.body,e.postData];return M(e.options)&&t.push(e.options.body),M(e.request)&&t.push(e.request.postData),t}function R(e,t){let n={scannedRecords:0,extracted:[]};if(!Array.isArray(e))return n;for(let r of e){if(!M(r))continue;n.scannedRecords+=1;let e=typeof r.url==`string`?r.url:``,i=typeof r.method==`string`?r.method:`POST`,a=typeof r.timestamp==`number`?r.timestamp:null,o=I(r);for(let s of L(r)){let r=null;M(s)?r=s:typeof s==`string`&&(r=P(s)),N(n.extracted,r,{source:t,url:e,method:i,timestamp:a,contentType:o})}o.includes(`application/graphql`)&&typeof r.body==`string`&&N(n.extracted,{query:r.body,variables:null,operationName:null},{source:t,url:e,method:i,timestamp:a,contentType:o})}return n}function z(e){let t=e.toSorted((e,t)=>(t.timestamp??0)-(e.timestamp??0)),n=[],r=new Set;for(let e of t){let t=`${e.url}|${e.operationName??``}|${e.query}|${JSON.stringify(e.variables)}`;r.has(t)||(r.add(t),n.push(e))}return n}var B=class{deps;constructor(e){this.deps=`collector`in e?e:{collector:e}}async handleGraphqlExtractQueries(e){try{let n=g(e,`limit`,50,1,200),r=await d(await this.deps.collector.getActivePage(),e=>{let t=window,n=[],r=0,i=(e,t)=>{if(!e)return;let r=e.query;if(typeof r!=`string`||r.trim().length===0)return;let i=e.operationName,a=typeof i==`string`&&i.trim().length>0?i:r.match(/^\s*(query|mutation|subscription)\s+([A-Za-z0-9_]+)/)?.[2]??null;n.push({source:t.source,url:t.url,method:t.method,operationName:a,query:r,variables:e.variables??null,timestamp:t.timestamp,contentType:t.contentType})},a=e=>{if(!e)return null;try{let t=JSON.parse(e);if(t&&typeof t==`object`&&!Array.isArray(t))return t}catch{}if(e.includes(`query=`))try{let t=new URLSearchParams(e),n=t.get(`query`);if(n){let e=t.get(`operationName`),r=t.get(`variables`),i=null;if(r)try{i=JSON.parse(r)}catch{i=r}return{query:n,operationName:e,variables:i}}}catch{}return e.startsWith(`query `)||e.startsWith(`mutation `)||e.startsWith(`subscription `)?{query:e}:null},o=(e,t)=>{r+=1;let n=typeof e.url==`string`?e.url:``,o=typeof e.method==`string`?e.method:`POST`,s=typeof e.timestamp==`number`?e.timestamp:null,c=(e.headers&&typeof e.headers==`object`&&!Array.isArray(e.headers)?e.headers:null)??(e.requestHeaders&&typeof e.requestHeaders==`object`&&!Array.isArray(e.requestHeaders)?e.requestHeaders:null)??{},l=``;for(let[e,t]of Object.entries(c))if(e.toLowerCase()===`content-type`){l=typeof t==`string`?t:String(t);break}l=l.toLowerCase();let u=[e.body,e.postData];e.options&&typeof e.options==`object`&&!Array.isArray(e.options)&&u.push(e.options.body);for(let e of u){let r=null;e&&typeof e==`object`&&!Array.isArray(e)?r=e:typeof e==`string`&&(r=a(e)),i(r,{source:t,url:n,method:o,timestamp:s,contentType:l})}l.includes(`application/graphql`)&&typeof e.body==`string`&&i({query:e.body,variables:null,operationName:null},{source:t,url:n,method:o,timestamp:s,contentType:l})},s=(e,t)=>{if(Array.isArray(e))for(let n of e)n&&typeof n==`object`&&o(n,t)},c=Array.isArray(t.__fetchRequests)?t.__fetchRequests:typeof t.__getFetchRequests==`function`?t.__getFetchRequests():void 0,l=Array.isArray(t.__xhrRequests)?t.__xhrRequests:typeof t.__getXHRRequests==`function`?t.__getXHRRequests():void 0;s(c,`window.__fetchRequests`),s(l,`window.__xhrRequests`),s(t.__networkRequests,`window.__networkRequests`);let u=t.__aiHooks;if(u&&typeof u==`object`){for(let[e,t]of Object.entries(u))if(Array.isArray(t))for(let n of t)n&&typeof n==`object`&&o(n,`window.__aiHooks.${e}`)}n.sort((e,t)=>(t.timestamp??0)-(e.timestamp??0));let d=[],f=new Set;for(let e of n){let t=`${e.url}|${e.operationName??``}|${e.query}|${JSON.stringify(e.variables)}`;f.has(t)||(f.add(t),d.push(e))}return{scannedRecords:r,totalExtracted:d.length,extracted:d.slice(0,e)}},n),a=r.scannedRecords,o=[...r.extracted];if(this.deps.consoleMonitor){let e=typeof this.deps.consoleMonitor.getFetchRequests==`function`?this.deps.consoleMonitor.getFetchRequests().catch(()=>[]):Promise.resolve([]),t=typeof this.deps.consoleMonitor.getXHRRequests==`function`?this.deps.consoleMonitor.getXHRRequests().catch(()=>[]):Promise.resolve([]),[n,r]=await Promise.all([e,t]),i=[];try{i=typeof this.deps.consoleMonitor.getNetworkRequests==`function`?this.deps.consoleMonitor.getNetworkRequests({limit:500}):[]}catch{i=[]}let s=[R(n,`consoleMonitor.fetchRequests`),R(r,`consoleMonitor.xhrRequests`),R(i,`consoleMonitor.networkRequests`)];for(let e of s)a+=e.scannedRecords,o.push(...e.extracted)}let s=z(o),c=Math.max(r.totalExtracted,s.length),l=s.slice(0,n).map((e,n)=>{let r=x(e.query,t),a=S(e.variables,i),o={index:n,source:e.source,url:e.url,method:e.method,operationName:e.operationName,contentType:e.contentType,timestamp:e.timestamp,queryLength:e.query.length,queryPreview:r.preview,queryTruncated:r.truncated};return r.truncated||(o.query=e.query),a.truncated?(o.variablesPreview=a.preview,o.variablesTruncated=!0):o.variables=e.variables,o});return p({success:!0,limit:n,stats:{scannedRecords:a,totalExtracted:c,returned:l.length},queries:l})}catch(e){return m(e)}}},V=class{collector;constructor(e){this.collector=e}async handleGraphqlReplay(e){try{let t=s(e,`endpoint`)?.trim(),n=s(e,`query`);if(!t)return m(`Missing required argument: endpoint`);if(typeof n!=`string`||n.trim().length===0)return m(`Missing required argument: query`);let r=c(e,`variables`)??{},i=s(e,`operationName`),a=i&&i.trim().length>0?i.trim():null,o=_(e.headers);if(u(e,`useBrowser`,!0)){let e=await this.collector.getActivePage(),i=await b(t,typeof e.url==`function`?e.url():null);return i?m(i):await this.replayViaBrowser(e,t,n,r,a,o)}let l=await y(t);return l?m(l):await this.replayViaNode(t,n,r,a,o)}catch(e){return m(e)}}async replayViaNode(e,t,n,r,i){let a={"content-type":`application/json`,...i},o,s;try{let i=new AbortController,c=setTimeout(()=>i.abort(),1e4);try{o=await fetch(e,{method:`POST`,headers:a,body:JSON.stringify({query:t,variables:n,operationName:r}),signal:i.signal}),s=await o.text()}finally{clearTimeout(c)}}catch(t){return p({success:!1,endpoint:e,status:0,statusText:`FETCH_ERROR`,error:t instanceof Error?t.message:String(t),operationName:r})}let c={};o.headers.forEach((e,t)=>{c[t]=e});let l=null;try{l=JSON.parse(s)}catch{l=null}return s=``,p(H(l,e,r,o.ok,o.status,o.statusText,c))}async replayViaBrowser(e,t,n,i,a,o){let s=await d(e,async e=>{let t={"content-type":`application/json`,...e.headers};try{let n=new AbortController,r=setTimeout(()=>n.abort(),1e4),i,a;try{a=await fetch(e.endpoint,{method:`POST`,headers:t,body:JSON.stringify({query:e.query,variables:e.variables,operationName:e.operationName}),signal:n.signal}),i=await a.text()}finally{clearTimeout(r)}let o=null;try{o=JSON.parse(i)}catch{o=null}let s=o===null?i:``;i=``;let c={};return a.headers.forEach((e,t)=>{c[t]=e}),{ok:a.ok,status:a.status,statusText:a.statusText,responseText:s,responseJson:o,responseHeaders:c}}catch(e){return{ok:!1,status:0,statusText:`FETCH_ERROR`,responseText:``,responseJson:null,error:e instanceof Error?e.message:String(e)}}},{endpoint:t,query:n,variables:i,operationName:a,headers:o}),c={success:s.ok,endpoint:t,status:s.status,statusText:s.statusText,operationName:a,responseHeaders:s.responseHeaders??{}};if(s.responseJson!==null){let e=S(s.responseJson,r);c.responseLength=e.totalLength,c.responsePreview=e.preview,c.responseTruncated=e.truncated,e.truncated||(c.response=s.responseJson)}else if(s.responseText){let e=s.responseText;c.responseFormat=`text`,c.responseLength=e.length,c.responsePreview=e.length>r?e.slice(0,r):e,c.responseTruncated=e.length>r}return s.error&&(c.error=s.error),p(c)}};function H(e,t,n,i,a,o,s){let c={success:i,endpoint:t,status:a,statusText:o,operationName:n,responseHeaders:s};if(e!==null){let t=S(e,r);c.responseLength=t.totalLength,c.responsePreview=t.preview,c.responseTruncated=t.truncated,t.truncated||(c.response=e)}return c}const U=new Map;function W(e){let t=U.get(e);if(t)return t;let n=`
|
|
50
|
+
`.trim();var A=class{collector;constructor(e){this.collector=e}async handleCallGraphAnalyze(e){try{let t=g(e,`maxDepth`,5,1,20),r=l(e,`filterPattern`)?.trim()||``;if(r)try{RegExp(r)}catch(e){return m(`Invalid filterPattern regex`,{filterPattern:r,reason:e instanceof Error?e.message:String(e)})}let a=await o(await this.collector.getActivePage(),({maxDepth:e,filterPattern:t})=>{let n=window,r=new Map,i=new Map,a=0,o=0,s=t?new RegExp(t):null,c=e=>s?(s.lastIndex=0,s.test(e)):!0,l=(e,t)=>s?c(e)||c(t):!0,u=(e,t=1)=>{let n=i.get(e);if(n){n.callCount+=t;return}i.set(e,{id:e,name:e,callCount:t})},d=(e,t)=>{let n=typeof e==`string`&&e.trim()||``,i=typeof t==`string`&&t.trim()||``;if(!n||!i||n===i||!l(n,i))return;let a=`${n}__->__${i}`,o=r.get(a);o?o.count+=1:r.set(a,{source:n,target:i,count:1}),u(n,1),u(i,1)},f=(t,n)=>{a+=1;let r=t.callee??t.functionName??t.fn??t.name??t.method??t.target??n,i=typeof r==`string`&&r.trim()||n,s=t.caller??t.parent??t.from??``,c=typeof s==`string`&&s.trim()||``,l=!1;c&&i&&(d(c,i),l=!0);let u=t.stack??t.stackTrace??t.trace,f=typeof u==`string`&&u.trim().length>0?u.split(`
|
|
51
|
+
`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>{let t=e.match(/at\s+([^(<\s]+)/);if(t?.[1])return t[1];let n=e.match(/^([^(<\s]+)@/);return n?.[1]?n[1]:``}).filter(e=>e.length>0):[];if(f.length>1){let t=Math.min(e,f.length-1);for(let e=0;e<t;e+=1)d(f[e+1],f[e]);l=!0}else f.length===1&&i&&f[0]!==i&&(d(f[0],i),l=!0);l&&(o+=1)},p=n.__aiHooks;if(p&&typeof p==`object`){for(let[e,t]of Object.entries(p))if(Array.isArray(t))for(let n of t)n&&typeof n==`object`&&f(n,e)}for(let e of[`__functionTraceRecords`,`__functionTracerRecords`,`__functionCalls`,`__callTrace`,`__traceCalls`]){let t=n[e];if(Array.isArray(t))for(let n of t)n&&typeof n==`object`&&f(n,e)}let m=n.__functionTracer;if(m&&typeof m==`object`){let e=m.records;if(Array.isArray(e))for(let t of e)t&&typeof t==`object`&&f(t,`functionTracer.records`)}let h=Array.from(i.values()).toSorted((e,t)=>t.callCount-e.callCount),g=Array.from(r.values()).toSorted((e,t)=>t.count-e.count);return{nodes:h,edges:g,stats:{scannedRecords:a,acceptedRecords:o,nodeCount:h.length,edgeCount:g.length,maxDepth:e,filterPattern:t||null}}},{maxDepth:t,filterPattern:r}),s=a.nodes.length>n,c=a.edges.length>i;return p({success:!0,nodes:a.nodes.slice(0,n),edges:a.edges.slice(0,i),stats:{...a.stats,nodesReturned:Math.min(a.nodes.length,n),edgesReturned:Math.min(a.edges.length,i),nodesTruncated:s,edgesTruncated:c}})}catch(e){return m(e)}}},j=class{collector;scriptReplaceRules=[];interceptionInstalledPages=new WeakSet;constructor(e){this.collector=e}async handleScriptReplacePersist(e){try{let t=l(e,`url`)?.trim(),n=l(e,`replacement`),i=ee(e.matchType);if(!t)return m(`Missing required argument: url`);if(typeof n!=`string`||n.length===0)return m(`Missing required argument: replacement`);if(i===`regex`)try{RegExp(t)}catch(e){return m(`Invalid regex in url for matchType=regex`,{url:t,reason:h(e)})}let a=await this.collector.getActivePage(),o={id:C(),url:t,replacement:n,matchType:i,createdAt:Date.now(),hits:0};this.scriptReplaceRules.push(o),await ne(this.scriptReplaceRules,this.interceptionInstalledPages,a),await a.evaluateOnNewDocument(e=>{let t=window,n=`__scriptReplacePersistRules`,r=(Array.isArray(t[n])?t[n]:[]).filter(t=>t&&t.id!==e.id);r.push(e),t[n]=r},{id:o.id,url:o.url,matchType:o.matchType,createdAt:o.createdAt});let s=x(n,r);return p({success:!0,message:`Script replacement rule registered and interception enabled`,rule:{id:o.id,url:o.url,matchType:o.matchType,createdAt:o.createdAt},replacement:{length:n.length,preview:s.preview,truncated:s.truncated},activeRuleCount:this.scriptReplaceRules.length})}catch(e){return m(e)}}},re=class{collector;constructor(e){this.collector=e}async handleGraphqlIntrospect(e){try{let t=l(e,`endpoint`)?.trim();if(!t)return m(`Missing required argument: endpoint`);let n=_(e.headers);if(d(e,`useBrowser`,!0)){let e=await this.collector.getActivePage(),r=await b(t,typeof e.url==`function`?e.url():null);return r?m(r):await this.introspectViaBrowser(e,t,n)}let r=await y(t);return r?m(r):await this.introspectViaNode(t,n)}catch(e){return m(e)}}async introspectViaNode(t,n){let r={"content-type":`application/json`,...n},i,a;try{let e=new AbortController,n=setTimeout(()=>e.abort(),1e4);try{i=await fetch(t,{method:`POST`,headers:r,body:JSON.stringify({query:k,operationName:`IntrospectionQuery`}),signal:e.signal}),a=await i.text()}finally{clearTimeout(n)}}catch(e){return p({success:!1,endpoint:t,status:0,statusText:`FETCH_ERROR`,error:e instanceof Error?e.message:String(e)})}let o={};i.headers.forEach((e,t)=>{o[t]=e});let s=null;try{s=JSON.parse(a)}catch{}if(a=``,!i.ok&&!s)return p({success:!1,endpoint:t,status:i.status,statusText:i.statusText,error:`Introspection request failed`});let c=s&&typeof s==`object`?s:null,l=c&&`data`in c?c.data:s,u=s!=null&&l!==void 0?S(l,e):{preview:``,truncated:!1,totalLength:0},d={success:i.ok,endpoint:t,status:i.status,statusText:i.statusText,schemaLength:u.totalLength,schemaPreview:u.preview,schemaTruncated:u.truncated,responseHeaders:o};return u.truncated||(d.schema=l),c&&Array.isArray(c.errors)&&(d.errors=c.errors),p(d)}async introspectViaBrowser(t,n,i){let a=await o(t,async e=>{let t={"content-type":`application/json`,...e.headers};try{let n=new AbortController,r=setTimeout(()=>n.abort(),1e4),i,a;try{a=await fetch(e.endpoint,{method:`POST`,headers:t,body:JSON.stringify({query:e.query,operationName:`IntrospectionQuery`}),signal:n.signal}),i=await a.text()}finally{clearTimeout(r)}let o={};a.headers.forEach((e,t)=>{o[t]=e});let s=i.length,c=null;try{c=JSON.parse(i)}catch{}let l=c===null?i:``;return i=``,{ok:a.ok,status:a.status,statusText:a.statusText,responseHeaders:o,totalLength:s,preview:l,truncated:!1,json:c}}catch(e){return{ok:!1,status:0,statusText:`FETCH_ERROR`,responseHeaders:{},totalLength:0,preview:``,truncated:!1,json:null,error:e instanceof Error?e.message:String(e)}}},{endpoint:n,headers:i,query:k,maxSchemaChars:e});if(!a.ok&&!a.json)return p({success:!1,endpoint:n,status:a.status,statusText:a.statusText,error:a.error??`Introspection request failed`,responsePreview:x(a.preview||``,r)});let s=a.json&&typeof a.json==`object`?a.json:null,c=s&&`data`in s?s.data:a.json,l=a.json!==null&&a.json!==void 0&&c!==void 0?S(c,e):{preview:a.preview??``,truncated:a.truncated??!1,totalLength:a.totalLength??0},u={success:a.ok,endpoint:n,status:a.status,statusText:a.statusText,schemaLength:l.totalLength,schemaPreview:l.preview,schemaTruncated:l.truncated,responseHeaders:a.responseHeaders??{}};return l.truncated||(u.schema=c),s&&Array.isArray(s.errors)&&(u.errors=s.errors),a.error&&(u.error=a.error),p(u)}};function M(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function N(e,t,n){if(!t)return;let r=t.query;if(typeof r!=`string`||r.trim().length===0)return;let i=t.operationName,a=typeof i==`string`&&i.trim().length>0?i:r.match(/^\s*(query|mutation|subscription)\s+([A-Za-z0-9_]+)/)?.[2]??null;e.push({source:n.source,url:n.url,method:n.method,operationName:a,query:r,variables:t.variables??null,timestamp:n.timestamp,contentType:n.contentType})}function P(e){let t=e.trim();if(!t)return null;try{let e=JSON.parse(t);if(M(e))return e}catch{}if(t.includes(`query=`))try{let e=new URLSearchParams(t),n=e.get(`query`);if(n){let t=e.get(`operationName`),r=e.get(`variables`),i=null;if(r)try{i=JSON.parse(r)}catch{i=r}return{query:n,operationName:t,variables:i}}}catch{}return t.startsWith(`query `)||t.startsWith(`mutation `)||t.startsWith(`subscription `)?{query:t}:null}function F(e){return M(e.headers)?e.headers:M(e.requestHeaders)?e.requestHeaders:{}}function I(e){let t=F(e);for(let[e,n]of Object.entries(t))if(e.toLowerCase()===`content-type`)return typeof n==`string`?n.toLowerCase():String(n).toLowerCase();return``}function L(e){let t=[e.body,e.postData];return M(e.options)&&t.push(e.options.body),M(e.request)&&t.push(e.request.postData),t}function R(e,t){let n={scannedRecords:0,extracted:[]};if(!Array.isArray(e))return n;for(let r of e){if(!M(r))continue;n.scannedRecords+=1;let e=typeof r.url==`string`?r.url:``,i=typeof r.method==`string`?r.method:`POST`,a=typeof r.timestamp==`number`?r.timestamp:null,o=I(r);for(let s of L(r)){let r=null;M(s)?r=s:typeof s==`string`&&(r=P(s)),N(n.extracted,r,{source:t,url:e,method:i,timestamp:a,contentType:o})}o.includes(`application/graphql`)&&typeof r.body==`string`&&N(n.extracted,{query:r.body,variables:null,operationName:null},{source:t,url:e,method:i,timestamp:a,contentType:o})}return n}function z(e){let t=e.toSorted((e,t)=>(t.timestamp??0)-(e.timestamp??0)),n=[],r=new Set;for(let e of t){let t=`${e.url}|${e.operationName??``}|${e.query}|${JSON.stringify(e.variables)}`;r.has(t)||(r.add(t),n.push(e))}return n}var B=class{deps;constructor(e){this.deps=`collector`in e?e:{collector:e}}async handleGraphqlExtractQueries(e){try{let n=g(e,`limit`,50,1,200),i=await o(await this.deps.collector.getActivePage(),e=>{let t=window,n=[],r=0,i=(e,t)=>{if(!e)return;let r=e.query;if(typeof r!=`string`||r.trim().length===0)return;let i=e.operationName,a=typeof i==`string`&&i.trim().length>0?i:r.match(/^\s*(query|mutation|subscription)\s+([A-Za-z0-9_]+)/)?.[2]??null;n.push({source:t.source,url:t.url,method:t.method,operationName:a,query:r,variables:e.variables??null,timestamp:t.timestamp,contentType:t.contentType})},a=e=>{if(!e)return null;try{let t=JSON.parse(e);if(t&&typeof t==`object`&&!Array.isArray(t))return t}catch{}if(e.includes(`query=`))try{let t=new URLSearchParams(e),n=t.get(`query`);if(n){let e=t.get(`operationName`),r=t.get(`variables`),i=null;if(r)try{i=JSON.parse(r)}catch{i=r}return{query:n,operationName:e,variables:i}}}catch{}return e.startsWith(`query `)||e.startsWith(`mutation `)||e.startsWith(`subscription `)?{query:e}:null},o=(e,t)=>{r+=1;let n=typeof e.url==`string`?e.url:``,o=typeof e.method==`string`?e.method:`POST`,s=typeof e.timestamp==`number`?e.timestamp:null,c=(e.headers&&typeof e.headers==`object`&&!Array.isArray(e.headers)?e.headers:null)??(e.requestHeaders&&typeof e.requestHeaders==`object`&&!Array.isArray(e.requestHeaders)?e.requestHeaders:null)??{},l=``;for(let[e,t]of Object.entries(c))if(e.toLowerCase()===`content-type`){l=typeof t==`string`?t:String(t);break}l=l.toLowerCase();let u=[e.body,e.postData];e.options&&typeof e.options==`object`&&!Array.isArray(e.options)&&u.push(e.options.body);for(let e of u){let r=null;e&&typeof e==`object`&&!Array.isArray(e)?r=e:typeof e==`string`&&(r=a(e)),i(r,{source:t,url:n,method:o,timestamp:s,contentType:l})}l.includes(`application/graphql`)&&typeof e.body==`string`&&i({query:e.body,variables:null,operationName:null},{source:t,url:n,method:o,timestamp:s,contentType:l})},s=(e,t)=>{if(Array.isArray(e))for(let n of e)n&&typeof n==`object`&&o(n,t)},c=Array.isArray(t.__fetchRequests)?t.__fetchRequests:typeof t.__getFetchRequests==`function`?t.__getFetchRequests():void 0,l=Array.isArray(t.__xhrRequests)?t.__xhrRequests:typeof t.__getXHRRequests==`function`?t.__getXHRRequests():void 0;s(c,`window.__fetchRequests`),s(l,`window.__xhrRequests`),s(t.__networkRequests,`window.__networkRequests`);let u=t.__aiHooks;if(u&&typeof u==`object`){for(let[e,t]of Object.entries(u))if(Array.isArray(t))for(let n of t)n&&typeof n==`object`&&o(n,`window.__aiHooks.${e}`)}n.sort((e,t)=>(t.timestamp??0)-(e.timestamp??0));let d=[],f=new Set;for(let e of n){let t=`${e.url}|${e.operationName??``}|${e.query}|${JSON.stringify(e.variables)}`;f.has(t)||(f.add(t),d.push(e))}return{scannedRecords:r,totalExtracted:d.length,extracted:d.slice(0,e)}},n),a=i.scannedRecords,s=[...i.extracted];if(this.deps.consoleMonitor){let e=typeof this.deps.consoleMonitor.getFetchRequests==`function`?this.deps.consoleMonitor.getFetchRequests().catch(()=>[]):Promise.resolve([]),t=typeof this.deps.consoleMonitor.getXHRRequests==`function`?this.deps.consoleMonitor.getXHRRequests().catch(()=>[]):Promise.resolve([]),[n,r]=await Promise.all([e,t]),i=[];try{i=typeof this.deps.consoleMonitor.getNetworkRequests==`function`?this.deps.consoleMonitor.getNetworkRequests({limit:500}):[]}catch{i=[]}let o=[R(n,`consoleMonitor.fetchRequests`),R(r,`consoleMonitor.xhrRequests`),R(i,`consoleMonitor.networkRequests`)];for(let e of o)a+=e.scannedRecords,s.push(...e.extracted)}let c=z(s),l=Math.max(i.totalExtracted,c.length),u=c.slice(0,n).map((e,n)=>{let i=x(e.query,t),a=S(e.variables,r),o={index:n,source:e.source,url:e.url,method:e.method,operationName:e.operationName,contentType:e.contentType,timestamp:e.timestamp,queryLength:e.query.length,queryPreview:i.preview,queryTruncated:i.truncated};return i.truncated||(o.query=e.query),a.truncated?(o.variablesPreview=a.preview,o.variablesTruncated=!0):o.variables=e.variables,o});return p({success:!0,limit:n,stats:{scannedRecords:a,totalExtracted:l,returned:u.length},queries:u})}catch(e){return m(e)}}},V=class{collector;constructor(e){this.collector=e}async handleGraphqlReplay(e){try{let t=l(e,`endpoint`)?.trim(),n=l(e,`query`);if(!t)return m(`Missing required argument: endpoint`);if(typeof n!=`string`||n.trim().length===0)return m(`Missing required argument: query`);let r=c(e,`variables`)??{},i=l(e,`operationName`),a=i&&i.trim().length>0?i.trim():null,o=_(e.headers);if(d(e,`useBrowser`,!0)){let e=await this.collector.getActivePage(),i=await b(t,typeof e.url==`function`?e.url():null);return i?m(i):await this.replayViaBrowser(e,t,n,r,a,o)}let s=await y(t);return s?m(s):await this.replayViaNode(t,n,r,a,o)}catch(e){return m(e)}}async replayViaNode(e,t,n,r,i){let a={"content-type":`application/json`,...i},o,s;try{let i=new AbortController,c=setTimeout(()=>i.abort(),1e4);try{o=await fetch(e,{method:`POST`,headers:a,body:JSON.stringify({query:t,variables:n,operationName:r}),signal:i.signal}),s=await o.text()}finally{clearTimeout(c)}}catch(t){return p({success:!1,endpoint:e,status:0,statusText:`FETCH_ERROR`,error:t instanceof Error?t.message:String(t),operationName:r})}let c={};o.headers.forEach((e,t)=>{c[t]=e});let l=null;try{l=JSON.parse(s)}catch{l=null}return s=``,p(H(l,e,r,o.ok,o.status,o.statusText,c))}async replayViaBrowser(t,n,r,i,a,s){let c=await o(t,async e=>{let t={"content-type":`application/json`,...e.headers};try{let n=new AbortController,r=setTimeout(()=>n.abort(),1e4),i,a;try{a=await fetch(e.endpoint,{method:`POST`,headers:t,body:JSON.stringify({query:e.query,variables:e.variables,operationName:e.operationName}),signal:n.signal}),i=await a.text()}finally{clearTimeout(r)}let o=null;try{o=JSON.parse(i)}catch{o=null}let s=o===null?i:``;i=``;let c={};return a.headers.forEach((e,t)=>{c[t]=e}),{ok:a.ok,status:a.status,statusText:a.statusText,responseText:s,responseJson:o,responseHeaders:c}}catch(e){return{ok:!1,status:0,statusText:`FETCH_ERROR`,responseText:``,responseJson:null,error:e instanceof Error?e.message:String(e)}}},{endpoint:n,query:r,variables:i,operationName:a,headers:s}),l={success:c.ok,endpoint:n,status:c.status,statusText:c.statusText,operationName:a,responseHeaders:c.responseHeaders??{}};if(c.responseJson!==null){let t=S(c.responseJson,e);l.responseLength=t.totalLength,l.responsePreview=t.preview,l.responseTruncated=t.truncated,t.truncated||(l.response=c.responseJson)}else if(c.responseText){let t=c.responseText;l.responseFormat=`text`,l.responseLength=t.length,l.responsePreview=t.length>e?t.slice(0,e):t,l.responseTruncated=t.length>e}return c.error&&(l.error=c.error),p(l)}};function H(t,n,r,i,a,o,s){let c={success:i,endpoint:n,status:a,statusText:o,operationName:r,responseHeaders:s};if(t!==null){let n=S(t,e);c.responseLength=n.totalLength,c.responsePreview=n.preview,c.responseTruncated=n.truncated,n.truncated||(c.response=t)}return c}const U=new Map;function W(e){let t=U.get(e);if(t)return t;let n=`
|
|
52
52
|
query EnumSchemaTypeProbe($typeName: String!) {
|
|
53
53
|
__type(name: $typeName) {
|
|
54
54
|
fields(includeDeprecated: true) {
|
|
@@ -59,4 +59,4 @@ query EnumSchemaTypeProbe($typeName: String!) {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
`.trim();return U.set(e,n),n}function G(e){let t=e??null;for(;t;){if(typeof t.name==`string`&&t.name.length>0)return{kind:typeof t.kind==`string`?t.kind:null,name:t.name};t=t.ofType??null}return{kind:null,name:null}}function K(e){return e===`OBJECT`||e===`INTERFACE`}function q(e){return e&&typeof e.data==`object`&&e.data!==null&&`__type`in e.data?e.data.__type:null}function J(e){let t=q(e);return Array.isArray(t?.fields)?t.fields.filter(e=>typeof e==`object`&&!!e&&typeof e.name==`string`):[]}function Y(e){let t=e??null,n=0;for(;t;){if(n+=1,typeof t.name==`string`&&t.name.length>0)return null;if(!t.ofType)return t.kind===`LIST`||t.kind===`NON_NULL`?n:null;t=t.ofType??null}return null}function ie(e){let t=null;for(let n of e){let e=Y(n.type);e!==null&&(t=Math.max(t??0,e))}return t}function ae(e){let t=[],n=e??null;for(;n;)t.push(`${n.kind??``}:${n.name??``}`),n=n.ofType??null;return t.join(`>`)}function oe(e){return e.map(e=>`${e.name??``}=${ae(e.type)}`).join(`|`)}async function se(e,t,n){let r=null,i=null,a=0;for(;;){let o=await X(e,t,{query:W(a),variables:{typeName:n}});if(!q(o.record))return r;let s=J(o.record);r=s;let c=ie(s);if(c===null)return r;let l=oe(s);if(c<=a||l===i)return r;i=l,a=c}}async function X(e,t,n){let r={"content-type":`application/json`,...t};try{let t=new AbortController,i=setTimeout(()=>t.abort(),1e4);try{let i=await fetch(e,{method:`POST`,headers:r,body:JSON.stringify(n),signal:t.signal}),a=await i.text(),o=null;try{o=JSON.parse(a)}catch{o=null}let s=o&&typeof o==`object`?o:null,c=Array.isArray(s?.errors)?s.errors:[];return{ok:i.ok||c.length>0,status:i.status,statusText:i.statusText,record:s,errors:c}}finally{clearTimeout(i)}}catch(e){return{ok:!1,status:0,statusText:`FETCH_ERROR`,record:null,errors:[],error:e instanceof Error?e.message:String(e)}}}async function ce(e,t,n,r){let i=[{typeName:n,depth:0}],a=new Map,o=new Set;for(;i.length>0;){let n=i.shift();if(o.has(n.typeName))continue;o.add(n.typeName);let s=await se(e,t,n.typeName);if(!s)return a.size>0?a:null;if(a.set(n.typeName,s.map(e=>e.name?.trim()??``).filter(e=>e.length>0)),!(n.depth+1>=r))for(let e of s){let t=G(e.type);!t.name||!K(t.kind)||o.has(t.name)||i.push({typeName:t.name,depth:n.depth+1})}}return a}const le=/Cannot query field\s+"[^"]+"\s+on type\s+"([^"]+)".*?Did you mean\s+(.+?)\?/i,ue=/"([^"]+)"/g,Z=`__jshook_probe__`;function de(e){let t=le.exec(e);if(!t)return null;let[,n,r]=t;if(!n||!r)return null;let i=Array.from(r.matchAll(ue),e=>e[1]??``).filter(e=>e.length>0);return i.length>0?{typeName:n,suggestions:i}:null}function Q(e){return e.length===0?`query EnumSchemaProbe { ${Z} }`:`query EnumSchemaProbe { ${e.join(` { `)} { ${Z} }${`}`.repeat(e.length)} }`}function $(
|
|
62
|
+
`.trim();return U.set(e,n),n}function G(e){let t=e??null;for(;t;){if(typeof t.name==`string`&&t.name.length>0)return{kind:typeof t.kind==`string`?t.kind:null,name:t.name};t=t.ofType??null}return{kind:null,name:null}}function K(e){return e===`OBJECT`||e===`INTERFACE`}function q(e){return e&&typeof e.data==`object`&&e.data!==null&&`__type`in e.data?e.data.__type:null}function J(e){let t=q(e);return Array.isArray(t?.fields)?t.fields.filter(e=>typeof e==`object`&&!!e&&typeof e.name==`string`):[]}function Y(e){let t=e??null,n=0;for(;t;){if(n+=1,typeof t.name==`string`&&t.name.length>0)return null;if(!t.ofType)return t.kind===`LIST`||t.kind===`NON_NULL`?n:null;t=t.ofType??null}return null}function ie(e){let t=null;for(let n of e){let e=Y(n.type);e!==null&&(t=Math.max(t??0,e))}return t}function ae(e){let t=[],n=e??null;for(;n;)t.push(`${n.kind??``}:${n.name??``}`),n=n.ofType??null;return t.join(`>`)}function oe(e){return e.map(e=>`${e.name??``}=${ae(e.type)}`).join(`|`)}async function se(e,t,n){let r=null,i=null,a=0;for(;;){let o=await X(e,t,{query:W(a),variables:{typeName:n}});if(!q(o.record))return r;let s=J(o.record);r=s;let c=ie(s);if(c===null)return r;let l=oe(s);if(c<=a||l===i)return r;i=l,a=c}}async function X(e,t,n){let r={"content-type":`application/json`,...t};try{let t=new AbortController,i=setTimeout(()=>t.abort(),1e4);try{let i=await fetch(e,{method:`POST`,headers:r,body:JSON.stringify(n),signal:t.signal}),a=await i.text(),o=null;try{o=JSON.parse(a)}catch{o=null}let s=o&&typeof o==`object`?o:null,c=Array.isArray(s?.errors)?s.errors:[];return{ok:i.ok||c.length>0,status:i.status,statusText:i.statusText,record:s,errors:c}}finally{clearTimeout(i)}}catch(e){return{ok:!1,status:0,statusText:`FETCH_ERROR`,record:null,errors:[],error:e instanceof Error?e.message:String(e)}}}async function ce(e,t,n,r){let i=[{typeName:n,depth:0}],a=new Map,o=new Set;for(;i.length>0;){let n=i.shift();if(o.has(n.typeName))continue;o.add(n.typeName);let s=await se(e,t,n.typeName);if(!s)return a.size>0?a:null;if(a.set(n.typeName,s.map(e=>e.name?.trim()??``).filter(e=>e.length>0)),!(n.depth+1>=r))for(let e of s){let t=G(e.type);!t.name||!K(t.kind)||o.has(t.name)||i.push({typeName:t.name,depth:n.depth+1})}}return a}const le=/Cannot query field\s+"[^"]+"\s+on type\s+"([^"]+)".*?Did you mean\s+(.+?)\?/i,ue=/"([^"]+)"/g,Z=`__jshook_probe__`;function de(e){let t=le.exec(e);if(!t)return null;let[,n,r]=t;if(!n||!r)return null;let i=Array.from(r.matchAll(ue),e=>e[1]??``).filter(e=>e.length>0);return i.length>0?{typeName:n,suggestions:i}:null}function Q(e){return e.length===0?`query EnumSchemaProbe { ${Z} }`:`query EnumSchemaProbe { ${e.join(` { `)} { ${Z} }${`}`.repeat(e.length)} }`}function $(t){let n=t.discovered.get(t.parentType)??t.discovered.get(t.typeName)??[],r=JSON.stringify({rootType:t.typeName,parentType:t.parentType,fields:n},null,2);return p({success:!0,endpoint:t.endpoint,typeName:t.typeName,parentType:t.parentType,maxDepth:t.maxDepth,concurrency:t.concurrency,fields:n,discoveredTypes:Object.fromEntries(Array.from(t.discovered.entries()).filter(([e])=>!e.includes(`.`))),responsePreview:r.length>e?`${r.slice(0,e)}\n... (truncated)`:r})}var fe=class{async handleGraphqlEnumSchema(e){try{let t=l(e,`endpoint`)?.trim();if(!t)return m(`Missing required argument: endpoint`);let n=await y(t);if(n)return m(n);let r=_(e.headers),i=l(e,`typeName`,`Query`)?.trim()||`Query`,a=l(e,`parentType`,i)?.trim()||i,o=u(e,`maxDepth`,1)??1,s=Math.min(Math.max(Math.trunc(o),1),6),c=u(e,`concurrency`,3)??3,d=Math.min(Math.max(Math.trunc(c),1),10),f=await X(t,r,{query:Q([])});if(!f.ok)return p({success:!1,endpoint:t,typeName:i,parentType:a,status:f.status,statusText:f.statusText,error:f.error??`Schema enumeration request failed`});let h=this.extractSuggestions(f.errors);if(!h)return $({endpoint:t,typeName:i,parentType:a,maxDepth:s,concurrency:d,discovered:await ce(t,r,a,s)??new Map([[a,[]]])});let g=[],v=new Map;if(v.set(h.typeName,h.suggestions),s>1)for(let e of h.suggestions){let t=[e],n=t.join(`.`);v.has(n)||(v.set(n,[]),g.push({path:t,depth:1,typeName:e}))}for(;g.length>0;){let e=g.shift(),n=await X(t,r,{query:Q(e.path)});if(!n.ok)return p({success:!1,endpoint:t,typeName:i,parentType:a,status:n.status,statusText:n.statusText,error:n.error??`Schema enumeration request failed`});let o=this.extractSuggestions(n.errors);if(!o){v.set(e.typeName,[]);continue}if(v.set(o.typeName,o.suggestions),!(e.depth+1>=s))for(let t of o.suggestions){let n=[...e.path,t],r=n.join(`.`);v.has(r)||(v.set(r,[]),g.push({path:n,depth:e.depth+1,typeName:t}))}}return $({endpoint:t,typeName:i,parentType:a,maxDepth:s,concurrency:d,discovered:v})}catch(e){return m(e)}}extractSuggestions(e){for(let t of e){if(typeof t.message!=`string`)continue;let e=de(t.message);if(e)return e}return null}};function pe(e){return`collector`in e?e:{collector:e}}var me=class{callGraph;scriptReplace;introspection;extract;replay;schemaEnum;constructor(e){let t=pe(e);this.callGraph=new A(t.collector),this.scriptReplace=new j(t.collector),this.introspection=new re(t.collector),this.extract=new B(t),this.replay=new V(t.collector),this.schemaEnum=new fe}async handleCallGraphAnalyze(e){return this.callGraph.handleCallGraphAnalyze(e)}async handleScriptReplacePersist(e){return this.scriptReplace.handleScriptReplacePersist(e)}async handleGraphqlIntrospect(e){return this.introspection.handleGraphqlIntrospect(e)}async handleGraphqlExtractQueries(e){return this.extract.handleGraphqlExtractQueries(e)}async handleGraphqlReplay(e){return this.replay.handleGraphqlReplay(e)}async handleGraphqlEnumSchema(e){return this.schemaEnum.handleGraphqlEnumSchema(e)}};export{me as GraphQLToolHandlers};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{n as e}from"./response-C7rKQst4.mjs";import{a as t,c as n,i as r,l as i,n as a,o,r as s,s as c}from"./boringssl-inspector-BBaJwwkU.mjs";import{a as l,n as u,o as d,r as f,t as p}from"./parse-args-Bw413PlW.mjs";import{a as m,s as h}from"./ssrf-policy-CsIJGkpd.mjs";import{X509Certificate as g,createHash as _,randomBytes as v,randomUUID as y}from"node:crypto";import{readFile as b}from"node:fs/promises";import{createSocket as x}from"node:dgram";import{Socket as S,createServer as C,isIP as w}from"node:net";import{checkServerIdentity as T,connect as E}from"node:tls";const D=new Set([`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`]);function O(e){return e instanceof Error?e.message:String(e)}function k(e){return e.replace(/\s+/g,``).toUpperCase()}function A(e){return e.length>0&&e.length%2==0&&/^[0-9A-F]+$/i.test(e)}function j(e){return h(e)&&!m(e)?{ok:!1,error:`Blocked: target host "${e}" resolves to a private/internal address. SSRF protection applies.`}:null}function M(e){return typeof e==`string`&&e.length>0?e:null}function N(e){return typeof e==`string`&&e.length>0?e:null}function P(e,t){let n={...e};return Reflect.set(n,`rejectUnauthorized`,!t),n}async function F(e){let t=l(e,`caPem`)??null,n=l(e,`caPath`)??null;if(t&&n)return{ok:!1,error:`caPem and caPath are mutually exclusive`};if(t)return{ok:!0,ca:t,source:`inline`,path:null,bytes:Buffer.byteLength(t)};if(n)try{let e=await b(n,`utf8`);return{ok:!0,ca:e,source:`path`,path:n,bytes:Buffer.byteLength(e)}}catch(e){return{ok:!1,error:`Failed to read caPath "${n}": ${O(e)}`}}return{ok:!0,ca:void 0,source:null,path:null,bytes:null}}function I(e){return typeof e==`object`&&!!e&&Object.keys(e).length>0}function L(e){return I(e)}function R(e,t){let n=Buffer.isBuffer(e.raw)?e.raw:null,r=n?new g(n):null,i=r?.subject??null,a=r?.issuer??null;return{depth:t,subject:i,issuer:a,subjectAltName:r?.subjectAltName??e.subjectaltname??null,serialNumber:r?.serialNumber??e.serialNumber??null,validFrom:r?.validFrom??e.valid_from??null,validTo:r?.validTo??e.valid_to??null,fingerprint256:r?.fingerprint256??e.fingerprint256??null,fingerprint512:r?.fingerprint512??e.fingerprint512??null,rawLength:n?.length??null,isCA:r?.ca??e.ca??null,selfIssued:i&&a?i===a:null}}function z(e){if(!e)return[];let t=[],n=new Set,r=e,i=0;for(;r&&L(r);){let e=R(r,i),a=e.fingerprint256??`${e.subject??`unknown-subject`}:${e.serialNumber??`unknown-serial`}:${i}`;if(n.has(a)||(n.add(a),t.push(e),!(`issuerCertificate`in r)))break;let o=r.issuerCertificate;if(!o||o===r||!L(o))break;r=o,i+=1}return t}function B(e){let t=_(`sha256`).update(e).digest(`hex`).toUpperCase();try{let n=new g(e);return{subject:n.subject||void 0,issuer:n.issuer||void 0,serialNumber:n.serialNumber||void 0,validFrom:n.validFrom||void 0,validTo:n.validTo||void 0,sha256:t,length:e.length}}catch{return{sha256:t,length:e.length}}}function V(e){let t=Buffer.from(k(e),`hex`),n=[],r=0;for(;r<t.length-4;)if(t[r]===48){let e=B(t.subarray(r));n.push({sha256:e.sha256,length:e.length}),r+=e.length}else r+=1;return n.length===0&&t.length>0&&n.push({sha256:_(`sha256`).update(t).digest(`hex`).toUpperCase(),length:t.length}),n}function H(e){return`${e}_${y()}`}function U(e){return{localAddress:e.localAddress??null,localPort:e.localPort??null,remoteAddress:e.remoteAddress??null,remotePort:e.remotePort??null}}function W(e){return{bufferedBytes:e.buffer.length,remoteEnded:e.ended,socketClosed:e.closed,error:e.error}}function G(e){for(let t of e.waiters)t();e.waiters.clear()}function K(e){e.socket.on(`data`,t=>{e.buffer=Buffer.concat([e.buffer,t]),G(e)}),e.socket.on(`end`,()=>{e.ended=!0,G(e)}),e.socket.on(`close`,()=>{e.closed=!0,G(e)}),e.socket.on(`error`,t=>{e.error=t.message,G(e)})}function ee(e,t){return new Promise(n=>{let r=()=>{clearTimeout(i),e.waiters.delete(r),n(!0)},i=setTimeout(()=>{e.waiters.delete(r),n(!1)},t);e.waiters.add(r)})}function te(e,t,n,r){let i=t?t.toString(`hex`).toUpperCase():null;if(t){let r=e.buffer.indexOf(t);if(r>=0){let a=r+t.length,o=n?e.buffer.subarray(0,a):e.buffer.subarray(0,r);return e.buffer=e.buffer.subarray(a),{data:o,matchedDelimiter:!0,stopReason:`delimiter`,delimiterHex:i}}}if(typeof r==`number`&&e.buffer.length>=r){let t=e.buffer.subarray(0,r);return e.buffer=e.buffer.subarray(r),{data:t,matchedDelimiter:!1,stopReason:`maxBytes`,delimiterHex:i}}if((e.error||e.ended||e.closed)&&e.buffer.length>0){let t=e.buffer;return e.buffer=Buffer.alloc(0),{data:t,matchedDelimiter:!1,stopReason:e.error?`error`:`closed`,delimiterHex:i}}return null}function q(e){return{bufferedBytes:e.parserBuffer.length,queuedFrames:e.frames.length,remoteEnded:e.ended,socketClosed:e.closed,closeSent:e.closeSent,closeReceived:e.closeReceived,error:e.error}}function J(e){return!e||e.trim().length===0?`/`:e.startsWith(`/`)?e:`/${e}`}function ne(e){return{1:`text`,2:`binary`,8:`close`,9:`ping`,10:`pong`}[e]??null}function re(e){return _(`sha1`).update(`${e}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`,`utf8`).digest(`base64`)}function Y(e,t,n,r){let i={text:1,binary:2,close:8,ping:9,pong:10},a=t;if(e===`close`)if(n!=null){let e=r?Buffer.from(r,`utf8`):Buffer.alloc(0);a=Buffer.alloc(2+e.length),a.writeUInt16BE(n,0),e.copy(a,2)}else r&&(a=Buffer.from(r,`utf8`));let o=v(4),s=a.length,c;s<126?(c=Buffer.alloc(2),c[1]=128|s):s<=65535?(c=Buffer.alloc(4),c[1]=254,c.writeUInt16BE(s,2)):(c=Buffer.alloc(10),c[1]=255,c.writeBigUInt64BE(BigInt(s),2)),c[0]=128|i[e];let l=Buffer.alloc(s);for(let e=0;e<s;e+=1)l[e]=a[e]^o[e%4];return Buffer.concat([c,o,l])}function ie(e){if(e.length<2)return null;let t=e[0],n=e[1],r=(t&128)!=0,i=t&15,a=(n&128)!=0,o=n&127,s=2;if(o===126){if(e.length<s+2)return null;o=e.readUInt16BE(s),s+=2}else if(o===127){if(e.length<s+8)return null;let t=e.readBigUInt64BE(s);if(t>BigInt(2**53-1))throw Error(`WebSocket frame payload length exceeds supported limits`);o=Number(t),s+=8}let c=a?e.subarray(s,s+4):null;if(a){if(e.length<s+4)return null;s+=4}if(e.length<s+o)return null;let l=e.subarray(s,s+o),u=Buffer.alloc(l.length);if(a&&c)for(let e=0;e<l.length;e+=1)u[e]=l[e]^c[e%4];else l.copy(u);let d=ne(i);if(!d)throw Error(`Unsupported WebSocket opcode 0x${i.toString(16)}`);let f=null,p=null;return d===`close`&&u.length>=2&&(f=u.readUInt16BE(0),p=u.subarray(2).toString(`utf8`)),{frame:{type:d,fin:r,opcode:i,masked:a,data:u,closeCode:f,closeReason:p,receivedAt:Date.now()},bytesConsumed:s+o}}function X(e){for(let t of e.waiters)t();e.waiters.clear()}function ae(e,t){return new Promise(n=>{let r=()=>{clearTimeout(i),e.waiters.delete(r),n(!0)},i=setTimeout(()=>{e.waiters.delete(r),n(!1)},t);e.waiters.add(r)})}const oe={"3:1":`TLS 1.0`,"3:2":`TLS 1.1`,"3:3":`TLS 1.2`,"3:4":`TLS 1.3`},se={20:`change_cipher_spec`,21:`alert`,22:`handshake`,23:`application_data`,24:`heartbeat`},ce={156:`TLS_RSA_WITH_AES_128_GCM_SHA256`,157:`TLS_RSA_WITH_AES_256_GCM_SHA384`,52392:`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,52393:`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`,4865:`TLS_AES_128_GCM_SHA256`,4866:`TLS_AES_256_GCM_SHA384`,4867:`TLS_CHACHA20_POLY1305_SHA256`,4868:`TLS_AES_128_CCM_SHA256`,4869:`TLS_AES_128_CCM_8_SHA256`,49195:`TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`,49196:`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`,49199:`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,49200:`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`},le={0:`server_name`,1:`max_fragment_length`,5:`status_request`,10:`supported_groups`,13:`signature_algorithms`,16:`application_layer_protocol_negotiation`,18:`signed_certificate_timestamp`,23:`record_size_limit`,27:`compress_certificate`,35:`session_ticket`,43:`supported_versions`,44:`cookie`,45:`psk_key_exchange_modes`,49:`post_handshake_auth`,51:`key_share`};function Z(e,t){return oe[`${e}:${t}`]??`0x${e.toString(16).padStart(2,`0`)}${t.toString(16).padStart(2,`0`)}`}function Q(e){return se[e]??`unknown`}function ue(e){let t={cipherSuites:[],extensions:[]},n=e[0]!==void 0&&e[0]<25?4:0;if(e.length<n+38)return t;let r=n+34,i=e[r]??0,a=r+1+i;if(a+2>e.length)return t;let o=e.readUInt16BE(a);a+=2;let s=a+o;for(;a+2<=s;){let n=e.readUInt16BE(a);t.cipherSuites.push(ce[n]??`0x${n.toString(16).padStart(4,`0`)}`),a+=2}if(a=s+1,a<e.length){let t=e[a];t!==void 0&&(a+=1+t)}if(a+2<=e.length){let n=e.readUInt16BE(a);a+=2;let r=a+n;for(;a+4<=r;){let n=e.readUInt16BE(a),i=e.readUInt16BE(a+2);a+=4;let o=le[n]??`unknown(0x${n.toString(16)})`;if(t.extensions.push({type:n,name:o,length:i}),n===0&&a+2<=r){let n=a+2;if(n+3<=r&&e[n]===0){let i=e.readUInt16BE(n+1),a=n+3;a+i<=r&&(t.serverName=e.subarray(a,a+i).toString(`utf8`))}}a+=i}}return t}var de=class{keyLogExtractor;extensionInvoke;eventBus;tcpSessions=new Map;tlsSessions=new Map;websocketSessions=new Map;constructor(e=new a){this.keyLogExtractor=e}setExtensionInvoke(e){this.extensionInvoke=e}setEventBus(e){this.eventBus=e}getTcpSession(e){return this.tcpSessions.get(e)??null}getTlsSession(e){return this.tlsSessions.get(e)??null}getWebSocketSession(e){return this.websocketSessions.get(e)??null}parseWritePayload(e){let t=l(e,`dataHex`),n=l(e,`dataText`);if(!t&&!n)return{ok:!1,error:`dataHex or dataText is required`};if(t&&n)return{ok:!1,error:`dataHex and dataText are mutually exclusive`};if(t){let e=k(t);return A(e)?{ok:!0,data:Buffer.from(e,`hex`),inputEncoding:`hex`}:{ok:!1,error:`dataHex must be valid even-length hexadecimal data`}}return{ok:!0,data:Buffer.from(n??``,`utf8`),inputEncoding:`utf8`}}async writeBufferedSession(e,t){if(e.socket.destroyed||e.closed)return{ok:!1,error:`Session "${e.id}" is already closed`,sessionId:e.id,kind:e.kind,state:W(e)};let n=this.parseWritePayload(t);if(!n.ok)return{ok:!1,error:n.error,sessionId:e.id,kind:e.kind};let r=f(t,`timeoutMs`)??5e3;return!Number.isFinite(r)||r<=0?{ok:!1,error:`timeoutMs must be a positive number`}:new Promise(t=>{let i=!1,a=n=>{i||(i=!0,clearTimeout(o),e.socket.off(`error`,s),t(n))},o=setTimeout(()=>{a({ok:!1,error:`write timed out`,sessionId:e.id,kind:e.kind,state:W(e)})},r),s=t=>{a({ok:!1,error:t.message,sessionId:e.id,kind:e.kind,state:W(e)})};e.socket.once(`error`,s),e.socket.write(n.data,()=>{e.kind===`tcp`?this.eventBus?.emit(`tcp:session_written`,{sessionId:e.id,byteLength:n.data.length,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_written`,{sessionId:e.id,byteLength:n.data.length,timestamp:new Date().toISOString()}),a({ok:!0,sessionId:e.id,kind:e.kind,inputEncoding:n.inputEncoding,bytesWritten:n.data.length,transport:U(e.socket),state:W(e)})})})}async readBufferedSessionUntil(e,t){let n=l(t,`delimiterHex`),r=l(t,`delimiterText`);if(n&&r)return{ok:!1,error:`delimiterHex and delimiterText are mutually exclusive`};let i=null;if(n){let e=k(n);if(!A(e))return{ok:!1,error:`delimiterHex must be valid even-length hexadecimal data`};i=Buffer.from(e,`hex`)}else r!==void 0&&(i=Buffer.from(r,`utf8`));if(i&&i.length===0)return{ok:!1,error:`delimiter must not be empty`};let a=p(t,`includeDelimiter`)??!0,o=f(t,`maxBytes`),s=o===void 0?void 0:Math.trunc(o);if(s!==void 0&&(!Number.isFinite(s)||s<=0))return{ok:!1,error:`maxBytes must be a positive integer when provided`};if(!i&&s===void 0)return{ok:!1,error:`delimiterHex, delimiterText, or maxBytes is required`};let c=f(t,`timeoutMs`)??5e3;if(!Number.isFinite(c)||c<=0)return{ok:!1,error:`timeoutMs must be a positive number`};if(e.activeRead)return{ok:!1,error:`Session "${e.id}" already has a pending read`,sessionId:e.id,kind:e.kind,state:W(e)};e.activeRead=!0;let u=Date.now();try{for(;;){let t=te(e,i,a,s);if(t)return e.kind===`tcp`?this.eventBus?.emit(`tcp:session_read`,{sessionId:e.id,byteLength:t.data.length,matched:t.matchedDelimiter,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_read`,{sessionId:e.id,byteLength:t.data.length,matched:t.matchedDelimiter,timestamp:new Date().toISOString()}),{ok:!0,sessionId:e.id,kind:e.kind,bytesRead:t.data.length,matchedDelimiter:t.matchedDelimiter,stopReason:t.stopReason,delimiterHex:t.delimiterHex,dataHex:t.data.toString(`hex`).toUpperCase(),dataText:t.data.toString(`utf8`),elapsedMs:Date.now()-u,state:W(e)};if(e.error)return{ok:!1,error:e.error,sessionId:e.id,kind:e.kind,state:W(e)};if(e.ended||e.closed)return{ok:!1,error:`socket closed before the requested read condition was satisfied`,sessionId:e.id,kind:e.kind,state:W(e)};let n=c-(Date.now()-u);if(n<=0||!await ee(e,n))return{ok:!1,error:`read timed out`,sessionId:e.id,kind:e.kind,state:W(e)}}}finally{e.activeRead=!1}}async closeBufferedSession(e,t,n,r){let i=t.get(e);if(!i)return{ok:!1,error:`Unknown ${n} sessionId "${e}"`};let a=p(r,`force`)??!1,o=f(r,`timeoutMs`)??1e3;if(!Number.isFinite(o)||o<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let s=i.buffer.length;return i.closed||i.socket.destroyed?(t.delete(e),{ok:!0,sessionId:e,kind:n,force:a,closed:!0,bufferedBytesDiscarded:s,state:W(i)}):new Promise(r=>{let c=!1,l=o=>{c||(c=!0,clearTimeout(f),i.socket.off(`close`,u),i.socket.off(`error`,d),t.delete(e),n===`tcp`?this.eventBus?.emit(`tcp:session_closed`,{sessionId:e,reason:i.error,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_closed`,{sessionId:e,reason:i.error,timestamp:new Date().toISOString()}),r({ok:!0,sessionId:e,kind:n,force:a,closed:o,bufferedBytesDiscarded:s,state:W(i)}))},u=()=>l(!0),d=()=>l(i.socket.destroyed||i.closed),f=setTimeout(()=>{i.socket.destroy(),l(i.socket.destroyed||i.closed)},o);if(i.socket.once(`close`,u),i.socket.once(`error`,d),a){i.socket.destroy();return}i.socket.end()})}},fe=class extends de{async handleTlsKeylogEnable(e){return{enabled:!0,keyLogPath:await this.keyLogExtractor.enableKeyLog(),environmentVariable:`SSLKEYLOGFILE`}}async handleTlsKeylogDisable(e){let t=l(e,`path`)??null;return t?await this.keyLogExtractor.disableKeyLog():r(),{disabled:!0,previousPath:t??o()}}async handleTlsKeylogParse(e){let t=l(e,`path`)??null,n=this.keyLogExtractor.parseKeyLog(t??void 0),r=this.keyLogExtractor.summarizeKeyLog(t??void 0);return{path:t??this.keyLogExtractor.getKeyLogFilePath(),entries:n,summary:r}}async handleTlsDecryptPayload(e){let t=l(e,`encryptedHex`)??null,n=l(e,`keyHex`)??null,r=l(e,`nonceHex`)??null,i=l(e,`algorithm`)??`aes-256-gcm`,a=l(e,`authTagHex`)??null;if(!t||!n||!r)return{ok:!1,error:`encryptedHex, keyHex, and nonceHex are required`};let o=s(t,n,r,i,a??void 0);return{ok:!0,algorithm:i,decrypted:o,isFailed:o.startsWith(`DECRYPTION_FAILED:`)}}async handleTlsKeylogSummarize(e){let t=l(e,`content`)??null;return t?i(n(t)):(this.keyLogExtractor.parseKeyLog(),this.keyLogExtractor.summarizeKeyLog())}async handleTlsKeylogLookupSecret(e){let t=l(e,`clientRandom`)??null,n=l(e,`label`)??void 0;if(!t)return{ok:!1,error:`clientRandom is required`};let r=this.keyLogExtractor.lookupSecret(t);if(r)return{ok:!0,clientRandom:k(t),secret:r};let i=c(this.keyLogExtractor.parseKeyLog(),t,n);return{ok:i!==null,clientRandom:k(t),secret:i??null}}async handleTlsCertPinBypass(e){let t=l(e,`target`)??null;return t!==`android`&&t!==`ios`&&t!==`desktop`?{error:`target must be one of android, ios, or desktop`}:{bypassStrategy:{android:`hook-trust-manager`,ios:`replace-sec-trust-evaluation`,desktop:`patch-custom-verifier`}[t],affectedDomains:[`*`],instructions:{android:[`Inject a Frida script that overrides X509TrustManager checks.`,`Re-run the target flow after SSLKEYLOGFILE capture is enabled.`],ios:[`Hook SecTrustEvaluateWithError and return success for the target session.`,`Collect TLS keys after the app resumes the failing request.`],desktop:[`Patch the custom verifier callback or disable pin comparison in the client.`,`Capture a fresh handshake after the patched build starts.`]}[t]}}async handleParseHandshake(t){let n=l(t,`rawHex`)??null,r=t.decrypt===!0;if(!n)return e({success:!1,error:`rawHex is required`});let i=k(n);if(!/^(?:[0-9a-f]{2})+$/i.test(i))return e({success:!1,error:`Invalid hex payload`});let a=Buffer.from(i,`hex`);if(a.length<5)return e({success:!1,error:`TLS record is too short`});let o=a[0],s=a[1],c=a[2],u=a.readUInt16BE(3),d=a.subarray(5),f=o===22&&d.length>0&&d[0]===1?ue(d):void 0,p=r?(()=>{let e=this.keyLogExtractor.decryptPayload(i,this.keyLogExtractor.parseKeyLog());return e?e.subarray(0,16).toString(`hex`).toUpperCase():null})():void 0;return e({success:!0,record:{contentType:o,contentTypeName:Q(o),version:Z(s,c),declaredLength:u,actualLength:d.length},handshake:{version:Z(s,c),contentType:Q(o),...f?{type:`client_hello`,serverName:f.serverName,cipherSuites:f.cipherSuites,extensions:f.extensions}:{cipherSuite:[],extensions:[]}},sni:f?.serverName?{serverName:f.serverName}:void 0,...p===void 0?{}:{decryptedPreviewHex:p}})}async handleKeyLogEnable(n){let r=l(n,`filePath`)??`/tmp/sslkeylog.log`;return t(r),this.eventBus?.emit(`tls:keylog_started`,{filePath:r,timestamp:new Date().toISOString()}),e({success:!0,filePath:r,currentFilePath:o()})}async handleCipherSuites(t){let n=l(t,`filter`)??null,r=[`TLS_AES_128_GCM_SHA256`,`TLS_AES_256_GCM_SHA384`,`TLS_CHACHA20_POLY1305_SHA256`,`TLS_AES_128_CCM_SHA256`,`TLS_AES_128_CCM_8_SHA256`,`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`,`TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`,`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`,`TLS_RSA_WITH_AES_128_GCM_SHA256`,`TLS_RSA_WITH_AES_256_GCM_SHA384`],i=n?r.filter(e=>e.includes(n)):r;return e({success:!0,filter:n,total:i.length,suites:i})}async handleParseCertificate(t){let n=l(t,`rawHex`)??null;if(!n)return e({success:!1,error:`rawHex is required`});let r=V(n);return e({success:!0,certificateCount:r.length,fingerprints:r.map(e=>({sha256:e.sha256,length:e.length}))})}};const $=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var pe=class extends fe{async handleTlsProbeEndpoint(e){let t=l(e,`host`)?.trim()??null;if(!t)return{ok:!1,error:`host is required`};let n=f(e,`port`)??443;if(!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`allowInvalidCertificates`)??!1,a=p(e,`skipHostnameCheck`)??!1,o=l(e,`servername`)?.trim()??null,s=[...new Set(d(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),c,m;try{c=u(e,`minVersion`,D),m=u(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(c&&m&&$.indexOf(c)>$.indexOf(m))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let h=j(t);if(h)return h;let g=await F(e);if(!g.ok)return{ok:!1,error:g.error};let _=o??t,v=o??(w(t)===0?t:void 0),y=Date.now();return new Promise(e=>{let o=!1,l=E(P({host:t,port:n,servername:v,...c?{minVersion:c}:{},...m?{maxVersion:m}:{},...s.length>0?{ALPNProtocols:s}:{},...g.ca?{ca:g.ca}:{}},i)),u=t=>{o||(o=!0,clearTimeout(d),l.removeAllListeners(),l.destroy(),e(t))},d=setTimeout(()=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS probe timed out`,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}}})},r);l.once(`error`,e=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:e.message,errorCode:e.code??null,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}}})}),l.once(`secureConnect`,()=>{let e=Date.now()-y,o=l.getPeerCertificate(!0),d=L(o),f=d?z(o):[],p=f[0]??null,h=a||!d?void 0:T(_,o),b={checked:!a,target:a?null:_,matched:a?null:h===void 0,error:!a&&!d?`Peer certificate was not presented by the server`:h?.message??null},x=[l.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${l.authorizationError??`unknown_authority`}`,a?`Hostname validation was skipped by request.`:b.matched?`Hostname validation passed.`:`Hostname validation failed: ${b.error??`unknown_error`}`,!l.authorized&&i?`Policy allowed the probe to continue despite certificate trust failure.`:null].filter(e=>!!e),S=l.getCipher();this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!0,timestamp:new Date().toISOString()}),u({ok:!0,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}},transport:{protocol:l.getProtocol()??null,alpnProtocol:N(l.alpnProtocol),cipher:{name:S.name,standardName:S.standardName,version:S.version},localAddress:l.localAddress??null,localPort:l.localPort??null,remoteAddress:l.remoteAddress??null,remotePort:l.remotePort??null,servernameSent:M(l.servername),sessionReused:l.isSessionReused()},authorization:{socketAuthorized:l.authorized,authorizationError:typeof l.authorizationError==`string`?l.authorizationError:l.authorizationError?.message??null,hostnameValidation:b,policyAllowed:(l.authorized||i)&&(a||b.matched===!0),reasons:x},certificates:{leaf:p,chain:f},timing:{handshakeMs:e}})})})}};const me=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var he=class extends pe{async handleTcpOpen(e){let t=l(e,`host`)??`127.0.0.1`,n=f(e,`port`);if(n===void 0||!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`noDelay`)??!0;return j(t)||new Promise(e=>{let a=!1,o=new S,s=t=>{a||(a=!0,clearTimeout(c),o.off(`connect`,u),o.off(`error`,l),e(t))},c=setTimeout(()=>{o.destroy(),s({ok:!1,error:`TCP connect timed out`,target:{host:t,port:n}})},r),l=e=>{s({ok:!1,error:e.message,target:{host:t,port:n}})},u=()=>{o.setNoDelay(i);let e=H(`tcp`),r={id:e,kind:`tcp`,socket:o,host:t,port:n,createdAt:Date.now(),buffer:Buffer.alloc(0),ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1};K(r),this.tcpSessions.set(e,r),this.eventBus?.emit(`tcp:session_opened`,{sessionId:e,host:t,port:n,timestamp:new Date().toISOString()}),s({ok:!0,sessionId:e,kind:`tcp`,target:{host:t,port:n},createdAt:new Date(r.createdAt).toISOString(),transport:U(o),state:W(r)})};o.once(`connect`,u),o.once(`error`,l),o.connect(n,t)})}async handleTcpWrite(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTcpSession(t);return n?this.writeBufferedSession(n,e):{ok:!1,error:`Unknown tcp sessionId "${t}"`}}async handleTcpReadUntil(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTcpSession(t);return n?this.readBufferedSessionUntil(n,e):{ok:!1,error:`Unknown tcp sessionId "${t}"`}}async handleTcpClose(e){let t=l(e,`sessionId`)?.trim()??null;return t?this.closeBufferedSession(t,this.tcpSessions,`tcp`,e):{ok:!1,error:`sessionId is required`}}async handleTlsOpen(e){let t=l(e,`host`)?.trim()??null;if(!t)return{ok:!1,error:`host is required`};let n=f(e,`port`)??443;if(!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`allowInvalidCertificates`)??!1,a=p(e,`skipHostnameCheck`)??!1,o=l(e,`servername`)?.trim()??null,s=[...new Set(d(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),c,m;try{c=u(e,`minVersion`,D),m=u(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(c&&m&&me.indexOf(c)>me.indexOf(m))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let h=j(t);if(h)return h;let g=await F(e);if(!g.ok)return{ok:!1,error:g.error};let _={host:t,port:n,requestedServername:o??(w(t)===0?t:void 0)??null,validationTarget:o??t},v={allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}},y=Date.now();return new Promise(e=>{let o=!1,l=E(P({host:t,port:n,servername:_.requestedServername??void 0,...c?{minVersion:c}:{},...m?{maxVersion:m}:{},...s.length>0?{ALPNProtocols:s}:{},...g.ca?{ca:g.ca}:{}},i)),u=t=>{o||(o=!0,clearTimeout(d),l.off(`error`,f),l.off(`secureConnect`,p),e(t))},d=setTimeout(()=>{l.destroy(),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS open timed out`,target:_,policy:v})},r),f=e=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:e.message,errorCode:e.code??null,target:_,policy:v})},p=()=>{let e=Date.now()-y,r=l.getPeerCertificate(!0),o=L(r),s=o?z(r):[],c=s[0]??null,d=a||!o?void 0:T(_.validationTarget,r),f={checked:!a,target:a?null:_.validationTarget,matched:a?null:d===void 0,error:!a&&!o?`Peer certificate was not presented by the server`:d?.message??null},p=[l.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${l.authorizationError??`unknown_authority`}`,a?`Hostname validation was skipped by request.`:f.matched?`Hostname validation passed.`:`Hostname validation failed: ${f.error??`unknown_error`}`,!l.authorized&&i?`Policy allowed the session to continue despite certificate trust failure.`:null].filter(e=>!!e),m=l.getCipher(),h={target:_,policy:v,transport:{protocol:l.getProtocol()??null,alpnProtocol:N(l.alpnProtocol),cipher:{name:m.name,standardName:m.standardName,version:m.version},localAddress:l.localAddress??null,localPort:l.localPort??null,remoteAddress:l.remoteAddress??null,remotePort:l.remotePort??null,servernameSent:M(l.servername),sessionReused:l.isSessionReused()},authorization:{socketAuthorized:l.authorized,authorizationError:typeof l.authorizationError==`string`?l.authorizationError:l.authorizationError?.message??null,hostnameValidation:f,policyAllowed:(l.authorized||i)&&(a||f.matched===!0),reasons:p},certificates:{leaf:c,chain:s}};if(!h.authorization.policyAllowed){l.destroy(),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS session authorization failed`,...h,timing:{handshakeMs:e}});return}let g=H(`tls`),b={id:g,kind:`tls`,socket:l,host:t,port:n,createdAt:Date.now(),buffer:Buffer.alloc(0),ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1,metadata:h};K(b),this.tlsSessions.set(g,b),this.eventBus?.emit(`tls:session_opened`,{sessionId:g,host:t,port:n,timestamp:new Date().toISOString()}),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!0,timestamp:new Date().toISOString()}),u({ok:!0,sessionId:g,kind:`tls`,...h,timing:{handshakeMs:e},state:W(b)})};l.once(`error`,f),l.once(`secureConnect`,p)})}async handleTlsWrite(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTlsSession(t);return n?this.writeBufferedSession(n,e):{ok:!1,error:`Unknown tls sessionId "${t}"`}}async handleTlsReadUntil(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTlsSession(t);return n?this.readBufferedSessionUntil(n,e):{ok:!1,error:`Unknown tls sessionId "${t}"`}}async handleTlsClose(e){let t=l(e,`sessionId`)?.trim()??null;return t?this.closeBufferedSession(t,this.tlsSessions,`tls`,e):{ok:!1,error:`sessionId is required`}}},ge=class extends he{emitWebSocketEvent(e,t){this.eventBus?.emit(e,t)}attachWebSocketSession(e){let t=()=>{for(;e.parserBuffer.length>0;){let t;try{t=ie(e.parserBuffer)}catch(t){e.error=O(t),e.socket.destroy();break}if(!t)break;e.parserBuffer=e.parserBuffer.subarray(t.bytesConsumed);let n=t.frame;if(e.frames.push(n),n.type===`ping`&&!e.closeSent&&!e.socket.destroyed){let t=Y(`pong`,n.data);e.socket.write(t),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:`pong`,byteLength:n.data.length,automatic:!0,timestamp:new Date().toISOString()})}n.type===`close`&&(e.closeReceived=!0,!e.closeSent&&!e.socket.destroyed&&(e.closeSent=!0,e.socket.write(Y(`close`,n.data,n.closeCode,n.closeReason)),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:`close`,byteLength:n.data.length,automatic:!0,timestamp:new Date().toISOString()})))}X(e)};e.socket.on(`data`,n=>{e.parserBuffer=Buffer.concat([e.parserBuffer,n]),t()}),e.socket.on(`end`,()=>{e.ended=!0,X(e)}),e.socket.on(`close`,()=>{e.closed=!0,X(e)}),e.socket.on(`error`,t=>{e.error=t.message,X(e)}),t()}async readWebSocketFrame(e,t){let n=f(t,`timeoutMs`)??5e3;if(!Number.isFinite(n)||n<=0)return{ok:!1,error:`timeoutMs must be a positive number`};if(e.activeRead)return{ok:!1,error:`Session "${e.id}" already has a pending read`,sessionId:e.id,kind:e.kind,state:q(e)};e.activeRead=!0;let r=Date.now();try{for(;;){let t=e.frames.shift();if(t)return this.emitWebSocketEvent(`websocket:frame_read`,{sessionId:e.id,frameType:t.type,byteLength:t.data.length,timestamp:new Date().toISOString()}),{ok:!0,sessionId:e.id,kind:e.kind,scheme:e.scheme,frameType:t.type,fin:t.fin,opcode:t.opcode,masked:t.masked,byteLength:t.data.length,dataHex:t.data.toString(`hex`).toUpperCase(),dataText:t.type===`binary`?null:t.data.toString(`utf8`),closeCode:t.closeCode,closeReason:t.closeReason,elapsedMs:Date.now()-r,state:q(e)};if(e.error)return{ok:!1,error:e.error,sessionId:e.id,kind:e.kind,state:q(e)};if(e.closed||e.ended)return{ok:!1,error:`socket closed before a WebSocket frame was available`,sessionId:e.id,kind:e.kind,state:q(e)};let i=n-(Date.now()-r);if(i<=0||!await ae(e,i))return{ok:!1,error:`read timed out`,sessionId:e.id,kind:e.kind,state:q(e)}}}finally{e.activeRead=!1}}async sendWebSocketFrame(e,t){if(e.closed||e.socket.destroyed)return{ok:!1,error:`Session "${e.id}" is already closed`,sessionId:e.id,kind:e.kind,state:q(e)};let n=u(t,`frameType`,new Set([`text`,`binary`,`ping`,`pong`,`close`]));if(!n)return{ok:!1,error:`frameType is required`};let r=l(t,`dataHex`),i=l(t,`dataText`);if(r&&i)return{ok:!1,error:`dataHex and dataText are mutually exclusive`};let a=f(t,`timeoutMs`)??5e3;if(!Number.isFinite(a)||a<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let o=Buffer.alloc(0);if(r){let e=k(r);if(!A(e))return{ok:!1,error:`dataHex must be valid even-length hexadecimal data`};o=Buffer.from(e,`hex`)}else i!==void 0&&(o=Buffer.from(i,`utf8`));let s=null,c=null;if(n===`close`){let n=f(t,`closeCode`);if(n!==void 0){if(!Number.isInteger(n)||n<1e3||n>4999)return{ok:!1,error:`closeCode must be an integer between 1000 and 4999`};s=n}if(c=l(t,`closeReason`)??null,r||i)return{ok:!1,error:`close frames use closeCode/closeReason instead of dataHex/dataText`};e.closeSent=!0}if(n===`text`&&r)return{ok:!1,error:`text frames require UTF-8 dataText instead of dataHex`};let d=Y(n,o,s,c);return new Promise(t=>{let r=!1,i=n=>{r||(r=!0,clearTimeout(l),e.socket.off(`error`,u),t(n))},l=setTimeout(()=>{i({ok:!1,error:`write timed out`,sessionId:e.id,kind:e.kind,state:q(e)})},a),u=t=>{i({ok:!1,error:t.message,sessionId:e.id,kind:e.kind,state:q(e)})};e.socket.once(`error`,u),e.socket.write(d,()=>{this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:n,byteLength:n===`close`?c?Buffer.byteLength(c)+2:s?2:0:o.length,automatic:!1,timestamp:new Date().toISOString()}),i({ok:!0,sessionId:e.id,kind:e.kind,scheme:e.scheme,frameType:n,bytesWritten:d.length,payloadBytes:n===`close`?c?Buffer.byteLength(c)+2:s?2:0:o.length,state:q(e)})})})}async closeWebSocketSession(e,t){let n=this.websocketSessions.get(e);if(!n)return{ok:!1,error:`Unknown websocket sessionId "${e}"`};let r=p(t,`force`)??!1,i=f(t,`timeoutMs`)??1e3;if(!Number.isFinite(i)||i<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let a=n.frames.length;if(n.closed||n.socket.destroyed)return this.websocketSessions.delete(e),{ok:!0,sessionId:e,kind:n.kind,force:r,closed:!0,queuedFramesDiscarded:a,state:q(n)};let o=null,s=f(t,`closeCode`);if(s!==void 0){if(!Number.isInteger(s)||s<1e3||s>4999)return{ok:!1,error:`closeCode must be an integer between 1000 and 4999`};o=s}let c=l(t,`closeReason`)??null;return new Promise(t=>{let s=!1,l=i=>{s||(s=!0,clearTimeout(f),n.socket.off(`close`,u),n.socket.off(`error`,d),this.websocketSessions.delete(e),this.emitWebSocketEvent(`websocket:session_closed`,{sessionId:e,reason:n.error,timestamp:new Date().toISOString()}),t({ok:!0,sessionId:e,kind:n.kind,force:r,closed:i,queuedFramesDiscarded:a,state:q(n)}))},u=()=>l(!0),d=()=>l(n.socket.destroyed||n.closed),f=setTimeout(()=>{n.socket.destroy(),l(n.socket.destroyed||n.closed)},i);if(n.socket.once(`close`,u),n.socket.once(`error`,d),r){n.socket.destroy();return}n.closeSent||(n.closeSent=!0,n.socket.write(Y(`close`,Buffer.alloc(0),o,c)),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e,frameType:`close`,byteLength:c?Buffer.byteLength(c)+2:o?2:0,automatic:!1,timestamp:new Date().toISOString()}))})}async handleWebSocketSendFrame(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getWebSocketSession(t);return n?this.sendWebSocketFrame(n,e):{ok:!1,error:`Unknown websocket sessionId "${t}"`}}async handleWebSocketReadFrame(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getWebSocketSession(t);return n?this.readWebSocketFrame(n,e):{ok:!1,error:`Unknown websocket sessionId "${t}"`}}async handleWebSocketClose(e){let t=l(e,`sessionId`)?.trim()??null;return t?this.closeWebSocketSession(t,e):{ok:!1,error:`sessionId is required`}}};const _e=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var ve=class extends ge{async handleWebSocketOpen(e){let t=l(e,`url`)?.trim()??null,n=l(e,`host`)?.trim()??null,r=l(e,`path`)?.trim()??null,i=f(e,`port`),a=l(e,`scheme`)?.trim()??null;if(t&&(n||r||i!==void 0||a))return{ok:!1,error:`url is mutually exclusive with explicit scheme/host/port/path inputs`};let o=`ws`,s=n,c=i??void 0,m=J(r),h;if(t){let e;try{e=new URL(t)}catch(e){return{ok:!1,error:`Invalid url: ${O(e)}`}}if(e.protocol!==`ws:`&&e.protocol!==`wss:`)return{ok:!1,error:`url must use ws:// or wss:// protocol`};o=e.protocol===`wss:`?`wss`:`ws`,s=e.hostname,c=e.port.length>0?Number(e.port):o===`wss`?443:80,m=J(`${e.pathname}${e.search}`),h=`${o}://${e.host}${m}`}else{if(!s)return{ok:!1,error:`host or url is required`};if(a){if(a!==`ws`&&a!==`wss`)return{ok:!1,error:`scheme must be ws or wss`};o=a}c??=o===`wss`?443:80;let e=c===(o===`wss`?443:80)?s:`${s}:${String(c)}`;h=`${o}://${e}${m}`}if(!s||!c||!Number.isInteger(c)||c<1||c>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let g=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(g)||g<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let _=[...new Set(d(e,`subprotocols`).map(e=>e.trim()))].filter(e=>e.length>0),y=j(s);if(y)return y;let b=p(e,`allowInvalidCertificates`)??!1,x=p(e,`skipHostnameCheck`)??!1,C=l(e,`servername`)?.trim()??null,k=[...new Set(d(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),A,I;try{A=u(e,`minVersion`,D),I=u(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(A&&I&&_e.indexOf(A)>_e.indexOf(I))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let R=o===`wss`?await F(e):{ok:!0,ca:void 0,source:null,path:null,bytes:null};if(!R.ok)return{ok:!1,error:R.error};let B={scheme:o,url:h,host:s,port:c,path:m,requestedServername:o===`wss`?C??(w(s)===0?s:void 0)??null:null,validationTarget:o===`wss`?C??s:null},V=v(16).toString(`base64`),W=re(V),G=Date.now();return new Promise(e=>{let t=!1,n=Buffer.alloc(0),r=null,i=null,a=null,l=o===`wss`?E(P({host:s,port:c,servername:B.requestedServername??void 0,...A?{minVersion:A}:{},...I?{maxVersion:I}:{},...k.length>0?{ALPNProtocols:k}:{},...R.ca?{ca:R.ca}:{}},b)):new S,u=n=>{t||(t=!0,clearTimeout(f),l.off(`error`,p),l.off(`connect`,v),l.off(`secureConnect`,y),l.off(`data`,C),e(n))},d=()=>{let e=c===(o===`wss`?443:80)?s:`${s}:${String(c)}`,t=[`GET ${m} HTTP/1.1`,`Host: ${e}`,`Upgrade: websocket`,`Connection: Upgrade`,`Sec-WebSocket-Key: ${V}`,`Sec-WebSocket-Version: 13`];return _.length>0&&t.push(`Sec-WebSocket-Protocol: ${_.join(`, `)}`),t.push(``,``),Buffer.from(t.join(`\r
|
|
1
|
+
import{n as e}from"./response-B1RuVVfD.mjs";import{a as t,c as n,i as r,l as i,n as a,o,r as s,s as c}from"./boringssl-inspector-ZOCkaipa.mjs";import{n as l,o as u,r as d,s as f,t as p}from"./parse-args-ngRrvF9e.mjs";import{a as m,s as h}from"./ssrf-policy-B72vdy23.mjs";import{readFile as g}from"node:fs/promises";import{X509Certificate as _,createHash as v,randomBytes as y,randomUUID as b}from"node:crypto";import{createSocket as x}from"node:dgram";import{Socket as S,createServer as C,isIP as w}from"node:net";import{checkServerIdentity as T,connect as E}from"node:tls";const D=new Set([`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`]);function O(e){return e instanceof Error?e.message:String(e)}function k(e){return e.replace(/\s+/g,``).toUpperCase()}function A(e){return e.length>0&&e.length%2==0&&/^[0-9A-F]+$/i.test(e)}function j(e){return h(e)&&!m(e)?{ok:!1,error:`Blocked: target host "${e}" resolves to a private/internal address. SSRF protection applies.`}:null}function M(e){return typeof e==`string`&&e.length>0?e:null}function N(e){return typeof e==`string`&&e.length>0?e:null}function P(e,t){let n={...e};return Reflect.set(n,`rejectUnauthorized`,!t),n}async function F(e){let t=u(e,`caPem`)??null,n=u(e,`caPath`)??null;if(t&&n)return{ok:!1,error:`caPem and caPath are mutually exclusive`};if(t)return{ok:!0,ca:t,source:`inline`,path:null,bytes:Buffer.byteLength(t)};if(n)try{let e=await g(n,`utf8`);return{ok:!0,ca:e,source:`path`,path:n,bytes:Buffer.byteLength(e)}}catch(e){return{ok:!1,error:`Failed to read caPath "${n}": ${O(e)}`}}return{ok:!0,ca:void 0,source:null,path:null,bytes:null}}function I(e){return typeof e==`object`&&!!e&&Object.keys(e).length>0}function L(e){return I(e)}function R(e,t){let n=Buffer.isBuffer(e.raw)?e.raw:null,r=n?new _(n):null,i=r?.subject??null,a=r?.issuer??null;return{depth:t,subject:i,issuer:a,subjectAltName:r?.subjectAltName??e.subjectaltname??null,serialNumber:r?.serialNumber??e.serialNumber??null,validFrom:r?.validFrom??e.valid_from??null,validTo:r?.validTo??e.valid_to??null,fingerprint256:r?.fingerprint256??e.fingerprint256??null,fingerprint512:r?.fingerprint512??e.fingerprint512??null,rawLength:n?.length??null,isCA:r?.ca??e.ca??null,selfIssued:i&&a?i===a:null}}function z(e){if(!e)return[];let t=[],n=new Set,r=e,i=0;for(;r&&L(r);){let e=R(r,i),a=e.fingerprint256??`${e.subject??`unknown-subject`}:${e.serialNumber??`unknown-serial`}:${i}`;if(n.has(a)||(n.add(a),t.push(e),!(`issuerCertificate`in r)))break;let o=r.issuerCertificate;if(!o||o===r||!L(o))break;r=o,i+=1}return t}function B(e){let t=v(`sha256`).update(e).digest(`hex`).toUpperCase();try{let n=new _(e);return{subject:n.subject||void 0,issuer:n.issuer||void 0,serialNumber:n.serialNumber||void 0,validFrom:n.validFrom||void 0,validTo:n.validTo||void 0,sha256:t,length:e.length}}catch{return{sha256:t,length:e.length}}}function V(e){let t=Buffer.from(k(e),`hex`),n=[],r=0;for(;r<t.length-4;)if(t[r]===48){let e=B(t.subarray(r));n.push({sha256:e.sha256,length:e.length}),r+=e.length}else r+=1;return n.length===0&&t.length>0&&n.push({sha256:v(`sha256`).update(t).digest(`hex`).toUpperCase(),length:t.length}),n}function H(e){return`${e}_${b()}`}function U(e){return{localAddress:e.localAddress??null,localPort:e.localPort??null,remoteAddress:e.remoteAddress??null,remotePort:e.remotePort??null}}function W(e){return{bufferedBytes:e.buffer.length,remoteEnded:e.ended,socketClosed:e.closed,error:e.error}}function G(e){for(let t of e.waiters)t();e.waiters.clear()}function K(e){e.socket.on(`data`,t=>{e.buffer=Buffer.concat([e.buffer,t]),G(e)}),e.socket.on(`end`,()=>{e.ended=!0,G(e)}),e.socket.on(`close`,()=>{e.closed=!0,G(e)}),e.socket.on(`error`,t=>{e.error=t.message,G(e)})}function ee(e,t){return new Promise(n=>{let r=()=>{clearTimeout(i),e.waiters.delete(r),n(!0)},i=setTimeout(()=>{e.waiters.delete(r),n(!1)},t);e.waiters.add(r)})}function te(e,t,n,r){let i=t?t.toString(`hex`).toUpperCase():null;if(t){let r=e.buffer.indexOf(t);if(r>=0){let a=r+t.length,o=n?e.buffer.subarray(0,a):e.buffer.subarray(0,r);return e.buffer=e.buffer.subarray(a),{data:o,matchedDelimiter:!0,stopReason:`delimiter`,delimiterHex:i}}}if(typeof r==`number`&&e.buffer.length>=r){let t=e.buffer.subarray(0,r);return e.buffer=e.buffer.subarray(r),{data:t,matchedDelimiter:!1,stopReason:`maxBytes`,delimiterHex:i}}if((e.error||e.ended||e.closed)&&e.buffer.length>0){let t=e.buffer;return e.buffer=Buffer.alloc(0),{data:t,matchedDelimiter:!1,stopReason:e.error?`error`:`closed`,delimiterHex:i}}return null}function q(e){return{bufferedBytes:e.parserBuffer.length,queuedFrames:e.frames.length,remoteEnded:e.ended,socketClosed:e.closed,closeSent:e.closeSent,closeReceived:e.closeReceived,error:e.error}}function J(e){return!e||e.trim().length===0?`/`:e.startsWith(`/`)?e:`/${e}`}function ne(e){return{1:`text`,2:`binary`,8:`close`,9:`ping`,10:`pong`}[e]??null}function re(e){return v(`sha1`).update(`${e}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`,`utf8`).digest(`base64`)}function Y(e,t,n,r){let i={text:1,binary:2,close:8,ping:9,pong:10},a=t;if(e===`close`)if(n!=null){let e=r?Buffer.from(r,`utf8`):Buffer.alloc(0);a=Buffer.alloc(2+e.length),a.writeUInt16BE(n,0),e.copy(a,2)}else r&&(a=Buffer.from(r,`utf8`));let o=y(4),s=a.length,c;s<126?(c=Buffer.alloc(2),c[1]=128|s):s<=65535?(c=Buffer.alloc(4),c[1]=254,c.writeUInt16BE(s,2)):(c=Buffer.alloc(10),c[1]=255,c.writeBigUInt64BE(BigInt(s),2)),c[0]=128|i[e];let l=Buffer.alloc(s);for(let e=0;e<s;e+=1)l[e]=a[e]^o[e%4];return Buffer.concat([c,o,l])}function ie(e){if(e.length<2)return null;let t=e[0],n=e[1],r=(t&128)!=0,i=t&15,a=(n&128)!=0,o=n&127,s=2;if(o===126){if(e.length<s+2)return null;o=e.readUInt16BE(s),s+=2}else if(o===127){if(e.length<s+8)return null;let t=e.readBigUInt64BE(s);if(t>BigInt(2**53-1))throw Error(`WebSocket frame payload length exceeds supported limits`);o=Number(t),s+=8}let c=a?e.subarray(s,s+4):null;if(a){if(e.length<s+4)return null;s+=4}if(e.length<s+o)return null;let l=e.subarray(s,s+o),u=Buffer.alloc(l.length);if(a&&c)for(let e=0;e<l.length;e+=1)u[e]=l[e]^c[e%4];else l.copy(u);let d=ne(i);if(!d)throw Error(`Unsupported WebSocket opcode 0x${i.toString(16)}`);let f=null,p=null;return d===`close`&&u.length>=2&&(f=u.readUInt16BE(0),p=u.subarray(2).toString(`utf8`)),{frame:{type:d,fin:r,opcode:i,masked:a,data:u,closeCode:f,closeReason:p,receivedAt:Date.now()},bytesConsumed:s+o}}function X(e){for(let t of e.waiters)t();e.waiters.clear()}function ae(e,t){return new Promise(n=>{let r=()=>{clearTimeout(i),e.waiters.delete(r),n(!0)},i=setTimeout(()=>{e.waiters.delete(r),n(!1)},t);e.waiters.add(r)})}const oe={"3:1":`TLS 1.0`,"3:2":`TLS 1.1`,"3:3":`TLS 1.2`,"3:4":`TLS 1.3`},se={20:`change_cipher_spec`,21:`alert`,22:`handshake`,23:`application_data`,24:`heartbeat`},ce={156:`TLS_RSA_WITH_AES_128_GCM_SHA256`,157:`TLS_RSA_WITH_AES_256_GCM_SHA384`,52392:`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,52393:`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`,4865:`TLS_AES_128_GCM_SHA256`,4866:`TLS_AES_256_GCM_SHA384`,4867:`TLS_CHACHA20_POLY1305_SHA256`,4868:`TLS_AES_128_CCM_SHA256`,4869:`TLS_AES_128_CCM_8_SHA256`,49195:`TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`,49196:`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`,49199:`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,49200:`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`},le={0:`server_name`,1:`max_fragment_length`,5:`status_request`,10:`supported_groups`,13:`signature_algorithms`,16:`application_layer_protocol_negotiation`,18:`signed_certificate_timestamp`,23:`record_size_limit`,27:`compress_certificate`,35:`session_ticket`,43:`supported_versions`,44:`cookie`,45:`psk_key_exchange_modes`,49:`post_handshake_auth`,51:`key_share`};function Z(e,t){return oe[`${e}:${t}`]??`0x${e.toString(16).padStart(2,`0`)}${t.toString(16).padStart(2,`0`)}`}function Q(e){return se[e]??`unknown`}function ue(e){let t={cipherSuites:[],extensions:[]},n=e[0]!==void 0&&e[0]<25?4:0;if(e.length<n+38)return t;let r=n+34,i=e[r]??0,a=r+1+i;if(a+2>e.length)return t;let o=e.readUInt16BE(a);a+=2;let s=a+o;for(;a+2<=s;){let n=e.readUInt16BE(a);t.cipherSuites.push(ce[n]??`0x${n.toString(16).padStart(4,`0`)}`),a+=2}if(a=s+1,a<e.length){let t=e[a];t!==void 0&&(a+=1+t)}if(a+2<=e.length){let n=e.readUInt16BE(a);a+=2;let r=a+n;for(;a+4<=r;){let n=e.readUInt16BE(a),i=e.readUInt16BE(a+2);a+=4;let o=le[n]??`unknown(0x${n.toString(16)})`;if(t.extensions.push({type:n,name:o,length:i}),n===0&&a+2<=r){let n=a+2;if(n+3<=r&&e[n]===0){let i=e.readUInt16BE(n+1),a=n+3;a+i<=r&&(t.serverName=e.subarray(a,a+i).toString(`utf8`))}}a+=i}}return t}var de=class{keyLogExtractor;extensionInvoke;eventBus;tcpSessions=new Map;tlsSessions=new Map;websocketSessions=new Map;constructor(e=new a){this.keyLogExtractor=e}setExtensionInvoke(e){this.extensionInvoke=e}setEventBus(e){this.eventBus=e}getTcpSession(e){return this.tcpSessions.get(e)??null}getTlsSession(e){return this.tlsSessions.get(e)??null}getWebSocketSession(e){return this.websocketSessions.get(e)??null}parseWritePayload(e){let t=u(e,`dataHex`),n=u(e,`dataText`);if(!t&&!n)return{ok:!1,error:`dataHex or dataText is required`};if(t&&n)return{ok:!1,error:`dataHex and dataText are mutually exclusive`};if(t){let e=k(t);return A(e)?{ok:!0,data:Buffer.from(e,`hex`),inputEncoding:`hex`}:{ok:!1,error:`dataHex must be valid even-length hexadecimal data`}}return{ok:!0,data:Buffer.from(n??``,`utf8`),inputEncoding:`utf8`}}async writeBufferedSession(e,t){if(e.socket.destroyed||e.closed)return{ok:!1,error:`Session "${e.id}" is already closed`,sessionId:e.id,kind:e.kind,state:W(e)};let n=this.parseWritePayload(t);if(!n.ok)return{ok:!1,error:n.error,sessionId:e.id,kind:e.kind};let r=d(t,`timeoutMs`)??5e3;return!Number.isFinite(r)||r<=0?{ok:!1,error:`timeoutMs must be a positive number`}:new Promise(t=>{let i=!1,a=n=>{i||(i=!0,clearTimeout(o),e.socket.off(`error`,s),t(n))},o=setTimeout(()=>{a({ok:!1,error:`write timed out`,sessionId:e.id,kind:e.kind,state:W(e)})},r),s=t=>{a({ok:!1,error:t.message,sessionId:e.id,kind:e.kind,state:W(e)})};e.socket.once(`error`,s),e.socket.write(n.data,()=>{e.kind===`tcp`?this.eventBus?.emit(`tcp:session_written`,{sessionId:e.id,byteLength:n.data.length,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_written`,{sessionId:e.id,byteLength:n.data.length,timestamp:new Date().toISOString()}),a({ok:!0,sessionId:e.id,kind:e.kind,inputEncoding:n.inputEncoding,bytesWritten:n.data.length,transport:U(e.socket),state:W(e)})})})}async readBufferedSessionUntil(e,t){let n=u(t,`delimiterHex`),r=u(t,`delimiterText`);if(n&&r)return{ok:!1,error:`delimiterHex and delimiterText are mutually exclusive`};let i=null;if(n){let e=k(n);if(!A(e))return{ok:!1,error:`delimiterHex must be valid even-length hexadecimal data`};i=Buffer.from(e,`hex`)}else r!==void 0&&(i=Buffer.from(r,`utf8`));if(i&&i.length===0)return{ok:!1,error:`delimiter must not be empty`};let a=p(t,`includeDelimiter`)??!0,o=d(t,`maxBytes`),s=o===void 0?void 0:Math.trunc(o);if(s!==void 0&&(!Number.isFinite(s)||s<=0))return{ok:!1,error:`maxBytes must be a positive integer when provided`};if(!i&&s===void 0)return{ok:!1,error:`delimiterHex, delimiterText, or maxBytes is required`};let c=d(t,`timeoutMs`)??5e3;if(!Number.isFinite(c)||c<=0)return{ok:!1,error:`timeoutMs must be a positive number`};if(e.activeRead)return{ok:!1,error:`Session "${e.id}" already has a pending read`,sessionId:e.id,kind:e.kind,state:W(e)};e.activeRead=!0;let l=Date.now();try{for(;;){let t=te(e,i,a,s);if(t)return e.kind===`tcp`?this.eventBus?.emit(`tcp:session_read`,{sessionId:e.id,byteLength:t.data.length,matched:t.matchedDelimiter,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_read`,{sessionId:e.id,byteLength:t.data.length,matched:t.matchedDelimiter,timestamp:new Date().toISOString()}),{ok:!0,sessionId:e.id,kind:e.kind,bytesRead:t.data.length,matchedDelimiter:t.matchedDelimiter,stopReason:t.stopReason,delimiterHex:t.delimiterHex,dataHex:t.data.toString(`hex`).toUpperCase(),dataText:t.data.toString(`utf8`),elapsedMs:Date.now()-l,state:W(e)};if(e.error)return{ok:!1,error:e.error,sessionId:e.id,kind:e.kind,state:W(e)};if(e.ended||e.closed)return{ok:!1,error:`socket closed before the requested read condition was satisfied`,sessionId:e.id,kind:e.kind,state:W(e)};let n=c-(Date.now()-l);if(n<=0||!await ee(e,n))return{ok:!1,error:`read timed out`,sessionId:e.id,kind:e.kind,state:W(e)}}}finally{e.activeRead=!1}}async closeBufferedSession(e,t,n,r){let i=t.get(e);if(!i)return{ok:!1,error:`Unknown ${n} sessionId "${e}"`};let a=p(r,`force`)??!1,o=d(r,`timeoutMs`)??1e3;if(!Number.isFinite(o)||o<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let s=i.buffer.length;return i.closed||i.socket.destroyed?(t.delete(e),{ok:!0,sessionId:e,kind:n,force:a,closed:!0,bufferedBytesDiscarded:s,state:W(i)}):new Promise(r=>{let c=!1,l=o=>{c||(c=!0,clearTimeout(f),i.socket.off(`close`,u),i.socket.off(`error`,d),t.delete(e),n===`tcp`?this.eventBus?.emit(`tcp:session_closed`,{sessionId:e,reason:i.error,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_closed`,{sessionId:e,reason:i.error,timestamp:new Date().toISOString()}),r({ok:!0,sessionId:e,kind:n,force:a,closed:o,bufferedBytesDiscarded:s,state:W(i)}))},u=()=>l(!0),d=()=>l(i.socket.destroyed||i.closed),f=setTimeout(()=>{i.socket.destroy(),l(i.socket.destroyed||i.closed)},o);if(i.socket.once(`close`,u),i.socket.once(`error`,d),a){i.socket.destroy();return}i.socket.end()})}},fe=class extends de{async handleTlsKeylogEnable(e){return{enabled:!0,keyLogPath:await this.keyLogExtractor.enableKeyLog(),environmentVariable:`SSLKEYLOGFILE`}}async handleTlsKeylogDisable(e){let t=u(e,`path`)??null;return t?await this.keyLogExtractor.disableKeyLog():r(),{disabled:!0,previousPath:t??o()}}async handleTlsKeylogParse(e){let t=u(e,`path`)??null,n=this.keyLogExtractor.parseKeyLog(t??void 0),r=this.keyLogExtractor.summarizeKeyLog(t??void 0);return{path:t??this.keyLogExtractor.getKeyLogFilePath(),entries:n,summary:r}}async handleTlsDecryptPayload(e){let t=u(e,`encryptedHex`)??null,n=u(e,`keyHex`)??null,r=u(e,`nonceHex`)??null,i=u(e,`algorithm`)??`aes-256-gcm`,a=u(e,`authTagHex`)??null;if(!t||!n||!r)return{ok:!1,error:`encryptedHex, keyHex, and nonceHex are required`};let o=s(t,n,r,i,a??void 0);return{ok:!0,algorithm:i,decrypted:o,isFailed:o.startsWith(`DECRYPTION_FAILED:`)}}async handleTlsKeylogSummarize(e){let t=u(e,`content`)??null;return t?i(n(t)):(this.keyLogExtractor.parseKeyLog(),this.keyLogExtractor.summarizeKeyLog())}async handleTlsKeylogLookupSecret(e){let t=u(e,`clientRandom`)??null,n=u(e,`label`)??void 0;if(!t)return{ok:!1,error:`clientRandom is required`};let r=this.keyLogExtractor.lookupSecret(t);if(r)return{ok:!0,clientRandom:k(t),secret:r};let i=c(this.keyLogExtractor.parseKeyLog(),t,n);return{ok:i!==null,clientRandom:k(t),secret:i??null}}async handleTlsCertPinBypass(e){let t=u(e,`target`)??null;return t!==`android`&&t!==`ios`&&t!==`desktop`?{error:`target must be one of android, ios, or desktop`}:{bypassStrategy:{android:`hook-trust-manager`,ios:`replace-sec-trust-evaluation`,desktop:`patch-custom-verifier`}[t],affectedDomains:[`*`],instructions:{android:[`Inject a Frida script that overrides X509TrustManager checks.`,`Re-run the target flow after SSLKEYLOGFILE capture is enabled.`],ios:[`Hook SecTrustEvaluateWithError and return success for the target session.`,`Collect TLS keys after the app resumes the failing request.`],desktop:[`Patch the custom verifier callback or disable pin comparison in the client.`,`Capture a fresh handshake after the patched build starts.`]}[t]}}async handleParseHandshake(t){let n=u(t,`rawHex`)??null,r=t.decrypt===!0;if(!n)return e({success:!1,error:`rawHex is required`});let i=k(n);if(!/^(?:[0-9a-f]{2})+$/i.test(i))return e({success:!1,error:`Invalid hex payload`});let a=Buffer.from(i,`hex`);if(a.length<5)return e({success:!1,error:`TLS record is too short`});let o=a[0],s=a[1],c=a[2],l=a.readUInt16BE(3),d=a.subarray(5),f=o===22&&d.length>0&&d[0]===1?ue(d):void 0,p=r?(()=>{let e=this.keyLogExtractor.decryptPayload(i,this.keyLogExtractor.parseKeyLog());return e?e.subarray(0,16).toString(`hex`).toUpperCase():null})():void 0;return e({success:!0,record:{contentType:o,contentTypeName:Q(o),version:Z(s,c),declaredLength:l,actualLength:d.length},handshake:{version:Z(s,c),contentType:Q(o),...f?{type:`client_hello`,serverName:f.serverName,cipherSuites:f.cipherSuites,extensions:f.extensions}:{cipherSuite:[],extensions:[]}},sni:f?.serverName?{serverName:f.serverName}:void 0,...p===void 0?{}:{decryptedPreviewHex:p}})}async handleKeyLogEnable(n){let r=u(n,`filePath`)??`/tmp/sslkeylog.log`;return t(r),this.eventBus?.emit(`tls:keylog_started`,{filePath:r,timestamp:new Date().toISOString()}),e({success:!0,filePath:r,currentFilePath:o()})}async handleCipherSuites(t){let n=u(t,`filter`)??null,r=[`TLS_AES_128_GCM_SHA256`,`TLS_AES_256_GCM_SHA384`,`TLS_CHACHA20_POLY1305_SHA256`,`TLS_AES_128_CCM_SHA256`,`TLS_AES_128_CCM_8_SHA256`,`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`,`TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`,`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`,`TLS_RSA_WITH_AES_128_GCM_SHA256`,`TLS_RSA_WITH_AES_256_GCM_SHA384`],i=n?r.filter(e=>e.includes(n)):r;return e({success:!0,filter:n,total:i.length,suites:i})}async handleParseCertificate(t){let n=u(t,`rawHex`)??null;if(!n)return e({success:!1,error:`rawHex is required`});let r=V(n);return e({success:!0,certificateCount:r.length,fingerprints:r.map(e=>({sha256:e.sha256,length:e.length}))})}};const $=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var pe=class extends fe{async handleTlsProbeEndpoint(e){let t=u(e,`host`)?.trim()??null;if(!t)return{ok:!1,error:`host is required`};let n=d(e,`port`)??443;if(!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=d(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`allowInvalidCertificates`)??!1,a=p(e,`skipHostnameCheck`)??!1,o=u(e,`servername`)?.trim()??null,s=[...new Set(f(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),c,m;try{c=l(e,`minVersion`,D),m=l(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(c&&m&&$.indexOf(c)>$.indexOf(m))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let h=j(t);if(h)return h;let g=await F(e);if(!g.ok)return{ok:!1,error:g.error};let _=o??t,v=o??(w(t)===0?t:void 0),y=Date.now();return new Promise(e=>{let o=!1,l=E(P({host:t,port:n,servername:v,...c?{minVersion:c}:{},...m?{maxVersion:m}:{},...s.length>0?{ALPNProtocols:s}:{},...g.ca?{ca:g.ca}:{}},i)),u=t=>{o||(o=!0,clearTimeout(d),l.removeAllListeners(),l.destroy(),e(t))},d=setTimeout(()=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS probe timed out`,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}}})},r);l.once(`error`,e=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:e.message,errorCode:e.code??null,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}}})}),l.once(`secureConnect`,()=>{let e=Date.now()-y,o=l.getPeerCertificate(!0),d=L(o),f=d?z(o):[],p=f[0]??null,h=a||!d?void 0:T(_,o),b={checked:!a,target:a?null:_,matched:a?null:h===void 0,error:!a&&!d?`Peer certificate was not presented by the server`:h?.message??null},x=[l.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${l.authorizationError??`unknown_authority`}`,a?`Hostname validation was skipped by request.`:b.matched?`Hostname validation passed.`:`Hostname validation failed: ${b.error??`unknown_error`}`,!l.authorized&&i?`Policy allowed the probe to continue despite certificate trust failure.`:null].filter(e=>!!e),S=l.getCipher();this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!0,timestamp:new Date().toISOString()}),u({ok:!0,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}},transport:{protocol:l.getProtocol()??null,alpnProtocol:N(l.alpnProtocol),cipher:{name:S.name,standardName:S.standardName,version:S.version},localAddress:l.localAddress??null,localPort:l.localPort??null,remoteAddress:l.remoteAddress??null,remotePort:l.remotePort??null,servernameSent:M(l.servername),sessionReused:l.isSessionReused()},authorization:{socketAuthorized:l.authorized,authorizationError:typeof l.authorizationError==`string`?l.authorizationError:l.authorizationError?.message??null,hostnameValidation:b,policyAllowed:(l.authorized||i)&&(a||b.matched===!0),reasons:x},certificates:{leaf:p,chain:f},timing:{handshakeMs:e}})})})}};const me=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var he=class extends pe{async handleTcpOpen(e){let t=u(e,`host`)??`127.0.0.1`,n=d(e,`port`);if(n===void 0||!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=d(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`noDelay`)??!0;return j(t)||new Promise(e=>{let a=!1,o=new S,s=t=>{a||(a=!0,clearTimeout(c),o.off(`connect`,u),o.off(`error`,l),e(t))},c=setTimeout(()=>{o.destroy(),s({ok:!1,error:`TCP connect timed out`,target:{host:t,port:n}})},r),l=e=>{s({ok:!1,error:e.message,target:{host:t,port:n}})},u=()=>{o.setNoDelay(i);let e=H(`tcp`),r={id:e,kind:`tcp`,socket:o,host:t,port:n,createdAt:Date.now(),buffer:Buffer.alloc(0),ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1};K(r),this.tcpSessions.set(e,r),this.eventBus?.emit(`tcp:session_opened`,{sessionId:e,host:t,port:n,timestamp:new Date().toISOString()}),s({ok:!0,sessionId:e,kind:`tcp`,target:{host:t,port:n},createdAt:new Date(r.createdAt).toISOString(),transport:U(o),state:W(r)})};o.once(`connect`,u),o.once(`error`,l),o.connect(n,t)})}async handleTcpWrite(e){let t=u(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTcpSession(t);return n?this.writeBufferedSession(n,e):{ok:!1,error:`Unknown tcp sessionId "${t}"`}}async handleTcpReadUntil(e){let t=u(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTcpSession(t);return n?this.readBufferedSessionUntil(n,e):{ok:!1,error:`Unknown tcp sessionId "${t}"`}}async handleTcpClose(e){let t=u(e,`sessionId`)?.trim()??null;return t?this.closeBufferedSession(t,this.tcpSessions,`tcp`,e):{ok:!1,error:`sessionId is required`}}async handleTlsOpen(e){let t=u(e,`host`)?.trim()??null;if(!t)return{ok:!1,error:`host is required`};let n=d(e,`port`)??443;if(!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=d(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`allowInvalidCertificates`)??!1,a=p(e,`skipHostnameCheck`)??!1,o=u(e,`servername`)?.trim()??null,s=[...new Set(f(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),c,m;try{c=l(e,`minVersion`,D),m=l(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(c&&m&&me.indexOf(c)>me.indexOf(m))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let h=j(t);if(h)return h;let g=await F(e);if(!g.ok)return{ok:!1,error:g.error};let _={host:t,port:n,requestedServername:o??(w(t)===0?t:void 0)??null,validationTarget:o??t},v={allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}},y=Date.now();return new Promise(e=>{let o=!1,l=E(P({host:t,port:n,servername:_.requestedServername??void 0,...c?{minVersion:c}:{},...m?{maxVersion:m}:{},...s.length>0?{ALPNProtocols:s}:{},...g.ca?{ca:g.ca}:{}},i)),u=t=>{o||(o=!0,clearTimeout(d),l.off(`error`,f),l.off(`secureConnect`,p),e(t))},d=setTimeout(()=>{l.destroy(),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS open timed out`,target:_,policy:v})},r),f=e=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:e.message,errorCode:e.code??null,target:_,policy:v})},p=()=>{let e=Date.now()-y,r=l.getPeerCertificate(!0),o=L(r),s=o?z(r):[],c=s[0]??null,d=a||!o?void 0:T(_.validationTarget,r),f={checked:!a,target:a?null:_.validationTarget,matched:a?null:d===void 0,error:!a&&!o?`Peer certificate was not presented by the server`:d?.message??null},p=[l.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${l.authorizationError??`unknown_authority`}`,a?`Hostname validation was skipped by request.`:f.matched?`Hostname validation passed.`:`Hostname validation failed: ${f.error??`unknown_error`}`,!l.authorized&&i?`Policy allowed the session to continue despite certificate trust failure.`:null].filter(e=>!!e),m=l.getCipher(),h={target:_,policy:v,transport:{protocol:l.getProtocol()??null,alpnProtocol:N(l.alpnProtocol),cipher:{name:m.name,standardName:m.standardName,version:m.version},localAddress:l.localAddress??null,localPort:l.localPort??null,remoteAddress:l.remoteAddress??null,remotePort:l.remotePort??null,servernameSent:M(l.servername),sessionReused:l.isSessionReused()},authorization:{socketAuthorized:l.authorized,authorizationError:typeof l.authorizationError==`string`?l.authorizationError:l.authorizationError?.message??null,hostnameValidation:f,policyAllowed:(l.authorized||i)&&(a||f.matched===!0),reasons:p},certificates:{leaf:c,chain:s}};if(!h.authorization.policyAllowed){l.destroy(),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS session authorization failed`,...h,timing:{handshakeMs:e}});return}let g=H(`tls`),b={id:g,kind:`tls`,socket:l,host:t,port:n,createdAt:Date.now(),buffer:Buffer.alloc(0),ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1,metadata:h};K(b),this.tlsSessions.set(g,b),this.eventBus?.emit(`tls:session_opened`,{sessionId:g,host:t,port:n,timestamp:new Date().toISOString()}),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!0,timestamp:new Date().toISOString()}),u({ok:!0,sessionId:g,kind:`tls`,...h,timing:{handshakeMs:e},state:W(b)})};l.once(`error`,f),l.once(`secureConnect`,p)})}async handleTlsWrite(e){let t=u(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTlsSession(t);return n?this.writeBufferedSession(n,e):{ok:!1,error:`Unknown tls sessionId "${t}"`}}async handleTlsReadUntil(e){let t=u(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTlsSession(t);return n?this.readBufferedSessionUntil(n,e):{ok:!1,error:`Unknown tls sessionId "${t}"`}}async handleTlsClose(e){let t=u(e,`sessionId`)?.trim()??null;return t?this.closeBufferedSession(t,this.tlsSessions,`tls`,e):{ok:!1,error:`sessionId is required`}}},ge=class extends he{emitWebSocketEvent(e,t){this.eventBus?.emit(e,t)}attachWebSocketSession(e){let t=()=>{for(;e.parserBuffer.length>0;){let t;try{t=ie(e.parserBuffer)}catch(t){e.error=O(t),e.socket.destroy();break}if(!t)break;e.parserBuffer=e.parserBuffer.subarray(t.bytesConsumed);let n=t.frame;if(e.frames.push(n),n.type===`ping`&&!e.closeSent&&!e.socket.destroyed){let t=Y(`pong`,n.data);e.socket.write(t),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:`pong`,byteLength:n.data.length,automatic:!0,timestamp:new Date().toISOString()})}n.type===`close`&&(e.closeReceived=!0,!e.closeSent&&!e.socket.destroyed&&(e.closeSent=!0,e.socket.write(Y(`close`,n.data,n.closeCode,n.closeReason)),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:`close`,byteLength:n.data.length,automatic:!0,timestamp:new Date().toISOString()})))}X(e)};e.socket.on(`data`,n=>{e.parserBuffer=Buffer.concat([e.parserBuffer,n]),t()}),e.socket.on(`end`,()=>{e.ended=!0,X(e)}),e.socket.on(`close`,()=>{e.closed=!0,X(e)}),e.socket.on(`error`,t=>{e.error=t.message,X(e)}),t()}async readWebSocketFrame(e,t){let n=d(t,`timeoutMs`)??5e3;if(!Number.isFinite(n)||n<=0)return{ok:!1,error:`timeoutMs must be a positive number`};if(e.activeRead)return{ok:!1,error:`Session "${e.id}" already has a pending read`,sessionId:e.id,kind:e.kind,state:q(e)};e.activeRead=!0;let r=Date.now();try{for(;;){let t=e.frames.shift();if(t)return this.emitWebSocketEvent(`websocket:frame_read`,{sessionId:e.id,frameType:t.type,byteLength:t.data.length,timestamp:new Date().toISOString()}),{ok:!0,sessionId:e.id,kind:e.kind,scheme:e.scheme,frameType:t.type,fin:t.fin,opcode:t.opcode,masked:t.masked,byteLength:t.data.length,dataHex:t.data.toString(`hex`).toUpperCase(),dataText:t.type===`binary`?null:t.data.toString(`utf8`),closeCode:t.closeCode,closeReason:t.closeReason,elapsedMs:Date.now()-r,state:q(e)};if(e.error)return{ok:!1,error:e.error,sessionId:e.id,kind:e.kind,state:q(e)};if(e.closed||e.ended)return{ok:!1,error:`socket closed before a WebSocket frame was available`,sessionId:e.id,kind:e.kind,state:q(e)};let i=n-(Date.now()-r);if(i<=0||!await ae(e,i))return{ok:!1,error:`read timed out`,sessionId:e.id,kind:e.kind,state:q(e)}}}finally{e.activeRead=!1}}async sendWebSocketFrame(e,t){if(e.closed||e.socket.destroyed)return{ok:!1,error:`Session "${e.id}" is already closed`,sessionId:e.id,kind:e.kind,state:q(e)};let n=l(t,`frameType`,new Set([`text`,`binary`,`ping`,`pong`,`close`]));if(!n)return{ok:!1,error:`frameType is required`};let r=u(t,`dataHex`),i=u(t,`dataText`);if(r&&i)return{ok:!1,error:`dataHex and dataText are mutually exclusive`};let a=d(t,`timeoutMs`)??5e3;if(!Number.isFinite(a)||a<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let o=Buffer.alloc(0);if(r){let e=k(r);if(!A(e))return{ok:!1,error:`dataHex must be valid even-length hexadecimal data`};o=Buffer.from(e,`hex`)}else i!==void 0&&(o=Buffer.from(i,`utf8`));let s=null,c=null;if(n===`close`){let n=d(t,`closeCode`);if(n!==void 0){if(!Number.isInteger(n)||n<1e3||n>4999)return{ok:!1,error:`closeCode must be an integer between 1000 and 4999`};s=n}if(c=u(t,`closeReason`)??null,r||i)return{ok:!1,error:`close frames use closeCode/closeReason instead of dataHex/dataText`};e.closeSent=!0}if(n===`text`&&r)return{ok:!1,error:`text frames require UTF-8 dataText instead of dataHex`};let f=Y(n,o,s,c);return new Promise(t=>{let r=!1,i=n=>{r||(r=!0,clearTimeout(l),e.socket.off(`error`,u),t(n))},l=setTimeout(()=>{i({ok:!1,error:`write timed out`,sessionId:e.id,kind:e.kind,state:q(e)})},a),u=t=>{i({ok:!1,error:t.message,sessionId:e.id,kind:e.kind,state:q(e)})};e.socket.once(`error`,u),e.socket.write(f,()=>{this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:n,byteLength:n===`close`?c?Buffer.byteLength(c)+2:s?2:0:o.length,automatic:!1,timestamp:new Date().toISOString()}),i({ok:!0,sessionId:e.id,kind:e.kind,scheme:e.scheme,frameType:n,bytesWritten:f.length,payloadBytes:n===`close`?c?Buffer.byteLength(c)+2:s?2:0:o.length,state:q(e)})})})}async closeWebSocketSession(e,t){let n=this.websocketSessions.get(e);if(!n)return{ok:!1,error:`Unknown websocket sessionId "${e}"`};let r=p(t,`force`)??!1,i=d(t,`timeoutMs`)??1e3;if(!Number.isFinite(i)||i<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let a=n.frames.length;if(n.closed||n.socket.destroyed)return this.websocketSessions.delete(e),{ok:!0,sessionId:e,kind:n.kind,force:r,closed:!0,queuedFramesDiscarded:a,state:q(n)};let o=null,s=d(t,`closeCode`);if(s!==void 0){if(!Number.isInteger(s)||s<1e3||s>4999)return{ok:!1,error:`closeCode must be an integer between 1000 and 4999`};o=s}let c=u(t,`closeReason`)??null;return new Promise(t=>{let s=!1,l=i=>{s||(s=!0,clearTimeout(f),n.socket.off(`close`,u),n.socket.off(`error`,d),this.websocketSessions.delete(e),this.emitWebSocketEvent(`websocket:session_closed`,{sessionId:e,reason:n.error,timestamp:new Date().toISOString()}),t({ok:!0,sessionId:e,kind:n.kind,force:r,closed:i,queuedFramesDiscarded:a,state:q(n)}))},u=()=>l(!0),d=()=>l(n.socket.destroyed||n.closed),f=setTimeout(()=>{n.socket.destroy(),l(n.socket.destroyed||n.closed)},i);if(n.socket.once(`close`,u),n.socket.once(`error`,d),r){n.socket.destroy();return}n.closeSent||(n.closeSent=!0,n.socket.write(Y(`close`,Buffer.alloc(0),o,c)),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e,frameType:`close`,byteLength:c?Buffer.byteLength(c)+2:o?2:0,automatic:!1,timestamp:new Date().toISOString()}))})}async handleWebSocketSendFrame(e){let t=u(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getWebSocketSession(t);return n?this.sendWebSocketFrame(n,e):{ok:!1,error:`Unknown websocket sessionId "${t}"`}}async handleWebSocketReadFrame(e){let t=u(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getWebSocketSession(t);return n?this.readWebSocketFrame(n,e):{ok:!1,error:`Unknown websocket sessionId "${t}"`}}async handleWebSocketClose(e){let t=u(e,`sessionId`)?.trim()??null;return t?this.closeWebSocketSession(t,e):{ok:!1,error:`sessionId is required`}}};const _e=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var ve=class extends ge{async handleWebSocketOpen(e){let t=u(e,`url`)?.trim()??null,n=u(e,`host`)?.trim()??null,r=u(e,`path`)?.trim()??null,i=d(e,`port`),a=u(e,`scheme`)?.trim()??null;if(t&&(n||r||i!==void 0||a))return{ok:!1,error:`url is mutually exclusive with explicit scheme/host/port/path inputs`};let o=`ws`,s=n,c=i??void 0,m=J(r),h;if(t){let e;try{e=new URL(t)}catch(e){return{ok:!1,error:`Invalid url: ${O(e)}`}}if(e.protocol!==`ws:`&&e.protocol!==`wss:`)return{ok:!1,error:`url must use ws:// or wss:// protocol`};o=e.protocol===`wss:`?`wss`:`ws`,s=e.hostname,c=e.port.length>0?Number(e.port):o===`wss`?443:80,m=J(`${e.pathname}${e.search}`),h=`${o}://${e.host}${m}`}else{if(!s)return{ok:!1,error:`host or url is required`};if(a){if(a!==`ws`&&a!==`wss`)return{ok:!1,error:`scheme must be ws or wss`};o=a}c??=o===`wss`?443:80;let e=c===(o===`wss`?443:80)?s:`${s}:${String(c)}`;h=`${o}://${e}${m}`}if(!s||!c||!Number.isInteger(c)||c<1||c>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let g=d(e,`timeoutMs`)??5e3;if(!Number.isFinite(g)||g<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let _=[...new Set(f(e,`subprotocols`).map(e=>e.trim()))].filter(e=>e.length>0),v=j(s);if(v)return v;let b=p(e,`allowInvalidCertificates`)??!1,x=p(e,`skipHostnameCheck`)??!1,C=u(e,`servername`)?.trim()??null,k=[...new Set(f(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),A,I;try{A=l(e,`minVersion`,D),I=l(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(A&&I&&_e.indexOf(A)>_e.indexOf(I))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let R=o===`wss`?await F(e):{ok:!0,ca:void 0,source:null,path:null,bytes:null};if(!R.ok)return{ok:!1,error:R.error};let B={scheme:o,url:h,host:s,port:c,path:m,requestedServername:o===`wss`?C??(w(s)===0?s:void 0)??null:null,validationTarget:o===`wss`?C??s:null},V=y(16).toString(`base64`),W=re(V),G=Date.now();return new Promise(e=>{let t=!1,n=Buffer.alloc(0),r=null,i=null,a=null,l=o===`wss`?E(P({host:s,port:c,servername:B.requestedServername??void 0,...A?{minVersion:A}:{},...I?{maxVersion:I}:{},...k.length>0?{ALPNProtocols:k}:{},...R.ca?{ca:R.ca}:{}},b)):new S,u=n=>{t||(t=!0,clearTimeout(f),l.off(`error`,p),l.off(`connect`,v),l.off(`secureConnect`,y),l.off(`data`,C),e(n))},d=()=>{let e=c===(o===`wss`?443:80)?s:`${s}:${String(c)}`,t=[`GET ${m} HTTP/1.1`,`Host: ${e}`,`Upgrade: websocket`,`Connection: Upgrade`,`Sec-WebSocket-Key: ${V}`,`Sec-WebSocket-Version: 13`];return _.length>0&&t.push(`Sec-WebSocket-Protocol: ${_.join(`, `)}`),t.push(``,``),Buffer.from(t.join(`\r
|
|
2
2
|
`),`utf8`)},f=setTimeout(()=>{l.destroy(),u({ok:!1,error:`WebSocket open timed out`,target:B})},g),p=e=>{u({ok:!1,error:e.message,errorCode:e.code??null,target:B})},h=()=>{l.write(d())},v=()=>{l instanceof S&&l.setNoDelay(!0),r={...U(l),protocol:null,alpnProtocol:null,servernameSent:null,sessionReused:null},h()},y=()=>{let e=l,t=e.getPeerCertificate(!0),n=L(t),o=n?z(t):[],s=o[0]??null,c=x||!n||!B.validationTarget?void 0:T(B.validationTarget,t),d={checked:!x,target:x?null:B.validationTarget,matched:x?null:c===void 0,error:!x&&!n?`Peer certificate was not presented by the server`:c?.message??null},f=[e.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${e.authorizationError??`unknown_authority`}`,x?`Hostname validation was skipped by request.`:d.matched?`Hostname validation passed.`:`Hostname validation failed: ${d.error??`unknown_error`}`,!e.authorized&&b?`Policy allowed the session to continue despite certificate trust failure.`:null].filter(e=>!!e);if(i={socketAuthorized:e.authorized,authorizationError:typeof e.authorizationError==`string`?e.authorizationError:e.authorizationError?.message??null,hostnameValidation:d,policyAllowed:(e.authorized||b)&&(x||d.matched===!0),reasons:f},a={leaf:s,chain:o},r={...U(e),protocol:e.getProtocol()??null,alpnProtocol:N(e.alpnProtocol),servernameSent:M(e.servername),sessionReused:e.isSessionReused()},!i.policyAllowed){e.destroy(),u({ok:!1,error:`WebSocket TLS authorization failed`,target:B,authorization:i,certificates:a});return}h()},C=e=>{n=Buffer.concat([n,e]);let t=n.indexOf(`\r
|
|
3
3
|
\r
|
|
4
4
|
`);if(t<0)return;let d=n.subarray(0,t).toString(`utf8`).split(`\r
|
|
5
|
-
`),f=d.shift()??``;if(!/^HTTP\/1\.1 101\b/.test(f)){l.destroy(),u({ok:!1,error:`Unexpected WebSocket upgrade response: ${f}`,target:B});return}let p=new Map;for(let e of d){let t=e.indexOf(`:`);if(t<=0)continue;let n=e.slice(0,t).trim().toLowerCase(),r=e.slice(t+1).trim();p.set(n,r)}let h=p.get(`upgrade`)?.toLowerCase()??``,g=p.get(`connection`)?.toLowerCase()??``,v=p.get(`sec-websocket-accept`)??null;if(h!==`websocket`){l.destroy(),u({ok:!1,error:`Upgrade header did not confirm websocket`,target:B});return}if(!g.split(`,`).map(e=>e.trim()).includes(`upgrade`)){l.destroy(),u({ok:!1,error:`Connection header did not confirm upgrade`,target:B});return}if(v!==W){l.destroy(),u({ok:!1,error:`sec-websocket-accept did not match the client key`,target:B});return}let y=p.get(`sec-websocket-protocol`)??null;if(y&&!_.includes(y)){l.destroy(),u({ok:!1,error:`Server selected unexpected subprotocol "${y}"`,target:B});return}let b=H(`websocket`),x={id:b,kind:`websocket`,scheme:o,socket:l,host:s,port:c,path:m,createdAt:Date.now(),parserBuffer:n.subarray(t+4),frames:[],ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1,closeSent:!1,closeReceived:!1,metadata:{target:B,handshake:{requestKey:V,acceptKey:W,responseAcceptKey:v,subprotocol:y},transport:r??{...U(l),protocol:null,alpnProtocol:null,servernameSent:null,sessionReused:null},authorization:i,certificates:a}};this.attachWebSocketSession(x),this.websocketSessions.set(b,x),this.emitWebSocketEvent(`websocket:session_opened`,{sessionId:b,scheme:o,host:s,port:c,path:m,timestamp:new Date().toISOString()}),u({ok:!0,sessionId:b,kind:x.kind,scheme:o,target:B,handshake:x.metadata.handshake,transport:x.metadata.transport,authorization:x.metadata.authorization,certificates:x.metadata.certificates,timing:{handshakeMs:Date.now()-G},state:q(x)})};l.once(`error`,p),l.on(`data`,C),o===`wss`?l.once(`secureConnect`,y):(l.once(`connect`,v),l.connect(c,s))})}async handleBypassCertPinning(t){if(this.extensionInvoke)try{let n=await this.extensionInvoke(t);if(n)return e({success:!0,strategy:`frida-injection`,result:n})}catch{}return e({success:!0,strategy:`manual-bypass`,instructions:{android:[`Use Frida to hook X509TrustManager.checkServerTrusted and return without throwing.`,`Alternatively, use OkHttp CertificatePinner.Builder().add() with the target cert.`],ios:[`Hook SecTrustEvaluateWithError to always return true.`,`Or use SSLSetSessionOption to disable certificate validation.`],desktop:[`Set NODE_TLS_REJECT_UNAUTHORIZED=0 for Node.js targets.`,`Or patch the certificate comparison function in the HTTP client.`]},args:t})}},ye=class extends ve{async handleRawTcpSend(e){let t=
|
|
5
|
+
`),f=d.shift()??``;if(!/^HTTP\/1\.1 101\b/.test(f)){l.destroy(),u({ok:!1,error:`Unexpected WebSocket upgrade response: ${f}`,target:B});return}let p=new Map;for(let e of d){let t=e.indexOf(`:`);if(t<=0)continue;let n=e.slice(0,t).trim().toLowerCase(),r=e.slice(t+1).trim();p.set(n,r)}let h=p.get(`upgrade`)?.toLowerCase()??``,g=p.get(`connection`)?.toLowerCase()??``,v=p.get(`sec-websocket-accept`)??null;if(h!==`websocket`){l.destroy(),u({ok:!1,error:`Upgrade header did not confirm websocket`,target:B});return}if(!g.split(`,`).map(e=>e.trim()).includes(`upgrade`)){l.destroy(),u({ok:!1,error:`Connection header did not confirm upgrade`,target:B});return}if(v!==W){l.destroy(),u({ok:!1,error:`sec-websocket-accept did not match the client key`,target:B});return}let y=p.get(`sec-websocket-protocol`)??null;if(y&&!_.includes(y)){l.destroy(),u({ok:!1,error:`Server selected unexpected subprotocol "${y}"`,target:B});return}let b=H(`websocket`),x={id:b,kind:`websocket`,scheme:o,socket:l,host:s,port:c,path:m,createdAt:Date.now(),parserBuffer:n.subarray(t+4),frames:[],ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1,closeSent:!1,closeReceived:!1,metadata:{target:B,handshake:{requestKey:V,acceptKey:W,responseAcceptKey:v,subprotocol:y},transport:r??{...U(l),protocol:null,alpnProtocol:null,servernameSent:null,sessionReused:null},authorization:i,certificates:a}};this.attachWebSocketSession(x),this.websocketSessions.set(b,x),this.emitWebSocketEvent(`websocket:session_opened`,{sessionId:b,scheme:o,host:s,port:c,path:m,timestamp:new Date().toISOString()}),u({ok:!0,sessionId:b,kind:x.kind,scheme:o,target:B,handshake:x.metadata.handshake,transport:x.metadata.transport,authorization:x.metadata.authorization,certificates:x.metadata.certificates,timing:{handshakeMs:Date.now()-G},state:q(x)})};l.once(`error`,p),l.on(`data`,C),o===`wss`?l.once(`secureConnect`,y):(l.once(`connect`,v),l.connect(c,s))})}async handleBypassCertPinning(t){if(this.extensionInvoke)try{let n=await this.extensionInvoke(t);if(n)return e({success:!0,strategy:`frida-injection`,result:n})}catch{}return e({success:!0,strategy:`manual-bypass`,instructions:{android:[`Use Frida to hook X509TrustManager.checkServerTrusted and return without throwing.`,`Alternatively, use OkHttp CertificatePinner.Builder().add() with the target cert.`],ios:[`Hook SecTrustEvaluateWithError to always return true.`,`Or use SSLSetSessionOption to disable certificate validation.`],desktop:[`Set NODE_TLS_REJECT_UNAUTHORIZED=0 for Node.js targets.`,`Or patch the certificate comparison function in the HTTP client.`]},args:t})}},ye=class extends ve{async handleRawTcpSend(e){let t=u(e,`host`)??`127.0.0.1`,n=d(e,`port`);if(n===void 0||n<1||n>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let r=j(t);if(r)return r;let i=u(e,`dataHex`),a=u(e,`dataText`);if(!i&&!a)return{ok:!1,error:`dataHex or dataText is required`};let o=i?Buffer.from(k(i),`hex`):Buffer.from(a??``,`utf8`),s=d(e,`timeout`)??5e3;return new Promise(e=>{let r=new S,i=setTimeout(()=>{r.destroy(),e({ok:!1,error:`Connection timed out`})},s);r.on(`connect`,()=>{r.write(o,()=>{r.end()})}),r.on(`data`,a=>{clearTimeout(i),e({ok:!0,host:t,port:n,sentBytes:o.length,responseHex:a.toString(`hex`).toUpperCase(),responseText:a.toString(`utf8`)}),r.destroy()}),r.on(`error`,t=>{clearTimeout(i),e({ok:!1,error:t.message})}),r.connect(n,t)})}async handleRawTcpListen(e){let t=d(e,`port`);if(t===void 0||t<1||t>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let n=d(e,`timeout`)??1e4;return new Promise(e=>{let r=C(),i=setTimeout(()=>{r.close(),e({ok:!1,error:`Listen timed out - no connection received`})},n);r.on(`connection`,n=>{clearTimeout(i);let a=[];n.on(`data`,e=>{a.push(e)}),n.on(`end`,()=>{let n=Buffer.concat(a);r.close(),e({ok:!0,port:t,receivedBytes:n.length,dataHex:n.toString(`hex`).toUpperCase(),dataText:n.toString(`utf8`)})}),n.on(`error`,t=>{clearTimeout(i),r.close(),e({ok:!1,error:t.message})})}),r.on(`error`,t=>{clearTimeout(i),e({ok:!1,error:t.message})}),r.listen(t,`127.0.0.1`)})}async handleRawUdpSend(e){let t=u(e,`host`)??`127.0.0.1`,n=d(e,`port`);if(n===void 0||n<1||n>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let r=j(t);if(r)return r;let i=u(e,`dataHex`),a=u(e,`dataText`);if(!i&&!a)return{ok:!1,error:`dataHex or dataText is required`};let o=i?Buffer.from(k(i),`hex`):Buffer.from(a??``,`utf8`),s=d(e,`timeout`)??5e3;return new Promise(e=>{let r=x(`udp4`),i=setTimeout(()=>{r.close(),e({ok:!1,error:`UDP response timed out`})},s);r.on(`message`,a=>{clearTimeout(i),r.close(),e({ok:!0,host:t,port:n,sentBytes:o.length,responseHex:a.toString(`hex`).toUpperCase(),responseText:a.toString(`utf8`)})}),r.on(`error`,t=>{clearTimeout(i),r.close(),e({ok:!1,error:t.message})}),r.send(o,0,o.length,n,t)})}async handleRawUdpListen(e){let t=d(e,`port`);if(t===void 0||t<1||t>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let n=d(e,`timeout`)??1e4;return new Promise(e=>{let r=x(`udp4`),i=setTimeout(()=>{r.close(),e({ok:!1,error:`UDP listen timed out`})},n);r.on(`message`,(n,a)=>{clearTimeout(i),r.close(),e({ok:!0,localPort:t,receivedBytes:n.length,from:a,dataHex:n.toString(`hex`).toUpperCase(),dataText:n.toString(`utf8`)})}),r.on(`error`,t=>{clearTimeout(i),r.close(),e({ok:!1,error:t.message})}),r.bind(t,`127.0.0.1`)})}},be=class extends ye{};export{be as BoringsslInspectorHandlers};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{A as e,B as t,D as n,E as r,F as i,Ft as a,I as o,It as s,L as c,Nt as l,O as u,Pt as d,R as f,V as p,Xt as m,Yi as h,Yt as ee,Zt as te,k as ne,nt as re,z as ie}from"./constants-DMv3svps.mjs";import{t as g}from"./ToolError-g3rjWzhx.mjs";import{t as _}from"./ToolProbe-DQiREmNp.mjs";import{a as ae,c as v,i as oe,n as se,o as ce,r as le,s as y}from"./binary-instrument-BeZ224mZ.mjs";import{n as ue,t as de}from"./capabilities-L1ax5EHS.mjs";import{tmpdir as b}from"node:os";import{promises as x}from"node:fs";import{basename as fe,join as S,posix as pe,relative as C,resolve as w,sep as T}from"node:path";import{access as me,mkdir as E,mkdtemp as D,readFile as O,readdir as he,rm as k,stat as ge,writeFile as _e}from"node:fs/promises";import{promisify as ve}from"node:util";import{execFile as A,spawn as ye}from"node:child_process";import{open as be}from"yauzl";const xe={plugin_frida_bridge:`Install @jshookmcpextension/plugin-frida-bridge and reload extensions.`,plugin_ghidra_bridge:`Install @jshookmcpextension/plugin-ghidra-bridge and reload extensions.`,plugin_ida_bridge:`Install @jshookmcpextension/plugin-ida-bridge and reload extensions.`,plugin_jadx_bridge:`Install @jshookmcpextension/plugin-jadx-bridge and reload extensions.`};function j(e){return{content:[{type:`text`,text:e}]}}function M(e){return j(JSON.stringify(e))}function N(e,t){let n=e[t];if(typeof n!=`string`||n.trim().length===0)throw Error(`${t} is required`);return n.trim()}function P(e,t){let n=e[t];return typeof n==`string`&&n.trim().length>0?n.trim():void 0}function F(e,t){let n=e[t];return typeof n==`number`&&Number.isFinite(n)?n:void 0}function I(e,t){let n=e[t];return typeof n==`boolean`?n:void 0}function L(e,t){let n=e[t];return Array.isArray(n)?n.filter(e=>typeof e==`string`&&e.length>0):[]}function R(e){return typeof e==`object`&&!!e}function Se(e){return R(e)&&e.extensionPluginsById instanceof Map&&e.extensionPluginRuntimeById instanceof Map}function Ce(e,t){if(!e)return;let n=e.extensionPluginsById;if(n instanceof Map)return n.has(t)}function z(e){return xe[e]}function B(e,t){let n=Ce(e,t);return n===!0?{status:`available`,fix:z(t)}:n===!1?{status:`unavailable`,reason:`Plugin ${t.replaceAll(`_`,`-`)} is not installed`,fix:z(t)}:{status:`unknown`,reason:`Extension plugin registry is not available in the current server context`,fix:`Run inside the full MCP server with extension support enabled.`}}async function V(e,t,n,r){let i=B(e,t);if(!e||i.status!==`available`)return M({...de(n,t,i.reason??`Plugin ${t.replaceAll(`_`,`-`)} is not available`,i.fix),status:i.status});let a=await ae(e,{pluginId:t,toolName:n,args:r});return a.success?M(a):M({...de(n,t,a.error??`Plugin invocation failed`,i.fix)})}function we(e,t){let n=e[t];if(!R(n))return;let r={},i=n.includeArgs,a=n.includeRetAddr;return typeof i==`boolean`&&(r.includeArgs=i),typeof a==`boolean`&&(r.includeRetAddr=a),r}function Te(e){if(!/^\d+$/.test(e))return null;let t=Number.parseInt(e,10);return Number.isNaN(t)?null:t}function Ee(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,24)}async function H(){let e=process.env.UNIDBG_JAR??``;if(e.length===0)return{available:!1,reason:`UNIDBG_JAR is not configured`,command:`java`,jarPath:``};try{await me(e)}catch{return{available:!1,reason:`UNIDBG_JAR not found: ${e}`,command:`java`,jarPath:e}}return{available:!0,reason:``,command:`java`,jarPath:e}}function U(e,t,n){return new Promise((r,i)=>{A(e,t,{timeout:n,windowsHide:!0,maxBuffer:8388608,encoding:`utf8`},(e,t,n)=>{if(e){i(e);return}r({stdout:typeof t==`string`?t:``,stderr:typeof n==`string`?n:``})})})}function De(e){return R(e)&&Array.isArray(e.functions)&&Array.isArray(e.imports)}function Oe(e){let t=[];for(let n of e){if(!R(n))continue;let e=W(n,`functionName`),r=W(n,`hookCode`),i=W(n,`description`),a=ke(n.parameters);!e||!r||!i||t.push({functionName:e,hookCode:r,description:i,parameters:a})}return t}function W(e,t){let n=e[t];return typeof n==`string`?n:void 0}function ke(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!R(n))continue;let e=W(n,`name`),r=W(n,`type`),i=W(n,`description`);e&&r&&i&&t.push({name:e,type:r,description:i})}return t}var Ae=class{state;constructor(e){this.state=e}async handleFridaAttach(e){let t=P(e,`pid`);if(!P(e,`target`)&&t)return V(this.state.context,`plugin_frida_bridge`,`frida_attach`,e);let n=N(e,`target`),r=this.getFridaSession(),i=await r.getAvailability();if(!i.available){let e=`mock-frida-${Ee(n)}`;return M({success:!1,available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,target:n,sessionId:e,reason:i.reason??`Frida CLI is not available`,sessions:[{id:e,target:n,pid:Te(n),status:`unavailable`}]})}let a;try{a=await r.attach(n)}catch(e){return M({success:!1,available:!0,capability:`frida_attach`,fix:`Run the server elevated or choose a target process that allows Frida injection.`,target:n,reason:e instanceof Error?e.message:String(e),sessions:r.listSessions()})}return this.state.context?.eventBus.emit(`frida:attached`,{target:n,sessionId:a,timestamp:new Date().toISOString()}),M({success:!0,available:!0,target:n,sessionId:a,sessions:r.listSessions()})}async handleFridaEnumerateModules(e){let t=N(e,`sessionId`),n=this.getFridaSession(),r=await n.getAvailability();if(!r.available)return M({available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessionId:t,reason:r.reason??`Frida CLI is not available`,modules:[{name:`mock-module`,base:`0x0`,size:0,path:`<unavailable>`}]});if(!n.useSession(t))return M({available:!1,capability:`frida_session`,fix:`Call frida_attach first and reuse the returned sessionId.`,sessionId:t,reason:`Unknown Frida session: ${t}`,modules:[]});let i=await n.enumerateModules(),a=n.getSessionDiagnostics(t);return a?.status===`error`&&a.lastError?M({success:!1,available:!0,sessionId:t,reason:a.lastError,modules:i}):M({success:!0,available:!0,sessionId:t,modules:i})}async handleFridaRunScript(e){let t=P(e,`sessionId`);if(!t)return j(`Missing required string argument: sessionId`);let n=N(e,`script`),r=this.getFridaSession(),i=await r.getAvailability();if(!i.available)return{available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessionId:t,reason:i.reason??`Frida CLI is not available`,execution:{output:``,error:`Frida unavailable`}};if(!r.useSession(t))return{available:!1,capability:`frida_session`,fix:`Call frida_attach first and reuse the returned sessionId.`,sessionId:t,reason:`Unknown Frida session: ${t}`,execution:{output:``,error:`Unknown session`}};let a=await r.executeScript(n);return a.error?M({success:!1,available:!0,sessionId:t,reason:a.error,execution:a}):M({success:!0,available:!0,sessionId:t,execution:a})}async handleFridaDetach(e){let t=P(e,`sessionId`);if(!t)return j(`Missing required string argument: sessionId`);let n=this.getFridaSession();return(await n.getAvailability()).available&&n.hasSession(t)?(n.useSession(t),await n.detach(),M({success:!0,sessionId:t,detached:!0})):V(this.state.context,`plugin_frida_bridge`,`frida_detach`,e)}async handleFridaListSessions(e){let t=this.getFridaSession(),n=await t.getAvailability(),r=t.listSessions();if(n.available)return M({success:!0,available:!0,sessions:r,count:r.length});let i=B(this.state.context,`plugin_frida_bridge`);return r.length>0||i.status===`unavailable`?M({success:!0,available:!1,capability:`frida_cli`,reason:n.reason??`Frida CLI is not available`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessions:r,count:r.length}):V(this.state.context,`plugin_frida_bridge`,`frida_list_sessions`,e)}async handleFridaGenerateScript(e){let t=P(e,`target`)??`unknown`,n=P(e,`template`)??`trace`,r=P(e,`functionName`)??`target_function`,i=[{functionName:r,hookCode:`console.log('[${n}] ${r} called');`,description:`${n} hook for ${r}`,parameters:[]}];return M({success:!0,target:t,template:n,functionName:r,script:this.state.hookCodeGenerator.exportScript(i,`frida`)})}async handleFridaEnumerateFunctions(e){let t=N(e,`sessionId`),n=N(e,`moduleName`),r=this.getFridaSession(),i=await r.getAvailability();if(!i.available)return{available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessionId:t,moduleName:n,reason:i.reason??`Frida CLI is not available`,functions:[]};if(!r.useSession(t))return{available:!1,capability:`frida_session`,fix:`Call frida_attach first and reuse the returned sessionId.`,sessionId:t,reason:`Unknown Frida session: ${t}`,functions:[]};let a=await r.enumerateFunctions(n),o=r.getSessionDiagnostics(t);return o?.status===`error`&&o.lastError?M({success:!1,available:!0,sessionId:t,moduleName:n,reason:o.lastError,functions:a,count:a.length}):M({success:!0,available:!0,sessionId:t,moduleName:n,functions:a,count:a.length})}async handleFridaFindSymbols(e){let t=N(e,`sessionId`),n=N(e,`pattern`),r=this.getFridaSession(),i=await r.getAvailability();if(!i.available)return{available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessionId:t,pattern:n,reason:i.reason??`Frida CLI is not available`,symbols:[]};if(!r.useSession(t))return{available:!1,capability:`frida_session`,fix:`Call frida_attach first and reuse the returned sessionId.`,sessionId:t,reason:`Unknown Frida session: ${t}`,symbols:[]};let a=await r.findSymbols(n),o=r.getSessionDiagnostics(t);return o?.status===`error`&&o.lastError?M({success:!1,available:!0,sessionId:t,pattern:n,reason:o.lastError,symbols:a,count:a.length}):M({success:!0,available:!0,sessionId:t,pattern:n,symbols:a,count:a.length})}getFridaSession(){return this.state.fridaSession||(this.state.fridaSession=new v),this.state.fridaSession}};const G=(e,t)=>{let n=process.env[e];if(n===void 0||n===``)return t;let r=parseInt(n,10);return Number.isFinite(r)?r:t},je=(e,t)=>process.env[e]||t,Me=G(`JADX_SEARCH_MAX_RESULTS`,500),Ne=G(`JADX_SEARCH_DEFAULT_CONTEXT_LINES`,2),Pe=G(`JADX_SEARCH_MAX_CONTEXT_LINES`,20),Fe=G(`JADX_SEARCH_MAX_MATCHES_PER_FILE`,100),K=G(`JADX_SEARCH_TIMEOUT_MS`,6e4),Ie=G(`JADX_SEARCH_REGEX_TIMEOUT_MS`,50),Le=G(`JADX_SEARCH_MAX_QUERY_LENGTH`,1024),Re=G(`JADX_SEARCH_FALLBACK_FILE_LIMIT`,5e4),ze=G(`JADX_SEARCH_RG_MAX_BUFFER_BYTES`,128*1024*1024),Be=je(`JADX_SEARCH_DEFAULT_GLOBS`,`**/*.java,**/*.kt`).split(`,`),Ve=G(`JADX_SEARCH_MAX_LINE_BYTES`,64*1024),He=Object.freeze([/\([^()]*[+*][^()]*\)[+*]/,/\([^()]*\|[^()]*\)[+*][^()]*[+*]/]);function Ue(e){return e.replace(/[\\^$.*+?()[\]{}|]/g,`\\$&`)}function We(e,t,n){let r=t?Ue(e):e;if(!t){for(let t of He)if(t.test(r))throw new g(`VALIDATION`,`query rejected as potentially catastrophic (ReDoS heuristic match)`,{details:{query:e}})}let i=n?`gi`:`g`;try{return new RegExp(r,i)}catch(t){throw new g(`VALIDATION`,`query failed to compile as regex: ${t.message}`,{cause:t,details:{query:e}})}}function Ge(e){return e.map(e=>{let t=e.startsWith(`!`);return{negate:t,re:Je(t?e.slice(1):e)}})}function Ke(e,t){let n=!1,r=!1;for(let{negate:i,re:a}of t)if(i||(r=!0),a.test(e)){if(i)return!1;n=!0}return r?n:!0}const qe=/[\\^$.+()|[\]{}]/;function Je(e){let t=`^`,n=0;for(;n<e.length;){let r=e[n];if(r===`*`){if(e[n+1]===`*`){t+=`.*`,n+=2,e[n]===`/`&&(n+=1);continue}t+=`[^/]*`}else r===`?`?t+=`[^/]`:r!==void 0&&qe.test(r)?t+=`\\`+r:r===`/`?t+=`/`:r!==void 0&&(t+=r);n+=1}return t+=`$`,new RegExp(t)}function Ye(e,t){let n=e.split(T).join(`/`),r=t.split(T).join(`/`),i=r.endsWith(`/`)?r:`${r}/`;return n.startsWith(i)?n.slice(i.length):n}function Xe(e){return e.split(/\r?\n/)}function Ze(e,t,n){e.lastIndex=n;let r=performance.now(),i=e.exec(t),a=performance.now()-r;if(a>Ie)throw new g(`TIMEOUT`,`Regex match exceeded JADX_SEARCH_REGEX_TIMEOUT_MS (${Ie} ms): ${a.toFixed(2)} ms`,{details:{pattern:e.source,elapsedMs:a}});return i}async function Qe(e,t,n=Re){let r;try{r=await x.readdir(e,{recursive:!0})}catch(t){throw new g(`NOT_FOUND`,`decompileDir not readable: ${e}`,{cause:t})}let i=Ge(t),a=[];for(let e of r){if(a.length>=n)break;let t=e.split(T).join(`/`);Ke(t,i)&&a.push(t)}return a}var $e=class{async run(e){let t=w(e.decompileDir),n=await Qe(t,e.globs),r=We(e.query,e.literal,e.caseInsensitive),i=[],a=new Set,o=!1;outer:for(let s of n){let n=pe.join(t.split(T).join(`/`),s),c;try{c=await x.readFile(n,`utf8`)}catch{continue}let l=Xe(c),u=0,d=Ye(n,t);for(let t=0;t<l.length;t+=1){let n=l[t];if(n===void 0||n.length>Ve)continue;let s=0,c=Ze(r,n,s);for(;c!==null;){if(u>=e.maxMatchesPerFile){o=!0;break}let f=c.index+1,p=c.index+c[0].length+1,m={file:d,line:t+1,column:f,text:n,matchStart:f,matchEnd:p};if(e.contextLines>0){let n=[];for(let r=Math.max(0,t-e.contextLines);r<t;r+=1){let e=l[r];e!==void 0&&n.push({line:r+1,text:e})}let r=[];for(let n=t+1;n<Math.min(l.length,t+1+e.contextLines);n+=1){let e=l[n];e!==void 0&&r.push({line:n+1,text:e})}m.context={before:n,after:r}}if(i.push(m),a.add(d),u+=1,i.length>=e.maxResults){o=!0;break outer}let h=c[0].length;if(s=c.index+(h>0?h:1),s>n.length)break;c=Ze(r,n,s)}}}return{matches:i,filesMatched:a.size,truncated:o}}};const et=ve(A);let q,J;async function tt(e=3e3){return q||J||(J=(async()=>{try{let t=process.platform===`win32`?`where`:`which`,{stdout:n}=await et(t,[`rg`],{timeout:e,windowsHide:!0}),r=n.trim().split(/\r?\n/)[0];if(!r){let e={available:!1,reason:`'${t} rg' produced empty output`};return q=e,e}let i;try{let{stdout:t}=await et(`rg`,[`--version`],{timeout:e,windowsHide:!0}),n=t.trim().split(/\r?\n/)[0];i=n?n.substring(0,100):void 0}catch{}let a=i?{available:!0,path:r,version:i}:{available:!0,path:r};return q=a,a}catch(e){let t=typeof e==`object`&&e&&`code`in e?e.code:void 0,n=e instanceof Error?e.message:String(e?.message??e),r={available:!1,reason:t===`ENOENT`?`Command 'rg' not found in PATH — install ripgrep (brew/apt/scoop install ripgrep)`:`Probe failed: ${n.substring(0,200)}`};return q=r,r}finally{J=void 0}})(),J)}function Y(e,t){let n=t.split(T).join(`/`),r=e.split(T).join(`/`),i=n.endsWith(`/`)?n:`${n}/`;return r.startsWith(i)?r.slice(i.length):r}function nt(e){return e.endsWith(`\r
|
|
2
|
+
`)?e.slice(0,-2):e.endsWith(`
|
|
3
|
+
`)||e.endsWith(`\r`)?e.slice(0,-1):e}function rt(e){return nt(e)}function it(e){let t=[`--json`,`--no-heading`,`-n`,`--no-config`];e.literal&&t.push(`-F`),e.caseInsensitive&&t.push(`-i`),e.contextLines>0&&t.push(`-C`,String(e.contextLines)),t.push(`--max-count`,String(e.maxMatchesPerFile));for(let n of e.globs)t.push(`--glob`,n);return t.push(`--`,e.query,e.decompileDir),t}var at=class{spawnFn;rgExecutable;constructor(e=ye,t=`rg`){this.spawnFn=e,this.rgExecutable=t}async run(e){let t=w(e.decompileDir),n=it({...e,decompileDir:t}),r=this.spawnFn(this.rgExecutable,n,{stdio:[`ignore`,`pipe`,`pipe`],windowsHide:!0}),i=0,a=``,o=``,s=[],c=new Set,l=!1,u=new Map,d=e=>{u.delete(e)},f=n=>{if(n.type===`begin`){let e=n.data.path.text,r=Y(e,t);return u.has(r)||u.set(r,{recentLines:[],pendingAfter:[],matchCount:0}),!0}if(n.type===`end`){let e=n.data.path.text;return d(Y(e,t)),!0}if(n.type===`context`){let r=n,i=Y(r.data.path.text,t),a=u.get(i);if(!a)return!0;let o=rt(r.data.lines.text),s={line:r.data.line_number,text:o},c=[];for(let e of a.pendingAfter)e.afterRemaining>0&&e.match.context&&(e.match.context.after.push(s),--e.afterRemaining),e.afterRemaining>0&&c.push(e);return a.pendingAfter=c,a.recentLines.push(s),a.recentLines.length>Math.max(e.contextLines,8)&&a.recentLines.shift(),!0}if(n.type===`match`){let r=n,i=Y(r.data.path.text,t),a=u.get(i)??{recentLines:[],pendingAfter:[],matchCount:0};if(u.has(i)||u.set(i,a),a.matchCount>=e.maxMatchesPerFile)return l=!0,!0;if(s.length>=e.maxResults)return l=!0,!1;let o=r.data.submatches[0];if(!o)return!0;let d=rt(r.data.lines.text),f=o.start+1,p=o.end+1,m={file:i,line:r.data.line_number,column:f,text:d,matchStart:f,matchEnd:p};return e.contextLines>0&&(m.context={before:a.recentLines.filter(e=>e.line<r.data.line_number).slice(-e.contextLines),after:[]},a.pendingAfter.push({match:m,afterRemaining:e.contextLines})),s.push(m),c.add(i),a.matchCount+=1,s.length>=e.maxResults?(l=!0,!1):!0}return!0};return new Promise((e,t)=>{let n=setTimeout(()=>{r.kill(`SIGKILL`),t(new g(`TIMEOUT`,`ripgrep timed out after ${K} ms`,{details:{timeoutMs:K}}))},K),u=!1,d=()=>{u||(u=!0,clearTimeout(n))};r.stdout?.setEncoding(`utf8`),r.stderr?.setEncoding(`utf8`),r.stdout?.on(`data`,e=>{if(u)return;if(i+=e.length,i>ze){r.kill(`SIGKILL`),d(),t(new g(`RUNTIME`,`ripgrep stdout exceeded JADX_SEARCH_RG_MAX_BUFFER_BYTES (${ze} bytes)`));return}o+=e;let n=o.indexOf(`
|
|
4
|
+
`);for(;n!==-1;){let e=o.slice(0,n).trimEnd();if(o=o.slice(n+1),e.length>0){let t;try{t=JSON.parse(e)}catch{}if(t&&!f(t)){o=``,d(),r.kill(`SIGTERM`);break}}n=o.indexOf(`
|
|
5
|
+
`)}}),r.stderr?.on(`data`,e=>{a+=e}),r.on(`error`,e=>{d(),t(new g(`RUNTIME`,`ripgrep spawn failed: ${e.message}`,{cause:e}))}),r.on(`close`,(n,r)=>{if(d(),n===2&&r!==`SIGTERM`&&r!==`SIGKILL`){t(new g(`RUNTIME`,`ripgrep exited with code 2: ${a.trim()}`,{details:{exitCode:n,signal:r??null,stderr:a.trim()}}));return}e({matches:s,filesMatched:c.size,truncated:l})})})}},ot=class{rg;fallback;probe;constructor(e={}){this.rg=e.ripgrep??new at,this.fallback=e.fallback??new $e,this.probe=e.probe??(()=>tt())}async search(e){let t=await this.validateAndNormalize(e),n=performance.now(),r=`node-fallback`,i;if(e.forceFallback)i=await this.fallback.run(t);else if((await this.probe()).available){r=`ripgrep`;try{i=await this.rg.run(t)}catch(e){if(e instanceof g&&e.code===`VALIDATION`)throw e;r=`node-fallback`,i=await this.fallback.run(t)}}else i=await this.fallback.run(t);let a=Math.round(performance.now()-n),o={matches:i.matches,filesMatched:i.filesMatched,totalMatches:i.matches.length,engine:r,decompileDir:t.decompileDir,durationMs:a};return i.truncated&&(o.truncated=!0),o}async validateAndNormalize(e){if(typeof e.decompileDir!=`string`||e.decompileDir.length===0)throw new g(`VALIDATION`,`decompileDir must be a non-empty string`);if(typeof e.query!=`string`||e.query.length===0)throw new g(`VALIDATION`,`query must be a non-empty string`);if(e.query.length>Le)throw new g(`VALIDATION`,`query length ${e.query.length} exceeds JADX_SEARCH_MAX_QUERY_LENGTH (${Le})`);let t=e.contextLines??Ne;if(!Number.isFinite(t)||t<0||!Number.isInteger(t))throw new g(`VALIDATION`,`contextLines must be a non-negative integer`);if(t>Pe)throw new g(`VALIDATION`,`contextLines ${t} exceeds JADX_SEARCH_MAX_CONTEXT_LINES (${Pe})`);let n=e.maxMatchesPerFile??Fe;if(!Number.isFinite(n)||n<1||!Number.isInteger(n))throw new g(`VALIDATION`,`maxMatchesPerFile must be a positive integer`);let r=e.maxResults??Me;if(!Number.isFinite(r)||r<1||!Number.isInteger(r))throw new g(`VALIDATION`,`maxResults must be a positive integer`);let i=w(e.decompileDir),a;try{a=await x.stat(i)}catch(e){throw new g(`NOT_FOUND`,`decompileDir not found: ${i}`,{cause:e,details:{decompileDir:i}})}if(!a.isDirectory())throw new g(`VALIDATION`,`decompileDir is not a directory: ${i}`);let o=e.globs&&e.globs.length>0?Array.from(e.globs):[...Be];return{decompileDir:i,query:e.query,globs:o,literal:e.literal===!0,caseInsensitive:e.caseInsensitive===!0,contextLines:t,maxMatchesPerFile:n,maxResults:r}}};const st=[{name:`SecNeo/Bangcle`,patterns:[/com\/secneo\/apkwrapper/i,/libDexHelper\.so/i,/libSecShell/i]},{name:`Qihoo 360`,patterns:[/com\/qihoo\/util/i,/libprotectClass\.so/i,/libjiagu/i]},{name:`Tencent Legu`,patterns:[/com\/tencent\/StubShell/i,/libshell/i,/libBugly_Native\.so/i]},{name:`Baidu Protect`,patterns:[/com\/baidu\/protect/i,/libbaiduprotect/i]},{name:`AliProtect`,patterns:[/aliprotect/i,/libsgmain/i,/libsgsecuritybody/i]}],ct=[{name:`BeiZis Ads`,patterns:[/beizi/i,/bzads/i]},{name:`Kuaishou/Kwai Ads`,patterns:[/kuaishou/i,/kwai/i,/ksad/i]},{name:`Pangle/Toutiao Ads`,patterns:[/pangle/i,/toutiao/i,/bytedance/i,/csj/i]},{name:`Tencent GDT Ads`,patterns:[/gdt/i,/qq\/e\/ads/i]},{name:`Huawei Services/Ads`,patterns:[/huawei/i,/hms/i,/agconnect/i]},{name:`OPPO/VIVO/Honor Push`,patterns:[/oppo/i,/vivo/i,/honor/i,/push/i]},{name:`Bugly`,patterns:[/bugly/i]},{name:`Agora`,patterns:[/agora/i]},{name:`Baidu Speech`,patterns:[/baidu.*speech/i,/BDSpeech/i]}];function X(e,t=200){return[...new Set(e.filter(Boolean))].slice(0,t)}function Z(e,t){let n=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return e.match(RegExp(`\\b${n}\\s*=\\s*"([^"]*)"`,`i`))?.[1]??e.match(RegExp(`\\bandroid:${n}\\s*=\\s*"([^"]*)"`,`i`))?.[1]}function Q(e,t){let n=[],r=RegExp(`<${t}\\b[^>]*(?:/>|>[\\s\\S]*?<\\/${t}>)`,`gi`),i;for(;(i=r.exec(e))!==null;)i[0]&&n.push(i[0]);return n}function lt(e){let t=e.match(/<manifest\b[^>]*>/i)?.[0]??``,n=e.match(/<application\b[^>]*>/i)?.[0]??``,r=Q(e,`activity`),i=Q(e,`activity-alias`),a=Q(e,`service`),o=Q(e,`receiver`),s=Q(e,`provider`),c=X([...e.matchAll(/<uses-permission\b[^>]*\bandroid:name="([^"]+)"/gi)].map(e=>e[1]??``),500),l=X([...e.matchAll(/<uses-feature\b[^>]*\bandroid:name="([^"]+)"/gi)].map(e=>e[1]??``),200),u=[...r,...i].find(e=>/android\.intent\.action\.MAIN/i.test(e)&&/android\.intent\.category\.LAUNCHER/i.test(e))??``,d={activities:X(r.map(e=>Z(e,`name`)??``),500),activityAliases:X(i.map(e=>Z(e,`name`)??``),200),services:X(a.map(e=>Z(e,`name`)??``),500),receivers:X(o.map(e=>Z(e,`name`)??``),500),providers:X(s.map(e=>Z(e,`name`)??``),500)};return{packageName:Z(t,`package`),versionCode:Z(t,`versionCode`),versionName:Z(t,`versionName`),minSdk:e.match(/<uses-sdk\b[^>]*\bandroid:minSdkVersion="([^"]+)"/i)?.[1],targetSdk:e.match(/<uses-sdk\b[^>]*\bandroid:targetSdkVersion="([^"]+)"/i)?.[1],applicationClass:Z(n,`name`),applicationLabel:Z(n,`label`),debuggable:Z(n,`debuggable`),launcherActivity:u?Z(u,`name`):void 0,permissions:c,usesFeatures:l,components:d,counts:{permissions:c.length,activities:d.activities.length,services:d.services.length,receivers:d.receivers.length,providers:d.providers.length}}}function ut(e,t){let n=[...e.slice(0,5e3),t].join(`
|
|
6
|
+
`);return ct.map(e=>({name:e.name,evidence:e.patterns.filter(e=>e.test(n)).map(e=>e.source).slice(0,5)})).filter(e=>e.evidence.length>0)}function $(e,t){let n=[...e.slice(0,5e3),t].join(`
|
|
7
|
+
`);return st.map(e=>({name:e.name,evidence:e.patterns.filter(e=>e.test(n)).map(e=>e.source).slice(0,5)})).filter(e=>e.evidence.length>0)}var dt=class{state;constructor(e){this.state=e}async handleGhidraAnalyze(e){let t=N(e,`binaryPath`),n=F(e,`timeout`),r=this.getGhidraAnalyzer(),i=await r.getAvailability();if(!i.available){let e=await O(t).catch(()=>Buffer.alloc(0)),n=this.extractPrintableStringsStatic(e);return{available:!1,capability:`ghidra_headless`,fix:`Install Ghidra and ensure analyzeHeadless is on PATH.`,binaryPath:t,reason:i.reason??`Ghidra analyzeHeadless is not available`,functions:[],imports:[],exports:[],strings:n}}return{available:!0,binaryPath:t,analysis:await r.analyze(t,n===void 0?void 0:{timeout:n})}}async handleGhidraDecompile(e){return V(this.state.context,`plugin_ghidra_bridge`,`ghidra_decompile`,e)}async handleIdaDecompile(e){return V(this.state.context,`plugin_ida_bridge`,`ida_decompile`,e)}async handleJadxDecompile(e){let t=N(e,`apkPath`),n=N(e,`className`),r=P(e,`methodName`),i=await _(`jadx`,[`--version`]);return i.available?this.jadxNativeDecompile(i.path??`jadx`,t,n,r):V(this.state.context,`plugin_jadx_bridge`,`jadx_decompile`,e)}async handleJadxDecompileApk(e){let t=N(e,`apkPath`),n=P(e,`outputDir`),r=I(e,`noResources`)??!1,i=I(e,`force`)??!1,a=await _(`jadx`,[`--version`]);if(!a.available)return M({available:!1,capability:`jadx_cli`,fix:`Install JADX and ensure jadx is on PATH.`,apkPath:t,reason:a.reason??`jadx is not available`});let o=n??await D(S(b(),`jshook-jadx-${fe(t)}-`));n&&i&&await k(n,{recursive:!0,force:!0}),await E(o,{recursive:!0});let s=[`--no-debug-info`];r&&s.push(`--no-res`),s.push(`-d`,o,t);try{await this.runJadx(a.path??`jadx`,s,3e5);let e=S(o,`sources`),n=await ge(e).then(e=>e.isDirectory()).catch(()=>!1)?await this.findFilesByExtension(e,[`.java`,`.kt`],20):[];return M({available:!0,apkPath:t,outputDir:o,sourcesDir:e,resourcesDir:S(o,`resources`),noResources:r,sampleFiles:n,next:`Use jadx_search_code with decompileDir set to sourcesDir.`})}catch(e){return M({available:!0,apkPath:t,outputDir:o,error:e instanceof Error?e.message:String(e)})}}async handleJadxSearchCode(e){let t=P(e,`decompileDir`),n=P(e,`apkPath`),r=N(e,`query`);if(!t&&!n)throw new g(`VALIDATION`,`Either decompileDir or apkPath must be provided for jadx_search_code.`);let i=!1;if(!t&&n){let e=await _(`jadx`,[`--version`]);if(!e.available)return M({success:!1,available:!1,capability:`jadx_cli`,fix:`Install JADX and ensure jadx is on PATH.`,apkPath:n,reason:e.reason??`jadx is not available`});let r=await D(S(b(),`jshook-jadx-search-${fe(n)}-`));await this.runJadx(e.path??`jadx`,[`--no-res`,`--no-debug-info`,`-d`,r,n],3e5),t=S(r,`sources`),i=!0}let a={decompileDir:t,query:r},o=I(e,`literal`);o!==void 0&&(a.literal=o);let s=I(e,`caseInsensitive`);s!==void 0&&(a.caseInsensitive=s);let c=F(e,`contextLines`);c!==void 0&&(a.contextLines=c);let l=F(e,`maxMatchesPerFile`);l!==void 0&&(a.maxMatchesPerFile=l);let u=F(e,`maxResults`);u!==void 0&&(a.maxResults=u);let d=e.globs;if(d!==void 0){if(!Array.isArray(d))throw new g(`VALIDATION`,`globs must be an array of strings`);let t=L(e,`globs`);if(t.length!==d.length)throw new g(`VALIDATION`,`globs contains non-string entries`);t.length>0&&(a.globs=t)}let f=await this.getJadxSearchEngine().search(a);return M({success:!0,matches:f.matches,filesMatched:f.filesMatched,totalMatches:f.totalMatches,engine:f.engine,durationMs:f.durationMs,decompileDir:f.decompileDir,...i?{autoDecompiled:!0}:{},...n?{apkPath:n}:{},...f.truncated?{truncated:!0}:{}})}getJadxSearchEngine(){return this.state.jadxSearchEngine||(this.state.jadxSearchEngine=new ot),this.state.jadxSearchEngine}async handleApktoolDecode(e){let t=N(e,`apkPath`),n=P(e,`outputDir`),r=I(e,`force`)??!1,i=await _(`apktool`,[`--version`]);if(!i.available)return M({available:!1,capability:`apktool_cli`,fix:`Install apktool and ensure it is on PATH.`,apkPath:t,reason:i.reason??`apktool is not available`});let a=n??S(b(),`jshook-apktool-${Date.now()}`);n&&await E(a,{recursive:!0});try{let e=[`decode`,`--output`,a];r&&e.push(`--force`),e.push(t);let n=await U(i.path??`apktool`,e,12e4);return M({available:!0,apkPath:t,outputDir:a,force:r,stdout:n.stdout.trim(),stderr:n.stderr.trim()})}catch(e){return M({available:!0,apkPath:t,outputDir:a,force:r,error:e instanceof Error?e.message:String(e)})}}async handleApkManifestDump(e){let t=N(e,`apkPath`),n=await this.decodeManifest(t);return n.success?n.format===`xml`?M({available:!0,apkPath:t,entry:`AndroidManifest.xml`,format:`xml`,decodedBy:n.decodedBy,manifest:n.manifest}):M({available:!0,apkPath:t,entry:`AndroidManifest.xml`,format:`binary-axml`,decodedBy:`zip-entry`,size:n.buffer.length,manifestBase64:n.buffer.toString(`base64`)}):M({available:!1,apkPath:t,entry:`AndroidManifest.xml`,error:n.error})}async handleApkManifestQuery(e){let t=N(e,`apkPath`),n=I(e,`includeRawManifest`)??!1,r=await this.decodeManifest(t);if(!r.success)return M({available:!1,apkPath:t,error:r.error});if(r.format!==`xml`)return M({available:!0,apkPath:t,format:r.format,decodedBy:r.decodedBy,error:`Manifest is binary AXML and JADX decode fallback was unavailable or failed.`,size:r.buffer.length});let i=await this.listZipEntries(t),a=i.success?i.entries:[],o=lt(r.manifest);return M({available:!0,apkPath:t,format:`xml`,decodedBy:r.decodedBy,summary:o,sdkHints:ut(a,r.manifest),protectorHints:$(a,r.manifest),...n?{manifest:r.manifest}:{}})}async handleApkStaticTriage(t){let i=N(t,`apkPath`),a=Math.max(ne,Math.min(F(t,`maxEntries`)??n,u)),o=await ge(i).catch(()=>void 0);if(!o?.isFile())return M({available:!1,apkPath:i,error:`APK path is not a regular file`});let s=await this.listZipEntries(i);if(!s.success)return M({available:!1,apkPath:i,error:s.error});let c=s.entries,l=await this.decodeManifest(i),d=l.success&&l.format===`xml`?l.manifest:``,f=c.filter(e=>/^lib\/.+\/[^/]+\.so$/i.test(e)).map(e=>{let t=e.split(`/`);return{path:e,abi:t[1]??``,name:t[t.length-1]??``}}),p=c.filter(e=>/(^|\/)classes.*\.(dex|cdex)$/i.test(e)),m=c.filter(e=>/(^|\/)(assets|unknown)\//i.test(e)&&/\.(jar|dex|dat|bin|json|txt|dve|y)$/i.test(e)).slice(0,r),h=$(c,d);return M({available:!0,apkPath:i,file:{size:o.size},zip:{entryCount:c.length,entries:c.slice(0,a),truncated:c.length>a},manifest:d.length>0?{decodedBy:l.success?l.decodedBy:void 0,summary:lt(d)}:{decodedBy:l.success?l.decodedBy:void 0,error:l.success?`Manifest is not decoded XML`:l.error},nativeLibs:{count:f.length,abis:X(f.map(e=>e.abi)),libraries:f.slice(0,e)},dexFiles:p,assetHints:m,protectorHints:h,sdkHints:ut(c,d),recommendedNextSteps:[h.length>0?`Packed/protected APK detected: start with adb_app_cold_start_trace/logcat and local APK artifact triage before escalating to device-specific runtime dumping.`:`No strong protector hint found: run jadx_decompile_apk then jadx_search_code for startup/splash logic.`,f.length>0?`Inspect native libraries relevant to protectors or startup SDKs with apk_native_libs_list and ghidra/unidbg tools.`:`Native library surface appears small or absent.`]})}async handleDexScanFile(e){let t=N(e,`filePath`),n=P(e,`outputDir`),r=Math.max(1,Math.min(F(e,`maxHits`)??d,s)),i=I(e,`extract`)??!1,o=await O(t);i&&n&&await E(n,{recursive:!0});let c=[],u=[{kind:`dex`,magic:Buffer.from(l,`ascii`)},{kind:`cdex`,magic:Buffer.from(re,`ascii`)}];for(let e=0;e<o.length&&c.length<r;e++){let t=u.find(t=>e+t.magic.length<=o.length&&o.subarray(e,e+t.magic.length).equals(t.magic));if(!t)continue;let r=o.subarray(e+t.magic.length,Math.min(e+t.magic.length+4,o.length)).toString(`latin1`).replaceAll(`\0`,``),s=e+36<=o.length?o.readUInt32LE(e+32):void 0,l=s!==void 0&&s>112&&s<=o.length-e&&s<a?s:void 0,d;i&&n&&l&&(d=S(n,`${t.kind}_${e.toString(16)}.${t.kind}`),await _e(d,o.subarray(e,e+l))),c.push({kind:t.kind,offset:e,offsetHex:`0x${e.toString(16)}`,version:r,fileSize:s,plausibleSize:l,...d?{extractedPath:d}:{}}),e+=Math.max(0,t.magic.length-1)}return M({success:!0,filePath:t,size:o.length,count:c.length,hits:c,truncated:c.length>=r})}async handleBinaryStringsExtract(e){let n=N(e,`filePath`),r=Math.max(ie,Math.min(F(e,`minLength`)??f,c)),a=Math.max(1,Math.min(F(e,`maxResults`)??i,o)),s=P(e,`pattern`),l=s?new RegExp(s,`i`):void 0,u=await O(n),d=[],m=(e,t,n)=>{n.length<r||l&&!l.test(n)||d.push({offset:e,encoding:t,value:n})},h=-1;for(let e=0;e<=u.length;e++){let n=e<u.length?u[e]:0,r=n>=p&&n<=t;if(r&&h<0&&(h=e),(!r||e===u.length)&&h>=0){if(m(h,`ascii`,u.subarray(h,e).toString(`utf8`)),d.length>=a)break;h=-1}}for(let e=0;e+r*2<=u.length&&d.length<a;e+=2){if(u[e+1]!==0)continue;let n=e,r=e;for(;r+1<u.length&&u[r+1]===0&&u[r]>=p&&u[r]<=t;)r+=2;r>n&&(m(n,`utf16le`,u.subarray(n,r).toString(`utf16le`)),e=r)}return M({success:!0,filePath:n,size:u.length,minLength:r,pattern:s,count:d.length,strings:d.slice(0,a),truncated:d.length>=a})}async handleApkNativeLibsList(e){let t=N(e,`apkPath`),n=await this.listZipEntries(t);if(!n.success)return M({available:!1,apkPath:t,error:n.error});let r=n.entries.filter(e=>/^lib\/.+\/[^/]+\.so$/i.test(e)).map(e=>{let t=e.split(`/`);return{path:e,abi:t[1]??``,name:t[t.length-1]??``}});return M({available:!0,apkPath:t,count:r.length,libraries:r})}async handleGenerateHooks(e){let t=P(e,`ghidraOutput`);if(t)return this.handleLegacyGenerateHooks(t);let n=e.ghidraOutput;if(R(n))return this.handleLegacyGenerateHooks(JSON.stringify(n));let r=L(e,`symbols`);if(r.length===0)return j(`symbols or ghidraOutput is required`);let i=we(e,`options`),a=this.getHookGenerator().generateFridaHookScript(r,i);return M({available:!0,symbolCount:r.length,script:a})}async handleExportHookScript(e){let t=P(e,`hookTemplates`);if(!t){let e=this.state.hookCodeGenerator.exportScript([],`frida`);return M({format:`frida`,hookCount:0,script:e.includes(`Java.perform`)?e:`Java.perform(function() {\n${e}\n});`})}try{let e=JSON.parse(t);if(!Array.isArray(e))return j(`Invalid JSON`);let n=Oe(e),r=this.state.hookCodeGenerator.exportScript(n,`frida`);return M({format:`frida`,hookCount:n.length,script:r})}catch{return j(`Invalid JSON`)}}async handleUnidbgEmulate(e){let t=N(e,`binaryPath`),n=N(e,`functionName`),r=L(e,`args`),i=await H();if(!i.available)return{available:!1,capability:`unidbg_jar`,fix:`Set UNIDBG_JAR to a reachable Unidbg JAR path.`,binaryPath:t,functionName:n,args:r,reason:i.reason,result:{returnValue:`0x0`,stdout:``,stderr:``,trace:[`mock-unidbg-unavailable`]}};let a=await U(i.command,[`-jar`,i.jarPath,t,n,...r],h);return{available:!0,binaryPath:t,functionName:n,args:r,result:{returnValue:`0x0`,stdout:a.stdout.trim(),stderr:a.stderr.trim(),trace:[]}}}async handleUnidbgLaunch(e){let t=P(e,`soPath`);if(!t)return j(`Missing required string argument: soPath`);let n=P(e,`arch`)??`arm`;try{let e=await this.state.unidbgRunner.launch(t,n);return{available:!0,sessionId:e.sessionId,soPath:e.soPath,arch:e.arch,sessions:this.state.unidbgRunner.listSessions()}}catch(e){return{available:!1,capability:`unidbg_jar`,fix:`Set UNIDBG_JAR to a reachable Unidbg JAR path and retry.`,soPath:t,arch:n,reason:e instanceof Error?e.message:String(e),sessions:this.state.unidbgRunner.listSessions()}}}async handleUnidbgCall(e){let t=P(e,`sessionId`);if(!t)return j(`Missing required string argument: sessionId`);let n=P(e,`functionName`);if(!n)return j(`Missing required string argument: functionName`);let r=R(e.args)?e.args:{};try{return M(await this.state.unidbgRunner.callFunction(t,n,r))}catch(e){let t=e instanceof Error?e.message:String(e);return j(t.startsWith(`No unidbg session found`)?`${t} (not found)`:t)}}async handleUnidbgTrace(e){let t=P(e,`sessionId`);if(!t)return j(`Missing required string argument: sessionId`);try{return M(await this.state.unidbgRunner.trace(t))}catch(e){let t=e instanceof Error?e.message:String(e);return j(t.startsWith(`No unidbg session found`)?`${t} (not found)`:t)}}async handleGetAvailablePlugins(e){let t=this.state.context?oe(this.state.context):[];return M({plugins:t,count:t.length})}async handleFridaDexDump(e){let t=N(e,`outputDir`),n=P(e,`target`),r=F(e,`pid`),i=I(e,`usb`)??!0,a=F(e,`timeoutMs`)??te;if(!r&&!n)throw new g(`VALIDATION`,`Either pid or target must be provided for frida_dex_dump`);let o=await _(`frida-dexdump`,[`--help`]);if(!o.available)return M({available:!1,capability:`frida-dexdump`,fix:"Install with `pip install frida-dexdump` and ensure it is on PATH.",reason:o.reason??`frida-dexdump is not available`});await E(t,{recursive:!0});let s=[];i&&s.push(`-U`),r?s.push(`-p`,String(r)):n&&s.push(`-n`,n),s.push(`-o`,t);let c=await new Promise(e=>{A(o.path??`frida-dexdump`,s,{encoding:`utf8`,windowsHide:!0,timeout:a,maxBuffer:m},(t,n,r)=>{e({stdout:typeof n==`string`?n:``,stderr:typeof r==`string`?r:``,exitCode:typeof t?.code==`number`?t.code??1:0,signal:typeof t?.signal==`string`?t.signal??void 0:void 0})})}),l=await this.findFilesByExtension(t,[`.dex`,`.cdex`],ee);return M({available:!0,success:c.exitCode===0,target:n,pid:r,outputDir:t,dumpedFiles:l,count:l.length,stdout:c.stdout,stderr:c.stderr,exitCode:c.exitCode,...c.signal?{signal:c.signal}:{}})}getGhidraAnalyzer(){return this.state.ghidra||(this.state.ghidra=new y),this.state.ghidra}getHookGenerator(){return this.state.hookGen||(this.state.hookGen=new le),this.state.hookGen}handleLegacyGenerateHooks(e){let t;try{t=JSON.parse(e)}catch{return j(`Invalid JSON`)}if(!De(t))return j(`ghidraOutput is required`);let n=this.state.hookCodeGenerator.generateHooks(t);return M({count:n.length,hooks:n})}async listZipEntries(e){try{let t=await this.openZipFile(e);return{success:!0,entries:await new Promise((e,n)=>{let r=[],i=!1,a=e=>{r.push(e.fileName),t.readEntry()},o=()=>c(()=>e(r)),s=e=>c(()=>n(e)),c=e=>{i||(i=!0,t.removeListener(`entry`,a),t.removeListener(`end`,o),t.removeListener(`error`,s),e())};t.on(`entry`,a),t.on(`end`,o),t.on(`error`,s),t.readEntry()})}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async readZipEntryBuffer(e,t){try{let n=await this.openZipFile(e);return{success:!0,buffer:await new Promise((e,r)=>{let i=!1,a=()=>{try{n.close()}catch{}},o=i=>{if(i.fileName!==t){n.readEntry();return}n.openReadStream(i,(n,i)=>{if(n||!i){l(()=>r(n??Error(`Unable to read ZIP entry: ${t}`))),a();return}this.readStreamToBuffer(i).then(t=>{l(()=>e(t)),a()}).catch(e=>{l(()=>r(e)),a()})})},s=()=>l(()=>r(Error(`ZIP entry not found: ${t}`))),c=e=>l(()=>r(e)),l=e=>{i||(i=!0,n.removeListener(`entry`,o),n.removeListener(`end`,s),n.removeListener(`error`,c),e())};n.on(`entry`,o),n.on(`end`,s),n.on(`error`,c),n.readEntry()})}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async decodeManifest(e){let t=await this.readZipEntryBuffer(e,`AndroidManifest.xml`);if(!t.success)return{success:!1,error:t.error};let n=this.decodeTextEntry(t.buffer);if(n!==null)return{success:!0,format:`xml`,decodedBy:`zip-entry`,manifest:n};let r=await _(`jadx`,[`--version`]);if(r.available){let t=await this.decodeManifestWithJadx(r.path??`jadx`,e);if(t.success)return{success:!0,format:`xml`,decodedBy:`jadx_cli`,manifest:t.manifest}}return{success:!0,format:`binary-axml`,decodedBy:`zip-entry`,buffer:t.buffer}}async jadxNativeDecompile(e,t,n,r){let i=await D(S(b(),`jshook-jadx-`));try{let a=[`--no-res`,`--no-debug-info`,`-d`,i,t];await this.runJadx(e,a);let o=S(i,`sources`),s=await this.resolveDecompiledClassFile(o,n);if(!s.success)return M({available:!0,apkPath:t,className:n,error:`Class file not found after decompilation: ${n}`,suggestions:s.suggestions});let c;try{c=await O(s.classFile,`utf8`)}catch{return M({available:!0,apkPath:t,className:n,...s.resolvedClassName===n?{}:{resolvedClassName:s.resolvedClassName},error:`Class file not found after decompilation: ${n}`})}if(r){let e=this.extractMethodSource(c,r);return M(e?{available:!0,apkPath:t,className:n,...s.resolvedClassName===n?{}:{resolvedClassName:s.resolvedClassName},methodName:r,source:e}:{available:!0,apkPath:t,className:n,...s.resolvedClassName===n?{}:{resolvedClassName:s.resolvedClassName},methodName:r,source:``,error:`Method ${r} not found in ${n}`})}return M({available:!0,apkPath:t,className:n,...s.resolvedClassName===n?{}:{resolvedClassName:s.resolvedClassName},source:c})}catch(e){return M({available:!0,apkPath:t,className:n,error:e instanceof Error?e.message:String(e)})}finally{await k(i,{recursive:!0,force:!0})}}openZipFile(e){return new Promise((t,n)=>{be(e,{autoClose:!0,lazyEntries:!0,decodeStrings:!0,validateEntrySizes:!0,strictFileNames:!1},(r,i)=>{if(r||!i){n(r??Error(`Unable to open ZIP archive: ${e}`));return}t(i)})})}readStreamToBuffer(e){return new Promise((t,n)=>{let r=[];e.on(`data`,e=>{r.push(Buffer.isBuffer(e)?e:Buffer.from(e))}),e.on(`end`,()=>t(Buffer.concat(r))),e.on(`error`,n)})}decodeTextEntry(e){if(e.length===0)return``;let t=e.subarray(0,Math.min(e.length,1024)),n=0;for(let e of t){if(e===0)return null;(e<9||e>13&&e<32)&&(n+=1)}if(n>t.length*.1)return null;let r=e.toString(`utf8`);return r.trimStart().startsWith(`<`)?r:null}async decodeManifestWithJadx(e,t){let n=await D(S(b(),`jshook-jadx-manifest-`));try{await this.runJadx(e,[`--no-src`,`-d`,n,t]);let r=await O(S(n,`resources`,`AndroidManifest.xml`),`utf8`);return r.trimStart().startsWith(`<`)?{success:!0,manifest:r}:{success:!1,error:`Decoded manifest is not XML`}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}finally{await k(n,{recursive:!0,force:!0})}}async runJadx(e,t,n=12e4){await new Promise((r,i)=>{A(e,t,{encoding:`utf8`,windowsHide:!0,timeout:n},e=>{if(e&&e.code!==1){i(e);return}r()})})}async resolveDecompiledClassFile(e,t){let n=this.buildExpectedClassFile(e,t);try{return await O(n,`utf8`),{success:!0,classFile:n,resolvedClassName:t}}catch{}let r=await this.findClassCandidates(e,t);if(r.length===0)return{success:!1,suggestions:[]};if(r.length===1){let e=r[0];return e?{success:!0,classFile:e.classFile,resolvedClassName:e.className}:{success:!1,suggestions:[]}}let i=r[0],a=r[1];return!i||!a?{success:!1,suggestions:r.slice(0,10).map(e=>e.className)}:i.score>a.score?{success:!0,classFile:i.classFile,resolvedClassName:i.className}:{success:!1,suggestions:r.slice(0,10).map(e=>e.className)}}buildExpectedClassFile(e,t){let n=t.split(`.`),r=(n[n.length-1]??``).split(`$`)[0]??``;return S(e,...n.slice(0,-1),`${r}.java`)}async findClassCandidates(e,t){let n=t.split(`.`),r=(n[n.length-1]??``).split(`$`)[0]??``,i=n.slice(0,-1),a=`${r}.java`,o=[],s=async t=>{let n=await he(t,{withFileTypes:!0});for(let r of n){let n=S(t,r.name);if(r.isDirectory()){await s(n);continue}if(!r.isFile()||r.name!==a)continue;let c=C(e,n).replace(/\\/g,`/`).replace(/\.java$/i,``).split(`/`).join(`.`),l=c.split(`.`).slice(0,-1);o.push({className:c,classFile:n,score:this.scoreClassCandidate(i,l)})}};return await s(e),o.toSorted((e,t)=>t.score-e.score||e.className.localeCompare(t.className))}async findFilesByExtension(e,t,n){let r=[],i=t.map(e=>e.toLowerCase()),a=async t=>{if(r.length>=n)return;let o=await he(t,{withFileTypes:!0}).catch(()=>[]);for(let s of o){if(r.length>=n)return;let o=S(t,s.name);if(s.isDirectory()){await a(o);continue}s.isFile()&&i.some(e=>s.name.toLowerCase().endsWith(e))&&r.push(C(e,o).replace(/\\/g,`/`))}};return await a(e),r}scoreClassCandidate(e,t){let n=0,r=Math.min(e.length,t.length);for(;n<r&&e[n]===t[n];)n+=1;let i=0,a=Math.min(e.length,t.length);for(;i<a&&e[e.length-1-i]===t[t.length-1-i];)i+=1;return n*10+i}extractMethodSource(e,t){let n=RegExp(`(?:public|private|protected|static|final|abstract|synchronized|native)\\s+[\\w<>\\[\\]]+\\s+${t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}\\s*\\([^)]*\\)\\s*(?:throws[^{]*)?\\{`),r=e.search(n);if(r===-1)return null;let i=0,a=e.indexOf(`{`,r);for(;a<e.length;a++)if(e[a]===`{`)i+=1;else if(e[a]===`}`&&(--i,i===0))break;return e.slice(r,a+1)}extractPrintableStringsStatic(e){let t=[],n=``;for(let r of e.values()){if(r>=32&&r<=126){n+=String.fromCharCode(r);continue}n.length>=4&&t.push(n),n=``}return n.length>=4&&t.push(n),Array.from(new Set(t)).slice(0,500)}},ft=class{state;constructor(e){this.state=e}async handleBinaryInstrumentCapabilities(){let[e,t,n,r,i]=await Promise.all([this.getFridaSession().getAvailability(),this.getGhidraAnalyzer().getAvailability(),_(`jadx`,[`--version`]),_(`apktool`,[`--version`]),H()]);return M(ue(`binary_instrument_capabilities`,[{capability:`frida_cli`,status:e.available?`available`:`unavailable`,reason:e.reason,fix:e.available?void 0:`Install frida-tools and ensure the frida CLI is on PATH.`,details:{tools:[`frida_attach`,`frida_enumerate_modules`,`frida_run_script`,`frida_enumerate_functions`,`frida_find_symbols`],...e.path?{path:e.path}:{},...e.version?{version:e.version}:{}}},{capability:`plugin_frida_bridge`,...B(this.state.context,`plugin_frida_bridge`),details:{tools:[`frida_attach`,`frida_detach`,`frida_list_sessions`]}},{capability:`ghidra_headless`,status:t.available?`available`:`unavailable`,reason:t.reason,fix:t.available?void 0:`Install Ghidra and ensure analyzeHeadless is on PATH.`,details:{tools:[`ghidra_analyze`],...t.path?{path:t.path}:{},...t.version?{version:t.version}:{}}},{capability:`plugin_ghidra_bridge`,...B(this.state.context,`plugin_ghidra_bridge`),details:{tools:[`ghidra_decompile`]}},{capability:`plugin_ida_bridge`,...B(this.state.context,`plugin_ida_bridge`),details:{tools:[`ida_decompile`]}},{capability:`jadx_cli`,status:n.available?`available`:`unavailable`,reason:n.reason,fix:n.available?void 0:`Install JADX and ensure the jadx CLI is on PATH.`,details:{tools:[`jadx_decompile`],...n.path?{path:n.path}:{},...n.version?{version:n.version}:{}}},{capability:`plugin_jadx_bridge`,...B(this.state.context,`plugin_jadx_bridge`),details:{tools:[`jadx_decompile`]}},{capability:`apktool_cli`,status:r.available?`available`:`unavailable`,reason:r.reason,fix:r.available?void 0:`Install apktool and ensure it is on PATH.`,details:{tools:[`apktool_decode`],...r.path?{path:r.path}:{},...r.version?{version:r.version}:{}}},{capability:`unidbg_jar`,status:i.available?`available`:`unavailable`,reason:i.reason||void 0,fix:i.available?void 0:`Set UNIDBG_JAR to a reachable Unidbg JAR path.`,details:{tools:[`unidbg_emulate`,`unidbg_launch`,`unidbg_call`,`unidbg_trace`],command:i.command,jarPath:i.jarPath}}]))}getFridaSession(){return this.state.fridaSession||(this.state.fridaSession=new v),this.state.fridaSession}getGhidraAnalyzer(){return this.state.ghidra||(this.state.ghidra=new y),this.state.ghidra}},pt=class{state;frida;analysis;capabilities;constructor(e,t,n){this.state={hookCodeGenerator:new ce,unidbgRunner:new se},e instanceof v?this.state.fridaSession=e:Se(e)&&(this.state.context=e),t&&(this.state.ghidra=t),n&&(this.state.hookGen=n),this.frida=new Ae(this.state),this.analysis=new dt(this.state),this.capabilities=new ft(this.state)}handleBinaryInstrumentCapabilities(){return this.capabilities.handleBinaryInstrumentCapabilities()}handleFridaAttach(e){return this.frida.handleFridaAttach(e)}handleFridaEnumerateModules(e){return this.frida.handleFridaEnumerateModules(e)}handleFridaRunScript(e){return this.frida.handleFridaRunScript(e)}handleFridaDetach(e){return this.frida.handleFridaDetach(e)}handleFridaListSessions(e){return this.frida.handleFridaListSessions(e)}handleFridaDexDump(e){return this.analysis.handleFridaDexDump(e)}handleFridaGenerateScript(e){return this.frida.handleFridaGenerateScript(e)}handleFridaEnumerateFunctions(e){return this.frida.handleFridaEnumerateFunctions(e)}handleFridaFindSymbols(e){return this.frida.handleFridaFindSymbols(e)}handleGhidraAnalyze(e){return this.analysis.handleGhidraAnalyze(e)}handleGhidraDecompile(e){return this.analysis.handleGhidraDecompile(e)}handleIdaDecompile(e){return this.analysis.handleIdaDecompile(e)}handleJadxDecompile(e){return this.analysis.handleJadxDecompile(e)}handleJadxDecompileApk(e){return this.analysis.handleJadxDecompileApk(e)}handleJadxSearchCode(e){return this.analysis.handleJadxSearchCode(e)}handleApktoolDecode(e){return this.analysis.handleApktoolDecode(e)}handleApkManifestDump(e){return this.analysis.handleApkManifestDump(e)}handleApkManifestQuery(e){return this.analysis.handleApkManifestQuery(e)}handleApkStaticTriage(e){return this.analysis.handleApkStaticTriage(e)}handleDexScanFile(e){return this.analysis.handleDexScanFile(e)}handleBinaryStringsExtract(e){return this.analysis.handleBinaryStringsExtract(e)}handleApkNativeLibsList(e){return this.analysis.handleApkNativeLibsList(e)}handleGenerateHooks(e){return this.analysis.handleGenerateHooks(e)}handleExportHookScript(e){return this.analysis.handleExportHookScript(e)}handleUnidbgEmulate(e){return this.analysis.handleUnidbgEmulate(e)}handleUnidbgLaunch(e){return this.analysis.handleUnidbgLaunch(e)}handleUnidbgCall(e){return this.analysis.handleUnidbgCall(e)}handleUnidbgTrace(e){return this.analysis.handleUnidbgTrace(e)}handleGetAvailablePlugins(e){return this.analysis.handleGetAvailablePlugins(e)}};export{pt as BinaryInstrumentHandlers};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ui as e}from"./constants-BYj8Xek8.mjs";import{n as t}from"./response-C7rKQst4.mjs";import{i as n,r}from"./outputPaths-B4Ic4RZh.mjs";import{a as i,i as a,s as o}from"./parse-args-Bw413PlW.mjs";import s from"node:http";import{createHash as c}from"node:crypto";import{existsSync as l,mkdirSync as u,readFileSync as d,readdirSync as f}from"node:fs";import p from"node:path";import{fileURLToPath as m,pathToFileURL as h}from"node:url";import{mkdir as g,readFile as _,writeFile as v}from"node:fs/promises";import{EventEmitter as y}from"node:events";function b(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function x(e){let t=e.trim().toLowerCase().replace(/\//g,`-`).replace(/(?!^@)[^a-z0-9@_-]+/g,`-`);return t.length>0?t:`plugin-${Date.now()}`}function S(e){if(!b(e))return null;let{id:t,name:n,version:r,entry:i,permissions:a,status:o}=e;return typeof t!=`string`||typeof n!=`string`||typeof r!=`string`||typeof i!=`string`||o!==`loaded`&&o!==`unloaded`?null:{id:t,name:n,version:r,entry:i,permissions:Array.isArray(a)?a.filter(e=>typeof e==`string`):[],status:o}}var C=class{rootDir;legacyPluginRoots;useLegacyScanApi;registryFile;moduleCacheDir;installedPlugins=new Map;loadedPlugins=new Map;constructor(e=r(),t=[]){let n=typeof e==`string`?e:r();this.useLegacyScanApi=typeof e!=`string`,this.rootDir=n,this.registryFile=p.join(n,`plugins.json`),this.moduleCacheDir=p.join(n,`modules`),this.legacyPluginRoots=t.length>0?t:process.env.JSHOOKMCP_PLUGIN_ROOT?[process.env.JSHOOKMCP_PLUGIN_ROOT]:[],!this.useLegacyScanApi&&this.initializeFromDisk()}async register(e){let t=x(e.id||e.name),n={id:t,name:e.name,version:e.version,entry:e.entry,permissions:e.permissions?[...e.permissions]:[],status:this.loadedPlugins.has(t)?`loaded`:`unloaded`};return this.installedPlugins.set(t,n),await this.persist(),t}async unregister(e){await this.unloadPlugin(e),this.installedPlugins.delete(e),await this.persist()}listInstalled(){return[...this.installedPlugins.values()].map(e=>({id:e.id,name:e.name,version:e.version,status:e.status,permissions:[...e.permissions]})).toSorted((e,t)=>e.name.localeCompare(t.name))}async loadPlugin(e){let t=this.installedPlugins.get(e);if(!t)throw Error(`Plugin not found: ${e}`);let n=this.loadedPlugins.get(e);if(n)return{manifest:this.toPublicManifest(n.manifest),exports:n.exports};let r=h(await this.resolveEntryPath(t));r.searchParams.set(`ts`,String(Date.now()));let i=await import(r.href),a=b(i)?i:{};return t.status=`loaded`,this.loadedPlugins.set(e,{manifest:t,exports:a}),await this.persist(),{manifest:this.toPublicManifest(t),exports:a}}async unloadPlugin(e){let t=this.installedPlugins.get(e);t&&(this.loadedPlugins.delete(e),t.status=`unloaded`,await this.persist())}initializeFromDisk(){if(l(this.rootDir)||u(this.rootDir,{recursive:!0}),l(this.moduleCacheDir)||u(this.moduleCacheDir,{recursive:!0}),!l(this.registryFile))return;let e=d(this.registryFile,`utf8`);if(!e.trim())return;let t=JSON.parse(e);if(Array.isArray(t))for(let e of t){let t=S(e);t&&this.installedPlugins.set(t.id,t)}}async persist(){await g(this.rootDir,{recursive:!0}),await g(this.moduleCacheDir,{recursive:!0}),await v(this.registryFile,JSON.stringify([...this.installedPlugins.values()],null,2),`utf8`)}async resolveEntryPath(e){return e.entry.startsWith(`http://`)||e.entry.startsWith(`https://`)?this.downloadRemoteModule(e.id,e.entry):e.entry.startsWith(`file://`)?m(new URL(e.entry)):p.isAbsolute(e.entry)?e.entry:p.resolve(n(),e.entry)}async downloadRemoteModule(e,t){let n=await fetch(t);if(!n.ok)throw Error(`Failed to download plugin module: ${n.status} ${n.statusText}`);let r=await n.text(),i=p.join(this.moduleCacheDir,`${x(e)}.mjs`),a=c(`sha256`).update(r).digest(`hex`);try{let e=await _(i,`utf8`);if(c(`sha256`).update(e).digest(`hex`)===a)return i}catch{}return await g(this.moduleCacheDir,{recursive:!0}),await v(i,r,`utf8`),i}toPublicManifest(e){return{id:e.id,name:e.name,version:e.version,entry:e.entry,permissions:[...e.permissions]}}listPlugins(){let e=[];for(let t of this.legacyPluginRoots){if(!l(t))continue;let n=f(t,{withFileTypes:!0});for(let r of n){if(!r.isDirectory()||r.name.startsWith(`.`))continue;let n=p.join(t,r.name,`package.json`);if(l(n))try{let t=JSON.parse(d(n,`utf8`)),r=this.toLegacyPluginInfo(t);r&&e.push(r)}catch{continue}}}return e}searchPlugins(e){let t=e.trim().toLowerCase();return t?this.listPlugins().filter(e=>e.name.toLowerCase().includes(t)||(e.description??``).toLowerCase().includes(t)||(e.capabilities??[]).some(e=>e.toLowerCase().includes(t))||(e.dependencies??[]).some(e=>e.toLowerCase().includes(t))):this.listPlugins()}async installPlugin(e){if(/^https:\/\/github\.com\/.+\.git$/u.test(e)||/^git@github\.com:.+\.git$/u.test(e))return{id:`git-plugin`,name:e.split(`/`).pop()?.replace(/\.git$/u,``)??`plugin`,version:`0.0.0`};if(e.includes(`://`)||e.startsWith(`git@`)||e===`invalid-url`)throw Error(`Invalid git URL`);if(e.startsWith(`/`)||e.includes(`\\`)){let t=p.join(e,`package.json`);if(!l(t))throw Error(`No package.json`);let n=JSON.parse(d(t,`utf8`)),r=this.toLegacyPluginInfo(n);if(!r)throw Error(`No package.json`);return r}for(let t of this.legacyPluginRoots){let n=p.join(t,e,`package.json`);if(!l(n))continue;let r=JSON.parse(d(n,`utf8`)),i=this.toLegacyPluginInfo(r);if(i)return i}throw Error(`Plugin not found`)}getPluginInfo(e){return this.listPlugins().find(t=>t.id===e||t.name===e)}getPluginDependencies(e){return this.getPluginInfo(e)?.dependencies??[]}async uninstallPlugin(e){}toLegacyPluginInfo(e){if(typeof e.name!=`string`)return null;let t=b(e.dependencies)?Object.keys(e.dependencies):[];return{id:x(e.name),name:e.name,version:typeof e.version==`string`?e.version:`0.0.0`,description:typeof e.description==`string`?e.description:void 0,capabilities:Array.isArray(e.capabilities)?e.capabilities.filter(e=>typeof e==`string`):void 0,dependencies:t}}};function w(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function T(e){if(!w(e))return null;let{id:t,url:n,events:r,active:i}=e;return typeof t!=`string`||typeof n!=`string`||!Array.isArray(r)||typeof i!=`boolean`?null:{id:t,url:n,events:r.filter(e=>typeof e==`string`),active:i}}var E=class{rootDir;storageFile;webhooks=new Map;constructor(e=r()){this.rootDir=e,this.storageFile=p.join(e,`webhooks.json`),this.initializeFromDisk()}async registerWebhook(e,t){new URL(e);let n={id:`webhook-${Date.now()}-${this.webhooks.size+1}`,url:e,events:[...new Set(t.filter(e=>e.trim().length>0))],active:!0};return this.webhooks.set(n.id,n),await this.persist(),n.id}async sendEvent(e,t){let n=[...this.webhooks.values()].filter(t=>t.active&&(t.events.includes(e)||t.events.includes(`*`)));for(let r of n){let n=await fetch(r.url,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({event:e,payload:t,timestamp:new Date().toISOString()})});if(!n.ok)throw Error(`Webhook delivery failed for ${r.url}: ${n.status} ${n.statusText}`)}}listWebhooks(){return[...this.webhooks.values()].map(e=>({id:e.id,url:e.url,events:[...e.events],active:e.active}))}registerExternalCallback(e,t){let n=this.webhooks.get(e);if(n){n.url=t;return}this.webhooks.set(e,{id:e,url:t,events:[`*`],active:!0})}initializeFromDisk(){if(l(this.rootDir)||u(this.rootDir,{recursive:!0}),!l(this.storageFile))return;let e=d(this.storageFile,`utf8`);if(!e.trim())return;let t=JSON.parse(e);if(Array.isArray(t))for(let e of t){let t=T(e);t&&this.webhooks.set(t.id,t)}}async persist(){await g(this.rootDir,{recursive:!0}),await v(this.storageFile,JSON.stringify([...this.webhooks.values()],null,2),`utf8`)}};function D(e){return{...e}}function O(){return new Date().toISOString()}var k=class extends y{maxQueueSize;commands=new Map;order=[];maxRetries;retryDelay;processTimeout;nextId=1;constructor(t={}){super(),this.maxQueueSize=typeof t.maxQueueSize==`number`?t.maxQueueSize:1e3,this.maxRetries=typeof t.maxRetries==`number`?t.maxRetries:3,this.retryDelay=typeof t.retryDelay==`number`?t.retryDelay:0,this.processTimeout=typeof t.processTimeout==`number`?t.processTimeout:e}enqueue(e){if(this.order.length>=this.maxQueueSize)throw Error(`Command queue is full (${this.maxQueueSize})`);let t=`cmd-${this.nextId}`;this.nextId+=1;let n=O(),r={id:t,endpointId:e.endpointId,event:e.event,payload:e.payload,status:`pending`,retries:0,createdAt:n,updatedAt:n};return this.commands.set(t,r),this.order.push(t),this.emit(`enqueued`,D(r)),t}dequeue(e){if(!e){let e=this.getCommandsByFilter({status:`pending`})[0];return e?D(e):void 0}return this.getCommandsByFilter(e).map(D)}getStatus(e){let t=this.commands.get(e);return t?t.status===`processed`?`completed`:t.status:`failed`}retry(e){let t=this.commands.get(e);if(!t)throw Error(`Command ${e} not found`);if(t.status!==`failed`)throw Error(`Command ${e} is not in failed state`);t.status=`pending`,t.retries=0,t.lastError=void 0,t.updatedAt=O()}getCommand(e){return this.commands.get(e)}getCommandsByFilter(e){let t=e.status===`completed`?`processed`:e.status,n=[];for(let r of this.order){let i=this.commands.get(r);i&&(t&&i.status!==t||e.endpointId&&i.endpointId!==e.endpointId||n.push(i))}return n}updateStatus(e,t,n){let r=this.commands.get(e);if(!r)throw Error(`Command ${e} not found`);return r.status=t,r.updatedAt=O(),r.lastError=n,r}},A=class extends k{async process(e,t){let n=this.getCommand(e);if(!n)throw Error(`Command ${e} not found`);if(n.status===`processed`)throw Error(`Command ${e} already processed`);if(n.status===`failed`)throw Error(`Command ${e} already processed with failure`);if(n.status===`processing`)throw Error(`Command ${e} is already processing`);this.updateStatus(e,`processing`);let r=`processed`,i;try{await Promise.race([Promise.resolve(t(D(n))),new Promise((e,t)=>{setTimeout(()=>{t(Error(`Process timeout`))},this.processTimeout)})])}catch(e){i=e instanceof Error?e.message:String(e),r=n.retries+1>=this.maxRetries?`failed`:`pending`}if(i!==void 0&&this.retryDelay>0&&setTimeout(()=>{},this.retryDelay),r===`processed`){let t=this.updateStatus(e,`processed`);this.emit(`processed`,D(t))}else if(r===`pending`){n.retries+=1;let t=this.updateStatus(e,`pending`,i);throw this.emit(`retried`,D(t)),Error(i===void 0?`retry`:i)}else{let t=this.updateStatus(e,`failed`,i);throw this.emit(`failed`,D(t)),Error(i===void 0?`failed`:i)}}async retry(e){super.retry(e)}exportState(){let e=[];for(let t of this.order){let n=this.commands.get(t);n&&e.push(D(n))}return e}importState(e){this.commands.clear(),this.order.length=0;let t=0;for(let n of e){let e=D(n);this.commands.set(e.id,e),this.order.push(e.id);let r=/^cmd-(\d+)$/.exec(e.id);if(r&&r[1]){let e=parseInt(r[1],10);e>t&&(t=e)}}t>0&&(this.nextId=t+1)}};function j(e){return e===`tool_called`||e===`domain_activated`||e===`evidence_added`||e===`workflow_completed`}function M(e){if(e.length===0)return{};try{return JSON.parse(e)}catch{return{rawBody:e}}}var N=class extends y{endpoints=new Map;eventHandlers=new Map;port;commandQueue;stats={eventsRegistered:0,webhooksSent:0};server;nextEndpointId=1;constructor(e={}){super(),this.port=typeof e.port==`number`?e.port:18789,this.commandQueue=e.commandQueue}registerEndpoint(e){let t=`ep-${this.nextEndpointId}`;return this.nextEndpointId+=1,this.endpoints.set(t,{id:t,path:e.path,method:e.method??`POST`,secret:e.secret}),this.emit(`endpointRegistered`,t),t}removeEndpoint(e){if(!this.endpoints.delete(e))throw Error(`Endpoint ${e} not found`);this.emit(`endpointRemoved`,e)}listEndpoints(){return[...this.endpoints.values()].map(e=>({...e}))}getPort(){return this.port}isRunning(){return this.server!==void 0}registerEvent(e,t){let n=this.eventHandlers.get(e)??[];n.push(t),this.eventHandlers.set(e,n),this.stats.eventsRegistered+=1}start(){if(this.server)throw Error(`Webhook server already started`);this.server=s.createServer((e,t)=>{this.handleRequest(e,t)}),this.server.listen(this.port),this.emit(`started`,this.port)}async stop(){if(!this.server)return;let e=this.server;this.server=void 0,await new Promise((t,n)=>{e.close(e=>{if(e){n(e);return}t()})}),this.emit(`stopped`)}async sendWebhook(e,t,n){await fetch(e,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({event:t,payload:n})}),this.stats.webhooksSent+=1,this.stats.lastSentAt=new Date().toISOString()}getStats(){return{...this.stats}}async handleRequest(e,t){let n=e.method??`GET`,r=e.url??`/`,i=[...this.endpoints.values()].find(e=>e.path===r&&e.method===n);if(!i){t.statusCode=404,t.end(`not found`);return}if(i.secret&&e.headers[`x-webhook-secret`]!==i.secret){t.statusCode=401,t.end(`unauthorized`);return}let a=[];await new Promise((t,n)=>{e.setEncoding(`utf8`),e.on(`data`,e=>{a.push(e)}),e.on(`end`,()=>{t()}),e.on(`error`,e=>{n(e)})});let o=M(a.join(``));this.commandQueue&&this.commandQueue.enqueue({endpointId:i.id,payload:o}),o&&typeof o==`object`&&`event`in o&&typeof o.event==`string`&&await this.invokeEventHandlers(o.event,o),t.setHeader(`content-type`,`application/json`),t.end(JSON.stringify({ok:!0,endpointId:i.id}))}async invokeEventHandlers(e,t){if(!j(e))return;let n=this.eventHandlers.get(e)??[];for(let e of n)await Promise.resolve(e(t))}},P=class extends N{};function F(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function I(e){return typeof e==`function`}var L=class{registry;webhook;webhookServer;commandQueue;constructor(e,t){this.registry=e,this.webhook=t}async handleListInstalled(){return t({success:!0,plugins:this.getRegistry().listInstalled()})}async handleExecuteInContext(e){let n=o(e,`pluginId`),r=o(e,`contextName`),i=a(e,`args`)??{},{manifest:s,exports:c}=await this.getRegistry().loadPlugin(n),l=this.resolveContext(c,r);if(!l)throw Error(`Context "${r}" was not found in plugin "${n}"`);let u=await Promise.resolve(l(i));return this.emitEvent(`extension.executed`,{pluginId:n,contextName:r}),t({success:!0,manifest:s,contextName:r,result:u})}async handleReload(e){let n=o(e,`pluginId`);await this.getRegistry().unloadPlugin(n);let r=await this.getRegistry().loadPlugin(n);return this.emitEvent(`extension.reloaded`,{pluginId:n}),t({success:!0,pluginId:n,manifest:r.manifest,exportedKeys:Object.keys(r.exports).toSorted()})}async handleUninstall(e){let n=o(e,`pluginId`);return await this.getRegistry().unregister(n),this.emitEvent(`extension.uninstalled`,{pluginId:n}),t({success:!0,pluginId:n})}async handleWebhookCreate(e){let n=o(e,`name`),r=o(e,`path`),a=i(e,`secret`),s=Array.isArray(e.events)?e.events.filter(e=>typeof e==`string`):[],c=this.getWebhookServer();c.isRunning()||c.start();let l=c.registerEndpoint({path:r,method:`POST`,secret:a??void 0}),u=this.getWebhook(),d=`http://localhost:${c.getPort()}${r}`;return u.registerExternalCallback(l,d),t({success:!0,endpointId:l,url:d,name:n,events:s})}async handleWebhookList(){let e=this.getWebhookServer();return t({success:!0,endpoints:e.listEndpoints(),port:e.getPort(),running:e.isRunning()})}async handleWebhookDelete(e){let n=o(e,`endpointId`),r=this.getWebhookServer();try{r.removeEndpoint(n)}catch(e){throw Error(`GRACEFUL: ${e instanceof Error?e.message:String(e)}`,{cause:e})}return t({success:!0,endpointId:n})}async handleWebhookCommands(e){let n=o(e,`endpointId`),r=i(e,`status`),s=a(e,`command`);if(s)return t({success:!0,commandId:this.getCommandQueue().enqueue({endpointId:n,payload:s}),status:`pending`});let c=this.getCommandQueue(),l={endpointId:n};r&&(l.status=r);let u=c.dequeue(l);return t({success:!0,endpointId:n,commands:u,count:Array.isArray(u)?u.length:+!!u})}getWebhookServer(){return this.webhookServer||=(this.commandQueue=new A,new P({commandQueue:this.commandQueue})),this.webhookServer}async startWebhookServer(){let e=this.getWebhookServer();e.isRunning()||e.start()}async stopWebhookServer(){this.webhookServer&&(await this.webhookServer.stop(),this.webhookServer=void 0,this.commandQueue=void 0)}getRegistry(){return this.registry||=new C,this.registry}getWebhook(){return this.webhook||=new E,this.webhook}getCommandQueue(){return this.commandQueue||=new A,this.commandQueue}emitEvent(e,t){this.getWebhook().sendEvent(e,t).catch(()=>void 0)}resolveContext(e,t){let n=e[t];if(I(n))return n;let r=e.default;if(t===`default`&&I(r))return r;if(F(r)){let e=r[t];if(I(e))return e}return null}async handleWebhookDispatch(e){let n=i(e,`action`);switch(n){case`create`:return this.handleWebhookCreate(e);case`list`:return this.handleWebhookList();case`delete`:return this.handleWebhookDelete(e);case`commands`:return this.handleWebhookCommands(e);default:return t({error:`Invalid action: "${n}". Expected one of: create, list, delete, commands`})}}};export{L as ExtensionRegistryHandlers};
|
|
1
|
+
import{ia as e}from"./constants-DMv3svps.mjs";import{i as t,r as n}from"./outputPaths-D2ddHrOJ.mjs";import{n as r}from"./response-B1RuVVfD.mjs";import{a as i,c as a,o}from"./parse-args-ngRrvF9e.mjs";import{existsSync as s,mkdirSync as c,readFileSync as l,readdirSync as u}from"node:fs";import d from"node:path";import{mkdir as f,readFile as p,writeFile as m}from"node:fs/promises";import{fileURLToPath as h,pathToFileURL as g}from"node:url";import _ from"node:http";import{createHash as v}from"node:crypto";import{EventEmitter as y}from"node:events";function b(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function x(e){let t=e.trim().toLowerCase().replace(/\//g,`-`).replace(/(?!^@)[^a-z0-9@_-]+/g,`-`);return t.length>0?t:`plugin-${Date.now()}`}function S(e){if(!b(e))return null;let{id:t,name:n,version:r,entry:i,permissions:a,status:o}=e;return typeof t!=`string`||typeof n!=`string`||typeof r!=`string`||typeof i!=`string`||o!==`loaded`&&o!==`unloaded`?null:{id:t,name:n,version:r,entry:i,permissions:Array.isArray(a)?a.filter(e=>typeof e==`string`):[],status:o}}var C=class{rootDir;legacyPluginRoots;useLegacyScanApi;registryFile;moduleCacheDir;installedPlugins=new Map;loadedPlugins=new Map;constructor(e=n(),t=[]){let r=typeof e==`string`?e:n();this.useLegacyScanApi=typeof e!=`string`,this.rootDir=r,this.registryFile=d.join(r,`plugins.json`),this.moduleCacheDir=d.join(r,`modules`),this.legacyPluginRoots=t.length>0?t:process.env.JSHOOKMCP_PLUGIN_ROOT?[process.env.JSHOOKMCP_PLUGIN_ROOT]:[],!this.useLegacyScanApi&&this.initializeFromDisk()}async register(e){let t=x(e.id||e.name),n={id:t,name:e.name,version:e.version,entry:e.entry,permissions:e.permissions?[...e.permissions]:[],status:this.loadedPlugins.has(t)?`loaded`:`unloaded`};return this.installedPlugins.set(t,n),await this.persist(),t}async unregister(e){await this.unloadPlugin(e),this.installedPlugins.delete(e),await this.persist()}listInstalled(){return[...this.installedPlugins.values()].map(e=>({id:e.id,name:e.name,version:e.version,status:e.status,permissions:[...e.permissions]})).toSorted((e,t)=>e.name.localeCompare(t.name))}async loadPlugin(e){let t=this.installedPlugins.get(e);if(!t)throw Error(`Plugin not found: ${e}`);let n=this.loadedPlugins.get(e);if(n)return{manifest:this.toPublicManifest(n.manifest),exports:n.exports};let r=g(await this.resolveEntryPath(t));r.searchParams.set(`ts`,String(Date.now()));let i=await import(r.href),a=b(i)?i:{};return t.status=`loaded`,this.loadedPlugins.set(e,{manifest:t,exports:a}),await this.persist(),{manifest:this.toPublicManifest(t),exports:a}}async unloadPlugin(e){let t=this.installedPlugins.get(e);t&&(this.loadedPlugins.delete(e),t.status=`unloaded`,await this.persist())}initializeFromDisk(){if(s(this.rootDir)||c(this.rootDir,{recursive:!0}),s(this.moduleCacheDir)||c(this.moduleCacheDir,{recursive:!0}),!s(this.registryFile))return;let e=l(this.registryFile,`utf8`);if(!e.trim())return;let t=JSON.parse(e);if(Array.isArray(t))for(let e of t){let t=S(e);t&&this.installedPlugins.set(t.id,t)}}async persist(){await f(this.rootDir,{recursive:!0}),await f(this.moduleCacheDir,{recursive:!0}),await m(this.registryFile,JSON.stringify([...this.installedPlugins.values()],null,2),`utf8`)}async resolveEntryPath(e){return e.entry.startsWith(`http://`)||e.entry.startsWith(`https://`)?this.downloadRemoteModule(e.id,e.entry):e.entry.startsWith(`file://`)?h(new URL(e.entry)):d.isAbsolute(e.entry)?e.entry:d.resolve(t(),e.entry)}async downloadRemoteModule(e,t){let n=await fetch(t);if(!n.ok)throw Error(`Failed to download plugin module: ${n.status} ${n.statusText}`);let r=await n.text(),i=d.join(this.moduleCacheDir,`${x(e)}.mjs`),a=v(`sha256`).update(r).digest(`hex`);try{let e=await p(i,`utf8`);if(v(`sha256`).update(e).digest(`hex`)===a)return i}catch{}return await f(this.moduleCacheDir,{recursive:!0}),await m(i,r,`utf8`),i}toPublicManifest(e){return{id:e.id,name:e.name,version:e.version,entry:e.entry,permissions:[...e.permissions]}}listPlugins(){let e=[];for(let t of this.legacyPluginRoots){if(!s(t))continue;let n=u(t,{withFileTypes:!0});for(let r of n){if(!r.isDirectory()||r.name.startsWith(`.`))continue;let n=d.join(t,r.name,`package.json`);if(s(n))try{let t=JSON.parse(l(n,`utf8`)),r=this.toLegacyPluginInfo(t);r&&e.push(r)}catch{continue}}}return e}searchPlugins(e){let t=e.trim().toLowerCase();return t?this.listPlugins().filter(e=>e.name.toLowerCase().includes(t)||(e.description??``).toLowerCase().includes(t)||(e.capabilities??[]).some(e=>e.toLowerCase().includes(t))||(e.dependencies??[]).some(e=>e.toLowerCase().includes(t))):this.listPlugins()}async installPlugin(e){if(/^https:\/\/github\.com\/.+\.git$/u.test(e)||/^git@github\.com:.+\.git$/u.test(e))return{id:`git-plugin`,name:e.split(`/`).pop()?.replace(/\.git$/u,``)??`plugin`,version:`0.0.0`};if(e.includes(`://`)||e.startsWith(`git@`)||e===`invalid-url`)throw Error(`Invalid git URL`);if(e.startsWith(`/`)||e.includes(`\\`)){let t=d.join(e,`package.json`);if(!s(t))throw Error(`No package.json`);let n=JSON.parse(l(t,`utf8`)),r=this.toLegacyPluginInfo(n);if(!r)throw Error(`No package.json`);return r}for(let t of this.legacyPluginRoots){let n=d.join(t,e,`package.json`);if(!s(n))continue;let r=JSON.parse(l(n,`utf8`)),i=this.toLegacyPluginInfo(r);if(i)return i}throw Error(`Plugin not found`)}getPluginInfo(e){return this.listPlugins().find(t=>t.id===e||t.name===e)}getPluginDependencies(e){return this.getPluginInfo(e)?.dependencies??[]}async uninstallPlugin(e){}toLegacyPluginInfo(e){if(typeof e.name!=`string`)return null;let t=b(e.dependencies)?Object.keys(e.dependencies):[];return{id:x(e.name),name:e.name,version:typeof e.version==`string`?e.version:`0.0.0`,description:typeof e.description==`string`?e.description:void 0,capabilities:Array.isArray(e.capabilities)?e.capabilities.filter(e=>typeof e==`string`):void 0,dependencies:t}}};function w(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function T(e){if(!w(e))return null;let{id:t,url:n,events:r,active:i}=e;return typeof t!=`string`||typeof n!=`string`||!Array.isArray(r)||typeof i!=`boolean`?null:{id:t,url:n,events:r.filter(e=>typeof e==`string`),active:i}}var E=class{rootDir;storageFile;webhooks=new Map;constructor(e=n()){this.rootDir=e,this.storageFile=d.join(e,`webhooks.json`),this.initializeFromDisk()}async registerWebhook(e,t){new URL(e);let n={id:`webhook-${Date.now()}-${this.webhooks.size+1}`,url:e,events:[...new Set(t.filter(e=>e.trim().length>0))],active:!0};return this.webhooks.set(n.id,n),await this.persist(),n.id}async sendEvent(e,t){let n=[...this.webhooks.values()].filter(t=>t.active&&(t.events.includes(e)||t.events.includes(`*`)));for(let r of n){let n=await fetch(r.url,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({event:e,payload:t,timestamp:new Date().toISOString()})});if(!n.ok)throw Error(`Webhook delivery failed for ${r.url}: ${n.status} ${n.statusText}`)}}listWebhooks(){return[...this.webhooks.values()].map(e=>({id:e.id,url:e.url,events:[...e.events],active:e.active}))}registerExternalCallback(e,t){let n=this.webhooks.get(e);if(n){n.url=t;return}this.webhooks.set(e,{id:e,url:t,events:[`*`],active:!0})}initializeFromDisk(){if(s(this.rootDir)||c(this.rootDir,{recursive:!0}),!s(this.storageFile))return;let e=l(this.storageFile,`utf8`);if(!e.trim())return;let t=JSON.parse(e);if(Array.isArray(t))for(let e of t){let t=T(e);t&&this.webhooks.set(t.id,t)}}async persist(){await f(this.rootDir,{recursive:!0}),await m(this.storageFile,JSON.stringify([...this.webhooks.values()],null,2),`utf8`)}};function D(e){return{...e}}function O(){return new Date().toISOString()}var k=class extends y{maxQueueSize;commands=new Map;order=[];maxRetries;retryDelay;processTimeout;nextId=1;constructor(t={}){super(),this.maxQueueSize=typeof t.maxQueueSize==`number`?t.maxQueueSize:1e3,this.maxRetries=typeof t.maxRetries==`number`?t.maxRetries:3,this.retryDelay=typeof t.retryDelay==`number`?t.retryDelay:0,this.processTimeout=typeof t.processTimeout==`number`?t.processTimeout:e}enqueue(e){if(this.order.length>=this.maxQueueSize)throw Error(`Command queue is full (${this.maxQueueSize})`);let t=`cmd-${this.nextId}`;this.nextId+=1;let n=O(),r={id:t,endpointId:e.endpointId,event:e.event,payload:e.payload,status:`pending`,retries:0,createdAt:n,updatedAt:n};return this.commands.set(t,r),this.order.push(t),this.emit(`enqueued`,D(r)),t}dequeue(e){if(!e){let e=this.getCommandsByFilter({status:`pending`})[0];return e?D(e):void 0}return this.getCommandsByFilter(e).map(D)}getStatus(e){let t=this.commands.get(e);return t?t.status===`processed`?`completed`:t.status:`failed`}retry(e){let t=this.commands.get(e);if(!t)throw Error(`Command ${e} not found`);if(t.status!==`failed`)throw Error(`Command ${e} is not in failed state`);t.status=`pending`,t.retries=0,t.lastError=void 0,t.updatedAt=O()}getCommand(e){return this.commands.get(e)}getCommandsByFilter(e){let t=e.status===`completed`?`processed`:e.status,n=[];for(let r of this.order){let i=this.commands.get(r);i&&(t&&i.status!==t||e.endpointId&&i.endpointId!==e.endpointId||n.push(i))}return n}updateStatus(e,t,n){let r=this.commands.get(e);if(!r)throw Error(`Command ${e} not found`);return r.status=t,r.updatedAt=O(),r.lastError=n,r}},A=class extends k{async process(e,t){let n=this.getCommand(e);if(!n)throw Error(`Command ${e} not found`);if(n.status===`processed`)throw Error(`Command ${e} already processed`);if(n.status===`failed`)throw Error(`Command ${e} already processed with failure`);if(n.status===`processing`)throw Error(`Command ${e} is already processing`);this.updateStatus(e,`processing`);let r=`processed`,i;try{await Promise.race([Promise.resolve(t(D(n))),new Promise((e,t)=>{setTimeout(()=>{t(Error(`Process timeout`))},this.processTimeout)})])}catch(e){i=e instanceof Error?e.message:String(e),r=n.retries+1>=this.maxRetries?`failed`:`pending`}if(i!==void 0&&this.retryDelay>0&&setTimeout(()=>{},this.retryDelay),r===`processed`){let t=this.updateStatus(e,`processed`);this.emit(`processed`,D(t))}else if(r===`pending`){n.retries+=1;let t=this.updateStatus(e,`pending`,i);throw this.emit(`retried`,D(t)),Error(i===void 0?`retry`:i)}else{let t=this.updateStatus(e,`failed`,i);throw this.emit(`failed`,D(t)),Error(i===void 0?`failed`:i)}}async retry(e){super.retry(e)}exportState(){let e=[];for(let t of this.order){let n=this.commands.get(t);n&&e.push(D(n))}return e}importState(e){this.commands.clear(),this.order.length=0;let t=0;for(let n of e){let e=D(n);this.commands.set(e.id,e),this.order.push(e.id);let r=/^cmd-(\d+)$/.exec(e.id);if(r&&r[1]){let e=parseInt(r[1],10);e>t&&(t=e)}}t>0&&(this.nextId=t+1)}};function j(e){return e===`tool_called`||e===`domain_activated`||e===`evidence_added`||e===`workflow_completed`}function M(e){if(e.length===0)return{};try{return JSON.parse(e)}catch{return{rawBody:e}}}var N=class extends y{endpoints=new Map;eventHandlers=new Map;port;commandQueue;stats={eventsRegistered:0,webhooksSent:0};server;nextEndpointId=1;constructor(e={}){super(),this.port=typeof e.port==`number`?e.port:18789,this.commandQueue=e.commandQueue}registerEndpoint(e){let t=`ep-${this.nextEndpointId}`;return this.nextEndpointId+=1,this.endpoints.set(t,{id:t,path:e.path,method:e.method??`POST`,secret:e.secret}),this.emit(`endpointRegistered`,t),t}removeEndpoint(e){if(!this.endpoints.delete(e))throw Error(`Endpoint ${e} not found`);this.emit(`endpointRemoved`,e)}listEndpoints(){return[...this.endpoints.values()].map(e=>({...e}))}getPort(){return this.port}isRunning(){return this.server!==void 0}registerEvent(e,t){let n=this.eventHandlers.get(e)??[];n.push(t),this.eventHandlers.set(e,n),this.stats.eventsRegistered+=1}start(){if(this.server)throw Error(`Webhook server already started`);this.server=_.createServer((e,t)=>{this.handleRequest(e,t)}),this.server.listen(this.port),this.emit(`started`,this.port)}async stop(){if(!this.server)return;let e=this.server;this.server=void 0,await new Promise((t,n)=>{e.close(e=>{if(e){n(e);return}t()})}),this.emit(`stopped`)}async sendWebhook(e,t,n){await fetch(e,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({event:t,payload:n})}),this.stats.webhooksSent+=1,this.stats.lastSentAt=new Date().toISOString()}getStats(){return{...this.stats}}async handleRequest(e,t){let n=e.method??`GET`,r=e.url??`/`,i=[...this.endpoints.values()].find(e=>e.path===r&&e.method===n);if(!i){t.statusCode=404,t.end(`not found`);return}if(i.secret&&e.headers[`x-webhook-secret`]!==i.secret){t.statusCode=401,t.end(`unauthorized`);return}let a=[];await new Promise((t,n)=>{e.setEncoding(`utf8`),e.on(`data`,e=>{a.push(e)}),e.on(`end`,()=>{t()}),e.on(`error`,e=>{n(e)})});let o=M(a.join(``));this.commandQueue&&this.commandQueue.enqueue({endpointId:i.id,payload:o}),o&&typeof o==`object`&&`event`in o&&typeof o.event==`string`&&await this.invokeEventHandlers(o.event,o),t.setHeader(`content-type`,`application/json`),t.end(JSON.stringify({ok:!0,endpointId:i.id}))}async invokeEventHandlers(e,t){if(!j(e))return;let n=this.eventHandlers.get(e)??[];for(let e of n)await Promise.resolve(e(t))}},P=class extends N{};function F(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function I(e){return typeof e==`function`}var L=class{registry;webhook;webhookServer;commandQueue;constructor(e,t){this.registry=e,this.webhook=t}async handleListInstalled(){return r({success:!0,plugins:this.getRegistry().listInstalled()})}async handleExecuteInContext(e){let t=a(e,`pluginId`),n=a(e,`contextName`),o=i(e,`args`)??{},{manifest:s,exports:c}=await this.getRegistry().loadPlugin(t),l=this.resolveContext(c,n);if(!l)throw Error(`Context "${n}" was not found in plugin "${t}"`);let u=await Promise.resolve(l(o));return this.emitEvent(`extension.executed`,{pluginId:t,contextName:n}),r({success:!0,manifest:s,contextName:n,result:u})}async handleReload(e){let t=a(e,`pluginId`);await this.getRegistry().unloadPlugin(t);let n=await this.getRegistry().loadPlugin(t);return this.emitEvent(`extension.reloaded`,{pluginId:t}),r({success:!0,pluginId:t,manifest:n.manifest,exportedKeys:Object.keys(n.exports).toSorted()})}async handleUninstall(e){let t=a(e,`pluginId`);return await this.getRegistry().unregister(t),this.emitEvent(`extension.uninstalled`,{pluginId:t}),r({success:!0,pluginId:t})}async handleWebhookCreate(e){let t=a(e,`name`),n=a(e,`path`),i=o(e,`secret`),s=Array.isArray(e.events)?e.events.filter(e=>typeof e==`string`):[],c=this.getWebhookServer();c.isRunning()||c.start();let l=c.registerEndpoint({path:n,method:`POST`,secret:i??void 0}),u=this.getWebhook(),d=`http://localhost:${c.getPort()}${n}`;return u.registerExternalCallback(l,d),r({success:!0,endpointId:l,url:d,name:t,events:s})}async handleWebhookList(){let e=this.getWebhookServer();return r({success:!0,endpoints:e.listEndpoints(),port:e.getPort(),running:e.isRunning()})}async handleWebhookDelete(e){let t=a(e,`endpointId`),n=this.getWebhookServer();try{n.removeEndpoint(t)}catch(e){throw Error(`GRACEFUL: ${e instanceof Error?e.message:String(e)}`,{cause:e})}return r({success:!0,endpointId:t})}async handleWebhookCommands(e){let t=a(e,`endpointId`),n=o(e,`status`),s=i(e,`command`);if(s)return r({success:!0,commandId:this.getCommandQueue().enqueue({endpointId:t,payload:s}),status:`pending`});let c=this.getCommandQueue(),l={endpointId:t};n&&(l.status=n);let u=c.dequeue(l);return r({success:!0,endpointId:t,commands:u,count:Array.isArray(u)?u.length:+!!u})}getWebhookServer(){return this.webhookServer||=(this.commandQueue=new A,new P({commandQueue:this.commandQueue})),this.webhookServer}async startWebhookServer(){let e=this.getWebhookServer();e.isRunning()||e.start()}async stopWebhookServer(){this.webhookServer&&(await this.webhookServer.stop(),this.webhookServer=void 0,this.commandQueue=void 0)}getRegistry(){return this.registry||=new C,this.registry}getWebhook(){return this.webhook||=new E,this.webhook}getCommandQueue(){return this.commandQueue||=new A,this.commandQueue}emitEvent(e,t){this.getWebhook().sendEvent(e,t).catch(()=>void 0)}resolveContext(e,t){let n=e[t];if(I(n))return n;let r=e.default;if(t==="default"&&I(r))return r;if(F(r)){let e=r[t];if(I(e))return e}return null}async handleWebhookDispatch(e){let t=o(e,`action`);switch(t){case`create`:return this.handleWebhookCreate(e);case`list`:return this.handleWebhookList();case`delete`:return this.handleWebhookDelete(e);case`commands`:return this.handleWebhookCommands(e);default:return r({error:`Invalid action: "${t}". Expected one of: create, list, delete, commands`})}}};export{L as ExtensionRegistryHandlers};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n as e,r as t}from"./response-
|
|
1
|
+
import{n as e,r as t}from"./response-B1RuVVfD.mjs";var n=class{graph;constructor(e){this.graph=e}pickStringArg(e,t){for(let n of t){let t=e[n];if(typeof t==`string`&&t.length>0)return t}}serializeNodes(e){return e.map(e=>({id:e.id,type:e.type,label:e.label,metadata:e.metadata}))}handleQueryDispatch(e){switch(e.by){case`function`:return this.handleQueryFunction({...e,name:this.pickStringArg(e,[`name`,`value`,`query`])});case`script`:return this.handleQueryScript({...e,scriptId:this.pickStringArg(e,[`scriptId`,`value`,`query`])});default:return this.handleQueryUrl({...e,url:this.pickStringArg(e,[`url`,`value`,`query`])})}}handleExportDispatch(e){return e.format===`markdown`?this.handleExportMarkdown():this.handleExportJson()}handleQueryUrl(t){let n=t.url,r=this.graph.queryByUrl(n);return e({query:{type:`url`,value:n},resultCount:r.length,nodes:this.serializeNodes(r)})}handleQueryFunction(t){let n=t.name,r=this.graph.queryByFunction(n);return e({query:{type:`function`,value:n},resultCount:r.length,nodes:this.serializeNodes(r)})}handleQueryScript(t){let n=t.scriptId,r=this.graph.queryByScriptId(n);return e({query:{type:`scriptId`,value:n},resultCount:r.length,nodes:this.serializeNodes(r)})}handleExportJson(){return e(this.graph.exportJson())}handleExportMarkdown(){let e=this.graph.exportMarkdown(),n=this.graph.exportJson();if(!n||!Array.isArray(n.nodes))return t(e);let r=n.nodes.filter(e=>n.edges.filter(t=>t.target===e.id).length===0),i=n.nodes.filter(e=>n.edges.filter(t=>t.source===e.id).length===0),a=n.edges.filter(e=>e.metadata&&typeof e.metadata.confidence==`number`&&e.metadata.confidence<.3),o=[];return o.push(``),o.push(`## Evidence Gaps`),o.push(``),o.push(`- **Dangling nodes (no inbound edges):** ${r.length}`),r.length>0&&o.push(` ${r.slice(0,10).map(e=>`\`${e.type}:${e.label}\``).join(`, `)}`),o.push(`- **Dangling nodes (no outbound edges):** ${i.length}`),i.length>0&&o.push(` ${i.slice(0,10).map(e=>`\`${e.type}:${e.label}\``).join(`, `)}`),o.push(`- **Low-confidence edges (<0.3):** ${a.length}`),r.length===0&&i.length===0&&a.length===0&&o.push(`- **Status:** No gaps detected — evidence chain is fully connected.`),o.push(``),t(e+o.join(`
|
|
2
2
|
`))}handleChain(t){let n=t.nodeId,r=t.direction??`forward`,i=this.graph.getEvidenceChain(n,r);return e({startNode:n,direction:r,chainLength:i.length,nodes:this.serializeNodes(i)})}};export{n as EvidenceHandlers};
|