agentic-qe 3.8.13 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +48 -0
- package/dist/adapters/a2ui/integration/agui-sync.js +2 -1
- package/dist/audit/witness-chain.js +15 -3
- package/dist/boot/fast-paths.d.ts +24 -0
- package/dist/boot/fast-paths.js +43 -0
- package/dist/boot/parallel-prefetch.d.ts +26 -0
- package/dist/boot/parallel-prefetch.js +36 -0
- package/dist/cli/bundle.js +12 -9431
- package/dist/cli/chunks/adapter-WBR5NXS3.js +2 -0
- package/dist/cli/chunks/agent-booster-wasm-PQYB7VRU.js +2 -0
- package/dist/cli/chunks/agent-handler-QDAB5NQS.js +33 -0
- package/dist/cli/chunks/aqe-learning-engine-TK4JQCGT.js +2 -0
- package/dist/cli/chunks/audit-S7JUYYVP.js +3 -0
- package/dist/cli/chunks/base-2WXOSMBQ.js +2 -0
- package/dist/cli/chunks/better-sqlite3-7KY2RDXO.js +2 -0
- package/dist/cli/chunks/brain-handler-PPEGDCN4.js +68 -0
- package/dist/cli/chunks/branch-enumerator-XK4V5W7L.js +7 -0
- package/dist/cli/chunks/browser-PALA5PL3.js +4 -0
- package/dist/cli/chunks/browser-workflow-42F7GK5T.js +2 -0
- package/dist/cli/chunks/chunk-24FKIJNC.js +15 -0
- package/dist/cli/chunks/chunk-263XS447.js +2 -0
- package/dist/cli/chunks/chunk-2BZFNEN2.js +4 -0
- package/dist/cli/chunks/chunk-2E5NQNSU.js +180 -0
- package/dist/cli/chunks/chunk-2I7J3O6V.js +2 -0
- package/dist/cli/chunks/chunk-3ADGXLTM.js +14 -0
- package/dist/cli/chunks/chunk-3IHG3WOY.js +12 -0
- package/dist/cli/chunks/chunk-3IUNFTIF.js +2 -0
- package/dist/cli/chunks/chunk-3JPRUND5.js +2 -0
- package/dist/cli/chunks/chunk-3NZLZHJI.js +2 -0
- package/dist/cli/chunks/chunk-3THRQEZ2.js +95 -0
- package/dist/cli/chunks/chunk-3ZOONQG6.js +2 -0
- package/dist/cli/chunks/chunk-4B6NCELM.js +2 -0
- package/dist/cli/chunks/chunk-4I2IOUS4.js +2 -0
- package/dist/cli/chunks/chunk-4VBTXZRM.js +2 -0
- package/dist/cli/chunks/chunk-4VUPRTVX.js +3 -0
- package/dist/cli/chunks/chunk-4YOMLWEK.js +70 -0
- package/dist/cli/chunks/chunk-4YS3IJ45.js +2 -0
- package/dist/cli/chunks/chunk-5SKGFSKD.js +2 -0
- package/dist/cli/chunks/chunk-5T2ZQWKF.js +27 -0
- package/dist/cli/chunks/chunk-62ADTHV7.js +2 -0
- package/dist/cli/chunks/chunk-6EOS7KX2.js +2 -0
- package/dist/cli/chunks/chunk-6SVX4DJC.js +6 -0
- package/dist/cli/chunks/chunk-72WOAVK6.js +2 -0
- package/dist/cli/chunks/chunk-7R6YMLVS.js +3 -0
- package/dist/cli/chunks/chunk-7VDBAVTY.js +2 -0
- package/dist/cli/chunks/chunk-AFLLQ5PP.js +15 -0
- package/dist/cli/chunks/chunk-AKE543X2.js +2 -0
- package/dist/cli/chunks/chunk-B36CDR4U.js +2 -0
- package/dist/cli/chunks/chunk-B6LLWYQ6.js +2 -0
- package/dist/cli/chunks/chunk-BDIEMZ22.js +91 -0
- package/dist/cli/chunks/chunk-BGXNSCXX.js +4 -0
- package/dist/cli/chunks/chunk-BLBRY5UD.js +2 -0
- package/dist/cli/chunks/chunk-BPWXXEH2.js +3029 -0
- package/dist/cli/chunks/chunk-BR26T7ZS.js +180 -0
- package/dist/cli/chunks/chunk-BTREG4IW.js +2 -0
- package/dist/cli/chunks/chunk-BULKFVYX.js +2 -0
- package/dist/cli/chunks/chunk-BXAXGEFC.js +24 -0
- package/dist/cli/chunks/chunk-CL6POIX4.js +2 -0
- package/dist/cli/chunks/chunk-CS2KS7LP.js +2 -0
- package/dist/cli/chunks/chunk-CWFB6BSA.js +316 -0
- package/dist/cli/chunks/chunk-DRT3WKQW.js +2 -0
- package/dist/cli/chunks/chunk-EHDQJQ6Y.js +27 -0
- package/dist/cli/chunks/chunk-ESVQ6MEB.js +2 -0
- package/dist/cli/chunks/chunk-FEKY7T6Q.js +2 -0
- package/dist/cli/chunks/chunk-FGA7VIFR.js +7 -0
- package/dist/cli/chunks/chunk-FIA6X7UL.js +2 -0
- package/dist/cli/chunks/chunk-GAOJV3OX.js +2 -0
- package/dist/cli/chunks/chunk-GKNNSCLC.js +5 -0
- package/dist/cli/chunks/chunk-GPQ57KA4.js +2 -0
- package/dist/cli/chunks/chunk-GRUUQAR6.js +2 -0
- package/dist/cli/chunks/chunk-HRO6OZQD.js +2 -0
- package/dist/cli/chunks/chunk-HY6PMO5W.js +66 -0
- package/dist/cli/chunks/chunk-IAV2JMIX.js +167 -0
- package/dist/cli/chunks/chunk-IFNIIK34.js +21 -0
- package/dist/cli/chunks/chunk-IGJPMN4I.js +3 -0
- package/dist/cli/chunks/chunk-J3KWWR6Z.js +1 -0
- package/dist/cli/chunks/chunk-JBANAPWG.js +2 -0
- package/dist/cli/chunks/chunk-JJO7Y4H3.js +604 -0
- package/dist/cli/chunks/chunk-JRYGQO2W.js +2 -0
- package/dist/cli/chunks/chunk-JXM26HEE.js +2 -0
- package/dist/cli/chunks/chunk-JZSDOIXA.js +2 -0
- package/dist/cli/chunks/chunk-KP5NUODU.js +3 -0
- package/dist/cli/chunks/chunk-LHJQD2VU.js +750 -0
- package/dist/cli/chunks/chunk-LNQIY6BP.js +2 -0
- package/dist/cli/chunks/chunk-MDUHYUHF.js +2 -0
- package/dist/cli/chunks/chunk-MV6CMOJQ.js +65 -0
- package/dist/cli/chunks/chunk-MZOFWJTM.js +2 -0
- package/dist/cli/chunks/chunk-N2NS2PHA.js +45 -0
- package/dist/cli/chunks/chunk-N4TL73TH.js +314 -0
- package/dist/cli/chunks/chunk-N5UXCLFI.js +2 -0
- package/dist/cli/chunks/chunk-NZ2VCPN4.js +2 -0
- package/dist/cli/chunks/chunk-OF4D7MYI.js +2 -0
- package/dist/cli/chunks/chunk-OI5NGQO2.js +2 -0
- package/dist/cli/chunks/chunk-OLHKGP35.js +2 -0
- package/dist/cli/chunks/chunk-QOVHWZEP.js +1 -0
- package/dist/cli/chunks/chunk-RFSN6IDA.js +79 -0
- package/dist/cli/chunks/chunk-RTGGL7D7.js +4 -0
- package/dist/cli/chunks/chunk-RU5WAHB7.js +3 -0
- package/dist/cli/chunks/chunk-SUSEVMZT.js +2 -0
- package/dist/cli/chunks/chunk-TLHP5EII.js +2 -0
- package/dist/cli/chunks/chunk-TWUWL5EJ.js +2 -0
- package/dist/cli/chunks/chunk-U5RN7YQW.js +2 -0
- package/dist/cli/chunks/chunk-UFUVUO3J.js +2 -0
- package/dist/cli/chunks/chunk-UQHYFOBX.js +16 -0
- package/dist/cli/chunks/chunk-VOS4NQSF.js +2 -0
- package/dist/cli/chunks/chunk-VSVXUTJN.js +256 -0
- package/dist/cli/chunks/chunk-WBQSXPBI.js +2 -0
- package/dist/cli/chunks/chunk-WGMPEW2T.js +2 -0
- package/dist/cli/chunks/chunk-WIEC7VKK.js +2 -0
- package/dist/cli/chunks/chunk-WJ3DLOXF.js +14 -0
- package/dist/cli/chunks/chunk-X3KI6JOY.js +9 -0
- package/dist/cli/chunks/chunk-X5IJGWYG.js +2 -0
- package/dist/cli/chunks/chunk-XIBDETCS.js +146 -0
- package/dist/cli/chunks/chunk-XLRQYLWW.js +2 -0
- package/dist/cli/chunks/chunk-XO6PVK2P.js +3 -0
- package/dist/cli/chunks/chunk-XRE2HCWG.js +3 -0
- package/dist/cli/chunks/chunk-XT2V2322.js +2 -0
- package/dist/cli/chunks/chunk-Y7BHKZFJ.js +18 -0
- package/dist/cli/chunks/chunk-YAGODYIG.js +59 -0
- package/dist/cli/chunks/chunk-YANUP2RO.js +2 -0
- package/dist/cli/chunks/chunk-YPFOCNOE.js +30 -0
- package/dist/cli/chunks/chunk-YR6ZZGH7.js +81 -0
- package/dist/cli/chunks/chunk-YVA65UZL.js +2 -0
- package/dist/cli/chunks/chunk-YW2THB5Q.js +2 -0
- package/dist/cli/chunks/chunk-ZAPS3UGQ.js +20 -0
- package/dist/cli/chunks/chunk-ZDATDCYN.js +2 -0
- package/dist/cli/chunks/ci-J374KDLI.js +81 -0
- package/dist/cli/chunks/ci-output-7JN7F6CI.js +2 -0
- package/dist/cli/chunks/claude-flow-setup-245JLJCN.js +2 -0
- package/dist/cli/chunks/client-MCSNSH2C.js +2 -0
- package/dist/cli/chunks/cline-installer-LBA2M5N3.js +4 -0
- package/dist/cli/chunks/code-U4N4WONM.js +38 -0
- package/dist/cli/chunks/code-index-extractor-A57Z6BO4.js +3 -0
- package/dist/cli/chunks/codex-installer-UXMK2N4T.js +8 -0
- package/dist/cli/chunks/completions-W66BSCOE.js +1364 -0
- package/dist/cli/chunks/complexity-analyzer-AB4OZARV.js +2 -0
- package/dist/cli/chunks/continuedev-installer-LRFZ2SJM.js +14 -0
- package/dist/cli/chunks/copilot-installer-CQ3JYBIB.js +3 -0
- package/dist/cli/chunks/cost-tracker-4F723RB6.js +2 -0
- package/dist/cli/chunks/coverage-4PUEQXAY.js +27 -0
- package/dist/cli/chunks/cross-domain-router-OWR5IJ5G.js +2 -0
- package/dist/cli/chunks/cursor-installer-JZEDEDHA.js +3 -0
- package/dist/cli/chunks/daemon-B7TWGHXQ.js +19 -0
- package/dist/cli/chunks/dag-attention-scheduler-JWO6XI6A.js +2 -0
- package/dist/cli/chunks/detect-L6ZZHUSX.js +2 -0
- package/dist/cli/chunks/domain-handler-FT5FLZWL.js +25 -0
- package/dist/cli/chunks/domain-transfer-5Y4FGJAJ.js +2 -0
- package/dist/cli/chunks/dream-4TDBIYED.js +2 -0
- package/dist/cli/chunks/esm-node-2PKHKOTS.js +2 -0
- package/dist/cli/chunks/eval-GHMPFGWV.js +15 -0
- package/dist/cli/chunks/fast-paths-B3R647KN.js +2 -0
- package/dist/cli/chunks/feature-flags-DWS7ARSX.js +2 -0
- package/dist/cli/chunks/feature-flags-IVQ3AL4Q.js +2 -0
- package/dist/cli/chunks/file-discovery-QFPA6GMV.js +2 -0
- package/dist/cli/chunks/fleet-EKOKMOMW.js +43 -0
- package/dist/cli/chunks/gnn-wrapper-OYC55N5E.js +2 -0
- package/dist/cli/chunks/heartbeat-handler-MBBS4IBU.js +48 -0
- package/dist/cli/chunks/heartbeat-scheduler-XDGMOT7X.js +2 -0
- package/dist/cli/chunks/hnsw-index-YO7CT23I.js +2 -0
- package/dist/cli/chunks/hnswlib-node-56YWVXFE.js +2 -0
- package/dist/cli/chunks/hooks-L5VLZGEK.js +101 -0
- package/dist/cli/chunks/hypergraph-engine-A4Y2ZRAG.js +2 -0
- package/dist/cli/chunks/hypergraph-handler-3HDGB5SZ.js +35 -0
- package/dist/cli/chunks/impact-analyzer-UEIGXSZ4.js +2 -0
- package/dist/cli/chunks/init-handler-JDET6WUN.js +68 -0
- package/dist/cli/chunks/init-wizard-JWZUGIPJ.js +2 -0
- package/dist/cli/chunks/kernel-YNDTVKIW.js +2 -0
- package/dist/cli/chunks/kilocode-installer-GZZG5AFW.js +4 -0
- package/dist/cli/chunks/kiro-installer-IWNY5TKH.js +74 -0
- package/dist/cli/chunks/knowledge-graph-NGJKFTSN.js +2 -0
- package/dist/cli/chunks/learning-722ZNSZ6.js +107 -0
- package/dist/cli/chunks/llm-router-DNAV746L.js +30 -0
- package/dist/cli/chunks/load-Y3GCUFM4.js +2 -0
- package/dist/cli/chunks/load-test-GZUBXFF3.js +2 -0
- package/dist/cli/chunks/mcp-LKPIBZ3W.js +2 -0
- package/dist/cli/chunks/memory-L57MLFOP.js +32 -0
- package/dist/cli/chunks/memory-backend-3NQIZUXE.js +2 -0
- package/dist/cli/chunks/memory-handlers-MDZQ7HVW.js +2 -0
- package/dist/cli/chunks/opencode-installer-4HUB36H5.js +3 -0
- package/dist/cli/chunks/orchestrator-QHSBB2UC.js +371 -0
- package/dist/cli/chunks/pipeline-D3QER35Z.js +19 -0
- package/dist/cli/chunks/platform-T4E7Q3RD.js +2 -0
- package/dist/cli/chunks/plugin-JHW2YPRC.js +27 -0
- package/dist/cli/chunks/prime-radiant-advanced-wasm-G7CFNNQV.js +2 -0
- package/dist/cli/chunks/protocol-executor-SPUVRDWT.js +2 -0
- package/dist/cli/chunks/protocol-handler-2BQQ4HDM.js +20 -0
- package/dist/cli/chunks/prove-UQ6JFT73.js +3 -0
- package/dist/cli/chunks/qe-reasoning-bank-3HBK2FVD.js +2 -0
- package/dist/cli/chunks/quality-JRZYMC77.js +7 -0
- package/dist/cli/chunks/queen-coordinator-RW3NKO5A.js +2 -0
- package/dist/cli/chunks/real-embeddings-GK63VF35.js +2 -0
- package/dist/cli/chunks/roocode-installer-F4E2LAYR.js +4 -0
- package/dist/cli/chunks/router-RJGHWDQ3.js +2 -0
- package/dist/cli/chunks/routing-feedback-ZXBXFKX6.js +2 -0
- package/dist/cli/chunks/routing-handler-VNKFUUGB.js +20 -0
- package/dist/cli/chunks/ruvector-commands-2TLNHC3A.js +8 -0
- package/dist/cli/chunks/rvf-dual-writer-MQW2SJLT.js +2 -0
- package/dist/cli/chunks/rvf-native-adapter-LKFKTMUN.js +2 -0
- package/dist/cli/chunks/safe-db-G22E5ROA.js +2 -0
- package/dist/cli/chunks/schedule-Y7VVCPYV.js +2 -0
- package/dist/cli/chunks/scheduler-AUQIFQB7.js +2 -0
- package/dist/cli/chunks/security-EBEG2OPU.js +14 -0
- package/dist/cli/chunks/shared-rvf-dual-writer-BVSCQAFS.js +2 -0
- package/dist/cli/chunks/sqlite-persistence-JAVHUGGL.js +2 -0
- package/dist/cli/chunks/status-handler-VZ32M4G4.js +45 -0
- package/dist/cli/chunks/structural-health-K6LRCKV6.js +2 -0
- package/dist/cli/chunks/sync-MHSHNLIM.js +23 -0
- package/dist/cli/chunks/task-handler-JNOIBZ2G.js +49 -0
- package/dist/cli/chunks/task-handlers-P5DSUKND.js +2 -0
- package/dist/cli/chunks/test-DO22BNIL.js +33 -0
- package/dist/cli/chunks/test-scheduling-VLRQZEFL.js +15 -0
- package/dist/cli/chunks/token-bootstrap-4VJKGVMK.js +2 -0
- package/dist/cli/chunks/token-usage-LG3PXRXH.js +25 -0
- package/dist/cli/chunks/transformers-GY7SIKEU.js +2 -0
- package/dist/cli/chunks/tree-sitter-wasm-parser-FT2KB66N.js +2 -0
- package/dist/cli/chunks/types-QJGNBKP2.js +2 -0
- package/dist/cli/chunks/unified-memory-XYGENQUT.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-MVEGQBF3.js +2 -0
- package/dist/cli/chunks/unified-persistence-PFRCWEUG.js +2 -0
- package/dist/cli/chunks/validate-VQCRSVNQ.js +21 -0
- package/dist/cli/chunks/validate-swarm-A5DHAWTP.js +14 -0
- package/dist/cli/chunks/vibium-RZBSL4EB.js +2 -0
- package/dist/cli/chunks/visual-security-V47BLGJM.js +2 -0
- package/dist/cli/chunks/web-tree-sitter-7C4NXEOF.js +2 -0
- package/dist/cli/chunks/windsurf-installer-ES3KPQG3.js +7 -0
- package/dist/cli/chunks/witness-chain-BR63P4A7.js +2 -0
- package/dist/cli/chunks/workflow-JETHX4ML.js +51 -0
- package/dist/cli/chunks/workflow-orchestrator-7PZMX3JZ.js +2 -0
- package/dist/cli/chunks/wrappers-WP5RH745.js +2 -0
- package/dist/cli/commands/daemon.d.ts +13 -0
- package/dist/cli/commands/daemon.js +224 -0
- package/dist/cli/commands/hooks-handlers/hooks-shared.js +2 -1
- package/dist/cli/commands/plugin.d.ts +12 -0
- package/dist/cli/commands/plugin.js +135 -0
- package/dist/cli/commands/workflow.d.ts +10 -0
- package/dist/cli/commands/workflow.js +587 -0
- package/dist/cli/handlers/brain-handler.js +13 -8
- package/dist/cli/handlers/heartbeat-handler.d.ts +1 -0
- package/dist/cli/handlers/heartbeat-handler.js +20 -10
- package/dist/cli/handlers/hypergraph-handler.js +3 -3
- package/dist/cli/handlers/init-handler.js +10 -9
- package/dist/cli/handlers/interfaces.d.ts +4 -4
- package/dist/cli/index.js +159 -638
- package/dist/cli/lazy-registry.d.ts +27 -0
- package/dist/cli/lazy-registry.js +70 -0
- package/dist/context/compaction/context-budget.d.ts +71 -0
- package/dist/context/compaction/context-budget.js +120 -0
- package/dist/context/compaction/index.d.ts +96 -0
- package/dist/context/compaction/index.js +259 -0
- package/dist/context/compaction/llm-caller-adapter.d.ts +14 -0
- package/dist/context/compaction/llm-caller-adapter.js +47 -0
- package/dist/context/compaction/tier1-microcompact.d.ts +33 -0
- package/dist/context/compaction/tier1-microcompact.js +47 -0
- package/dist/context/compaction/tier2-session-summary.d.ts +72 -0
- package/dist/context/compaction/tier2-session-summary.js +172 -0
- package/dist/context/compaction/tier3-llm-compact.d.ts +65 -0
- package/dist/context/compaction/tier3-llm-compact.js +166 -0
- package/dist/context/compaction/tier4-reactive.d.ts +54 -0
- package/dist/context/compaction/tier4-reactive.js +129 -0
- package/dist/coordination/consensus/providers/claude-provider.d.ts +1 -0
- package/dist/coordination/consensus/providers/claude-provider.js +23 -3
- package/dist/domains/test-generation/generators/base-test-generator.d.ts +1 -1
- package/dist/domains/test-generation/generators/base-test-generator.js +11 -11
- package/dist/domains/test-generation/generators/go-test-generator.js +12 -12
- package/dist/domains/test-generation/generators/junit5-generator.js +9 -9
- package/dist/domains/test-generation/generators/kotlin-junit-generator.js +10 -10
- package/dist/domains/test-generation/generators/pytest-generator.js +8 -8
- package/dist/domains/test-generation/generators/swift-testing-generator.js +8 -8
- package/dist/domains/test-generation/generators/test-value-helpers.d.ts +20 -0
- package/dist/domains/test-generation/generators/test-value-helpers.js +48 -0
- package/dist/domains/test-generation/generators/xunit-generator.js +11 -11
- package/dist/hooks/cross-phase-hooks.d.ts +11 -0
- package/dist/hooks/cross-phase-hooks.js +73 -9
- package/dist/hooks/security/config-snapshot.d.ts +21 -0
- package/dist/hooks/security/config-snapshot.js +33 -0
- package/dist/hooks/security/exit-codes.d.ts +28 -0
- package/dist/hooks/security/exit-codes.js +33 -0
- package/dist/hooks/security/index.d.ts +15 -0
- package/dist/hooks/security/index.js +15 -0
- package/dist/hooks/security/ssrf-guard.d.ts +25 -0
- package/dist/hooks/security/ssrf-guard.js +69 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -2
- package/dist/init/init-wizard-hooks.js +15 -1
- package/dist/init/phases/07-hooks.js +2 -2
- package/dist/init/settings-merge.js +3 -7
- package/dist/kernel/kernel.js +35 -0
- package/dist/kernel/memory-backend.js +3 -1
- package/dist/mcp/bundle.js +416 -362
- package/dist/mcp/entry.js +132 -77
- package/dist/mcp/http-server.js +4 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +5 -4
- package/dist/mcp/middleware/batch-executor.d.ts +46 -0
- package/dist/mcp/middleware/batch-executor.js +150 -0
- package/dist/mcp/middleware/microcompact.d.ts +97 -0
- package/dist/mcp/middleware/microcompact.js +179 -0
- package/dist/mcp/middleware/middleware-chain.d.ts +37 -0
- package/dist/mcp/middleware/middleware-chain.js +60 -0
- package/dist/mcp/protocol-server.d.ts +16 -0
- package/dist/mcp/protocol-server.js +140 -36
- package/dist/mcp/services/session-durability-middleware.d.ts +22 -0
- package/dist/mcp/services/session-durability-middleware.js +64 -0
- package/dist/mcp/services/session-resume.d.ts +29 -0
- package/dist/mcp/services/session-resume.js +221 -0
- package/dist/mcp/services/session-store.d.ts +84 -0
- package/dist/mcp/services/session-store.js +163 -0
- package/dist/mcp/tool-registry.d.ts +9 -0
- package/dist/mcp/tool-registry.js +30 -1
- package/dist/mcp/types.d.ts +1 -0
- package/dist/plugins/cache.d.ts +44 -0
- package/dist/plugins/cache.js +149 -0
- package/dist/plugins/index.d.ts +15 -0
- package/dist/plugins/index.js +15 -0
- package/dist/plugins/lifecycle.d.ts +67 -0
- package/dist/plugins/lifecycle.js +175 -0
- package/dist/plugins/manifest.d.ts +45 -0
- package/dist/plugins/manifest.js +173 -0
- package/dist/plugins/resolver.d.ts +37 -0
- package/dist/plugins/resolver.js +80 -0
- package/dist/plugins/security.d.ts +23 -0
- package/dist/plugins/security.js +125 -0
- package/dist/plugins/sources/github.d.ts +17 -0
- package/dist/plugins/sources/github.js +77 -0
- package/dist/plugins/sources/local.d.ts +20 -0
- package/dist/plugins/sources/local.js +32 -0
- package/dist/plugins/sources/npm.d.ts +18 -0
- package/dist/plugins/sources/npm.js +82 -0
- package/dist/shared/llm/retry.d.ts +5 -2
- package/dist/shared/llm/retry.js +7 -3
- package/dist/shared/prompt-cache-latch.d.ts +41 -0
- package/dist/shared/prompt-cache-latch.js +63 -0
- package/dist/shared/retry-engine.d.ts +77 -0
- package/dist/shared/retry-engine.js +194 -0
- package/dist/workers/daemon.d.ts +8 -0
- package/dist/workers/daemon.js +13 -0
- package/dist/workers/quality-daemon/ci-monitor.d.ts +55 -0
- package/dist/workers/quality-daemon/ci-monitor.js +147 -0
- package/dist/workers/quality-daemon/coverage-delta.d.ts +72 -0
- package/dist/workers/quality-daemon/coverage-delta.js +135 -0
- package/dist/workers/quality-daemon/git-watcher.d.ts +51 -0
- package/dist/workers/quality-daemon/git-watcher.js +209 -0
- package/dist/workers/quality-daemon/index.d.ts +119 -0
- package/dist/workers/quality-daemon/index.js +343 -0
- package/dist/workers/quality-daemon/nightly-consolidation.d.ts +74 -0
- package/dist/workers/quality-daemon/nightly-consolidation.js +136 -0
- package/dist/workers/quality-daemon/notification-service.d.ts +67 -0
- package/dist/workers/quality-daemon/notification-service.js +178 -0
- package/dist/workers/quality-daemon/persistent-memory.d.ts +31 -0
- package/dist/workers/quality-daemon/persistent-memory.js +30 -0
- package/dist/workers/quality-daemon/priority-queue.d.ts +97 -0
- package/dist/workers/quality-daemon/priority-queue.js +126 -0
- package/dist/workers/quality-daemon/test-suggester.d.ts +50 -0
- package/dist/workers/quality-daemon/test-suggester.js +121 -0
- package/dist/workers/worker-manager.js +2 -1
- package/package.json +1 -1
- package/dist/mcp/server.d.ts +0 -46
- package/dist/mcp/server.js +0 -802
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Plugin Dependency Resolver (IMP-09)
|
|
3
|
+
*
|
|
4
|
+
* DFS dependency resolution with cycle detection.
|
|
5
|
+
* Given a set of plugin manifests, produces a topologically-sorted
|
|
6
|
+
* load order where dependencies are loaded before dependents.
|
|
7
|
+
*/
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// PluginResolver
|
|
10
|
+
// ============================================================================
|
|
11
|
+
export class PluginResolver {
|
|
12
|
+
/**
|
|
13
|
+
* Resolve plugin load order via DFS topological sort.
|
|
14
|
+
*
|
|
15
|
+
* @param manifests - All available plugin manifests
|
|
16
|
+
* @returns Ordered list of plugins safe to load sequentially
|
|
17
|
+
* @throws Error if a dependency cycle is detected
|
|
18
|
+
*/
|
|
19
|
+
resolve(manifests) {
|
|
20
|
+
const byName = new Map();
|
|
21
|
+
for (const m of manifests) {
|
|
22
|
+
byName.set(m.name, m);
|
|
23
|
+
}
|
|
24
|
+
const ordered = [];
|
|
25
|
+
const visited = new Set();
|
|
26
|
+
const visiting = new Set(); // cycle detection (gray nodes)
|
|
27
|
+
const missing = new Map();
|
|
28
|
+
const visit = (name, path) => {
|
|
29
|
+
if (visited.has(name))
|
|
30
|
+
return;
|
|
31
|
+
if (visiting.has(name)) {
|
|
32
|
+
const cycle = [...path.slice(path.indexOf(name)), name];
|
|
33
|
+
throw new Error(`Dependency cycle detected: ${cycle.join(' -> ')}`);
|
|
34
|
+
}
|
|
35
|
+
const manifest = byName.get(name);
|
|
36
|
+
if (!manifest) {
|
|
37
|
+
// Missing dependency — record it but don't fail the entire resolution
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
visiting.add(name);
|
|
41
|
+
// Visit dependencies first
|
|
42
|
+
const deps = Object.keys(manifest.dependencies ?? {});
|
|
43
|
+
const missingDeps = [];
|
|
44
|
+
for (const dep of deps) {
|
|
45
|
+
if (!byName.has(dep)) {
|
|
46
|
+
missingDeps.push(dep);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
visit(dep, [...path, name]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (missingDeps.length > 0) {
|
|
53
|
+
missing.set(name, missingDeps);
|
|
54
|
+
}
|
|
55
|
+
visiting.delete(name);
|
|
56
|
+
visited.add(name);
|
|
57
|
+
ordered.push(manifest);
|
|
58
|
+
};
|
|
59
|
+
// Visit all plugins
|
|
60
|
+
for (const m of manifests) {
|
|
61
|
+
visit(m.name, []);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
ordered: ordered.map((manifest, index) => ({ manifest, order: index })),
|
|
65
|
+
missing,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if a specific plugin can be loaded given the currently loaded set.
|
|
70
|
+
*/
|
|
71
|
+
canLoad(manifest, loaded) {
|
|
72
|
+
const deps = Object.keys(manifest.dependencies ?? {});
|
|
73
|
+
const missingDeps = deps.filter(d => !loaded.has(d));
|
|
74
|
+
return {
|
|
75
|
+
canLoad: missingDeps.length === 0,
|
|
76
|
+
missingDeps,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Plugin Security (IMP-09)
|
|
3
|
+
*
|
|
4
|
+
* Security validation for plugins:
|
|
5
|
+
* - Name impersonation prevention (reserved namespaces)
|
|
6
|
+
* - Path traversal prevention in entry points and hook handlers
|
|
7
|
+
* - Non-ASCII name blocking
|
|
8
|
+
* - Hook policy integration (leverages IMP-07 hook security)
|
|
9
|
+
*/
|
|
10
|
+
import type { QEPluginManifest } from './manifest';
|
|
11
|
+
export interface SecurityCheckResult {
|
|
12
|
+
safe: boolean;
|
|
13
|
+
violations: string[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Run all security checks on a plugin manifest.
|
|
17
|
+
*/
|
|
18
|
+
export declare function checkPluginSecurity(manifest: QEPluginManifest): SecurityCheckResult;
|
|
19
|
+
/**
|
|
20
|
+
* Validate that a plugin name is safe to use.
|
|
21
|
+
*/
|
|
22
|
+
export declare function isNameSafe(name: string): boolean;
|
|
23
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Plugin Security (IMP-09)
|
|
3
|
+
*
|
|
4
|
+
* Security validation for plugins:
|
|
5
|
+
* - Name impersonation prevention (reserved namespaces)
|
|
6
|
+
* - Path traversal prevention in entry points and hook handlers
|
|
7
|
+
* - Non-ASCII name blocking
|
|
8
|
+
* - Hook policy integration (leverages IMP-07 hook security)
|
|
9
|
+
*/
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Constants
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/** Prefixes reserved for first-party plugins */
|
|
14
|
+
const RESERVED_PREFIXES = [
|
|
15
|
+
'aqe-core-',
|
|
16
|
+
'agentic-qe-core-',
|
|
17
|
+
'agentic-qe-internal-',
|
|
18
|
+
];
|
|
19
|
+
/** Names that cannot be used (exact match) */
|
|
20
|
+
const RESERVED_NAMES = new Set([
|
|
21
|
+
'aqe',
|
|
22
|
+
'agentic-qe',
|
|
23
|
+
'ruflo',
|
|
24
|
+
'claude-flow',
|
|
25
|
+
]);
|
|
26
|
+
/** Dangerous path patterns */
|
|
27
|
+
const DANGEROUS_PATH_PATTERNS = [
|
|
28
|
+
'..', // directory traversal
|
|
29
|
+
'~', // home directory expansion
|
|
30
|
+
'/etc/', // system config
|
|
31
|
+
'/proc/', // process info
|
|
32
|
+
'/dev/', // devices
|
|
33
|
+
'node_modules/', // dependency injection
|
|
34
|
+
];
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// Plugin Security Checks
|
|
37
|
+
// ============================================================================
|
|
38
|
+
/**
|
|
39
|
+
* Run all security checks on a plugin manifest.
|
|
40
|
+
*/
|
|
41
|
+
export function checkPluginSecurity(manifest) {
|
|
42
|
+
const violations = [];
|
|
43
|
+
checkName(manifest.name, violations);
|
|
44
|
+
checkEntryPoint(manifest.entryPoint, violations);
|
|
45
|
+
checkHookPaths(manifest.hooks, violations);
|
|
46
|
+
checkPermissions(manifest.permissions, violations);
|
|
47
|
+
return {
|
|
48
|
+
safe: violations.length === 0,
|
|
49
|
+
violations,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validate that a plugin name is safe to use.
|
|
54
|
+
*/
|
|
55
|
+
export function isNameSafe(name) {
|
|
56
|
+
const violations = [];
|
|
57
|
+
checkName(name, violations);
|
|
58
|
+
return violations.length === 0;
|
|
59
|
+
}
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Internal Checks
|
|
62
|
+
// ============================================================================
|
|
63
|
+
function checkName(name, violations) {
|
|
64
|
+
// Non-ASCII check
|
|
65
|
+
// eslint-disable-next-line no-control-regex
|
|
66
|
+
if (/[^\x20-\x7E]/.test(name)) {
|
|
67
|
+
violations.push(`Plugin name "${name}" contains non-ASCII characters`);
|
|
68
|
+
}
|
|
69
|
+
// Reserved exact names
|
|
70
|
+
if (RESERVED_NAMES.has(name.toLowerCase())) {
|
|
71
|
+
violations.push(`Plugin name "${name}" is a reserved name`);
|
|
72
|
+
}
|
|
73
|
+
// Reserved prefixes
|
|
74
|
+
for (const prefix of RESERVED_PREFIXES) {
|
|
75
|
+
if (name.toLowerCase().startsWith(prefix)) {
|
|
76
|
+
violations.push(`Plugin name "${name}" uses reserved prefix "${prefix}"`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Homoglyph detection: block names that look like reserved names
|
|
80
|
+
// (simplified — checks for common substitutions)
|
|
81
|
+
const normalized = name
|
|
82
|
+
.toLowerCase()
|
|
83
|
+
.replace(/[0o]/g, 'o')
|
|
84
|
+
.replace(/[1il]/g, 'l')
|
|
85
|
+
.replace(/[-_]/g, '');
|
|
86
|
+
if (RESERVED_NAMES.has(normalized)) {
|
|
87
|
+
violations.push(`Plugin name "${name}" is visually similar to a reserved name`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function checkEntryPoint(entryPoint, violations) {
|
|
91
|
+
checkPath(entryPoint, 'entryPoint', violations);
|
|
92
|
+
// Must be relative
|
|
93
|
+
if (entryPoint.startsWith('/') || entryPoint.startsWith('\\')) {
|
|
94
|
+
violations.push('entryPoint must be a relative path, not absolute');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function checkHookPaths(hooks, violations) {
|
|
98
|
+
if (!hooks)
|
|
99
|
+
return;
|
|
100
|
+
for (const [event, handlerPath] of Object.entries(hooks)) {
|
|
101
|
+
checkPath(handlerPath, `hook[${event}]`, violations);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function checkPath(p, label, violations) {
|
|
105
|
+
for (const pattern of DANGEROUS_PATH_PATTERNS) {
|
|
106
|
+
if (p.includes(pattern)) {
|
|
107
|
+
violations.push(`${label} contains dangerous path pattern "${pattern}"`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Check for null bytes (path injection)
|
|
111
|
+
if (p.includes('\0')) {
|
|
112
|
+
violations.push(`${label} contains null byte (path injection attempt)`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function checkPermissions(permissions, violations) {
|
|
116
|
+
if (!permissions)
|
|
117
|
+
return;
|
|
118
|
+
const dangerous = ['fs:write-root', 'net:arbitrary', 'exec:shell'];
|
|
119
|
+
for (const perm of permissions) {
|
|
120
|
+
if (dangerous.includes(perm)) {
|
|
121
|
+
violations.push(`Plugin requests dangerous permission: ${perm}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - GitHub Plugin Source (IMP-09)
|
|
3
|
+
*
|
|
4
|
+
* Discovers and fetches plugins from GitHub repositories.
|
|
5
|
+
* Uses git clone over HTTPS (public repos only).
|
|
6
|
+
*/
|
|
7
|
+
import { type QEPluginManifest } from '../manifest';
|
|
8
|
+
import type { PluginSource } from './local';
|
|
9
|
+
export declare class GitHubPluginSource implements PluginSource {
|
|
10
|
+
readonly type = "github";
|
|
11
|
+
private readonly cacheDir;
|
|
12
|
+
constructor(cacheDir?: string);
|
|
13
|
+
resolve(location: string): Promise<QEPluginManifest>;
|
|
14
|
+
getPluginPath(location: string): Promise<string>;
|
|
15
|
+
private parseLocation;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - GitHub Plugin Source (IMP-09)
|
|
3
|
+
*
|
|
4
|
+
* Discovers and fetches plugins from GitHub repositories.
|
|
5
|
+
* Uses git clone over HTTPS (public repos only).
|
|
6
|
+
*/
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { execFileSync } from 'child_process';
|
|
9
|
+
import { parseManifest } from '../manifest';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Input Validation
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/** Only allow safe characters in repo owner/name and tag */
|
|
14
|
+
const SAFE_REPO_REGEX = /^[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+$/;
|
|
15
|
+
const SAFE_TAG_REGEX = /^[a-zA-Z0-9._\-/]+$/;
|
|
16
|
+
function validateRepoRef(repo, tag) {
|
|
17
|
+
if (!SAFE_REPO_REGEX.test(repo)) {
|
|
18
|
+
throw new Error(`Invalid GitHub repo "${repo}": must be owner/repo with alphanumeric, dots, hyphens, underscores only`);
|
|
19
|
+
}
|
|
20
|
+
if (tag && !SAFE_TAG_REGEX.test(tag)) {
|
|
21
|
+
throw new Error(`Invalid tag "${tag}": must be alphanumeric with dots, hyphens, underscores, slashes only`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// GitHubPluginSource
|
|
26
|
+
// ============================================================================
|
|
27
|
+
export class GitHubPluginSource {
|
|
28
|
+
type = 'github';
|
|
29
|
+
cacheDir;
|
|
30
|
+
constructor(cacheDir) {
|
|
31
|
+
this.cacheDir = cacheDir ?? path.join(process.cwd(), '.agentic-qe', 'plugins-cache');
|
|
32
|
+
}
|
|
33
|
+
async resolve(location) {
|
|
34
|
+
const pluginPath = await this.getPluginPath(location);
|
|
35
|
+
const manifestPath = path.join(pluginPath, 'qe-plugin.json');
|
|
36
|
+
const fs = await import('fs');
|
|
37
|
+
if (!fs.existsSync(manifestPath)) {
|
|
38
|
+
throw new Error(`No qe-plugin.json found in ${location}`);
|
|
39
|
+
}
|
|
40
|
+
const raw = fs.readFileSync(manifestPath, 'utf-8');
|
|
41
|
+
return parseManifest(raw);
|
|
42
|
+
}
|
|
43
|
+
async getPluginPath(location) {
|
|
44
|
+
const { repo, tag } = this.parseLocation(location);
|
|
45
|
+
// Validate inputs before using in any command
|
|
46
|
+
validateRepoRef(repo, tag);
|
|
47
|
+
const targetDir = path.join(this.cacheDir, repo.replace('/', '__'), tag || 'latest');
|
|
48
|
+
const fs = await import('fs');
|
|
49
|
+
if (fs.existsSync(targetDir)) {
|
|
50
|
+
return targetDir;
|
|
51
|
+
}
|
|
52
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
53
|
+
try {
|
|
54
|
+
const cloneUrl = `https://github.com/${repo}.git`;
|
|
55
|
+
// Use execFileSync with array args — no shell, no injection
|
|
56
|
+
const args = ['clone', '--depth', '1'];
|
|
57
|
+
if (tag) {
|
|
58
|
+
args.push('--branch', tag);
|
|
59
|
+
}
|
|
60
|
+
args.push(cloneUrl, targetDir);
|
|
61
|
+
execFileSync('git', args, { stdio: 'pipe', timeout: 60_000 });
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
65
|
+
throw new Error(`Failed to clone ${repo}: ${err instanceof Error ? err.message : String(err)}`);
|
|
66
|
+
}
|
|
67
|
+
return targetDir;
|
|
68
|
+
}
|
|
69
|
+
parseLocation(location) {
|
|
70
|
+
const [repo, tag] = location.split('@');
|
|
71
|
+
if (!repo || !repo.includes('/')) {
|
|
72
|
+
throw new Error(`Invalid GitHub location "${location}". Expected "owner/repo" or "owner/repo@tag"`);
|
|
73
|
+
}
|
|
74
|
+
return { repo, tag };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Local Plugin Source (IMP-09)
|
|
3
|
+
*
|
|
4
|
+
* Discovers and loads plugins from local filesystem directories.
|
|
5
|
+
* Expects a `qe-plugin.json` manifest file in the plugin root.
|
|
6
|
+
*/
|
|
7
|
+
import { type QEPluginManifest } from '../manifest';
|
|
8
|
+
export interface PluginSource {
|
|
9
|
+
type: string;
|
|
10
|
+
/** Resolve the plugin manifest from this source. */
|
|
11
|
+
resolve(location: string): Promise<QEPluginManifest>;
|
|
12
|
+
/** Get the absolute path to the plugin directory. */
|
|
13
|
+
getPluginPath(location: string): Promise<string>;
|
|
14
|
+
}
|
|
15
|
+
export declare class LocalPluginSource implements PluginSource {
|
|
16
|
+
readonly type = "local";
|
|
17
|
+
resolve(location: string): Promise<QEPluginManifest>;
|
|
18
|
+
getPluginPath(location: string): Promise<string>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=local.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Local Plugin Source (IMP-09)
|
|
3
|
+
*
|
|
4
|
+
* Discovers and loads plugins from local filesystem directories.
|
|
5
|
+
* Expects a `qe-plugin.json` manifest file in the plugin root.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { parseManifest } from '../manifest';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// LocalPluginSource
|
|
12
|
+
// ============================================================================
|
|
13
|
+
export class LocalPluginSource {
|
|
14
|
+
type = 'local';
|
|
15
|
+
async resolve(location) {
|
|
16
|
+
const absPath = path.resolve(location);
|
|
17
|
+
const manifestPath = path.join(absPath, 'qe-plugin.json');
|
|
18
|
+
if (!fs.existsSync(manifestPath)) {
|
|
19
|
+
throw new Error(`No qe-plugin.json found at ${manifestPath}`);
|
|
20
|
+
}
|
|
21
|
+
const raw = fs.readFileSync(manifestPath, 'utf-8');
|
|
22
|
+
return parseManifest(raw);
|
|
23
|
+
}
|
|
24
|
+
async getPluginPath(location) {
|
|
25
|
+
const absPath = path.resolve(location);
|
|
26
|
+
if (!fs.existsSync(absPath)) {
|
|
27
|
+
throw new Error(`Plugin directory does not exist: ${absPath}`);
|
|
28
|
+
}
|
|
29
|
+
return absPath;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=local.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - npm Plugin Source (IMP-09)
|
|
3
|
+
*
|
|
4
|
+
* Discovers and installs plugins from the npm registry.
|
|
5
|
+
* Uses `npm pack` + extract to get the plugin without polluting
|
|
6
|
+
* the project's node_modules.
|
|
7
|
+
*/
|
|
8
|
+
import { type QEPluginManifest } from '../manifest';
|
|
9
|
+
import type { PluginSource } from './local';
|
|
10
|
+
export declare class NpmPluginSource implements PluginSource {
|
|
11
|
+
readonly type = "npm";
|
|
12
|
+
private readonly cacheDir;
|
|
13
|
+
constructor(cacheDir?: string);
|
|
14
|
+
resolve(location: string): Promise<QEPluginManifest>;
|
|
15
|
+
getPluginPath(location: string): Promise<string>;
|
|
16
|
+
private parseLocation;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=npm.d.ts.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - npm Plugin Source (IMP-09)
|
|
3
|
+
*
|
|
4
|
+
* Discovers and installs plugins from the npm registry.
|
|
5
|
+
* Uses `npm pack` + extract to get the plugin without polluting
|
|
6
|
+
* the project's node_modules.
|
|
7
|
+
*/
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import { execFileSync } from 'child_process';
|
|
11
|
+
import { parseManifest } from '../manifest';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Input Validation
|
|
14
|
+
// ============================================================================
|
|
15
|
+
/** Only allow safe npm package name characters: alphanumeric, @, /, -, ., _ */
|
|
16
|
+
const SAFE_NPM_NAME_REGEX = /^(@[a-zA-Z0-9._-]+\/)?[a-zA-Z0-9._-]+$/;
|
|
17
|
+
const SAFE_VERSION_REGEX = /^[a-zA-Z0-9._\-+]+$/;
|
|
18
|
+
function validateNpmSpec(name, version) {
|
|
19
|
+
if (!SAFE_NPM_NAME_REGEX.test(name)) {
|
|
20
|
+
throw new Error(`Invalid npm package name "${name}": contains unsafe characters`);
|
|
21
|
+
}
|
|
22
|
+
if (version && !SAFE_VERSION_REGEX.test(version)) {
|
|
23
|
+
throw new Error(`Invalid version "${version}": contains unsafe characters`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// NpmPluginSource
|
|
28
|
+
// ============================================================================
|
|
29
|
+
export class NpmPluginSource {
|
|
30
|
+
type = 'npm';
|
|
31
|
+
cacheDir;
|
|
32
|
+
constructor(cacheDir) {
|
|
33
|
+
this.cacheDir = cacheDir ?? path.join(process.cwd(), '.agentic-qe', 'plugins-cache', 'npm');
|
|
34
|
+
}
|
|
35
|
+
async resolve(location) {
|
|
36
|
+
const pluginPath = await this.getPluginPath(location);
|
|
37
|
+
const manifestPath = path.join(pluginPath, 'qe-plugin.json');
|
|
38
|
+
if (!fs.existsSync(manifestPath)) {
|
|
39
|
+
throw new Error(`No qe-plugin.json found in npm package ${location}`);
|
|
40
|
+
}
|
|
41
|
+
const raw = fs.readFileSync(manifestPath, 'utf-8');
|
|
42
|
+
return parseManifest(raw);
|
|
43
|
+
}
|
|
44
|
+
async getPluginPath(location) {
|
|
45
|
+
const { name, version } = this.parseLocation(location);
|
|
46
|
+
// Validate inputs before using in any command
|
|
47
|
+
validateNpmSpec(name, version);
|
|
48
|
+
const safeName = name.replace(/\//g, '__');
|
|
49
|
+
const targetDir = path.join(this.cacheDir, `${safeName}@${version || 'latest'}`);
|
|
50
|
+
if (fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0) {
|
|
51
|
+
return targetDir;
|
|
52
|
+
}
|
|
53
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
54
|
+
try {
|
|
55
|
+
const spec = version ? `${name}@${version}` : name;
|
|
56
|
+
// Use execFileSync with array args — no shell, no injection
|
|
57
|
+
const tarball = execFileSync('npm', ['pack', spec, '--pack-destination', targetDir], { stdio: 'pipe', timeout: 60_000 }).toString().trim();
|
|
58
|
+
const tarPath = path.join(targetDir, tarball);
|
|
59
|
+
execFileSync('tar', ['-xzf', tarPath, '-C', targetDir, '--strip-components=1'], { stdio: 'pipe' });
|
|
60
|
+
if (fs.existsSync(tarPath)) {
|
|
61
|
+
fs.unlinkSync(tarPath);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
66
|
+
throw new Error(`Failed to fetch npm package ${location}: ${err instanceof Error ? err.message : String(err)}`);
|
|
67
|
+
}
|
|
68
|
+
return targetDir;
|
|
69
|
+
}
|
|
70
|
+
parseLocation(location) {
|
|
71
|
+
// Handle scoped packages: @scope/name@version
|
|
72
|
+
const atIndex = location.lastIndexOf('@');
|
|
73
|
+
if (atIndex > 0) {
|
|
74
|
+
return {
|
|
75
|
+
name: location.slice(0, atIndex),
|
|
76
|
+
version: location.slice(atIndex + 1) || undefined,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return { name: location };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=npm.js.map
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared retry utilities for LLM providers.
|
|
3
|
-
*
|
|
3
|
+
* IMP-03: Now delegates to the unified retry engine.
|
|
4
|
+
* Preserves the original backoffDelay() signature for backwards compatibility.
|
|
4
5
|
*/
|
|
5
6
|
/**
|
|
6
7
|
* Compute exponential backoff delay: min(base * 2^attempt, max).
|
|
7
|
-
*
|
|
8
|
+
* @deprecated Use `computeBackoff` from `../retry-engine` directly.
|
|
8
9
|
*/
|
|
9
10
|
export declare function backoffDelay(attempt: number, baseMs?: number, maxMs?: number): number;
|
|
11
|
+
export { computeBackoff, withRetry, isRetryableError } from '../retry-engine.js';
|
|
12
|
+
export type { RetryOptions, RetryResult } from '../retry-engine.js';
|
|
10
13
|
//# sourceMappingURL=retry.d.ts.map
|
package/dist/shared/llm/retry.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared retry utilities for LLM providers.
|
|
3
|
-
*
|
|
3
|
+
* IMP-03: Now delegates to the unified retry engine.
|
|
4
|
+
* Preserves the original backoffDelay() signature for backwards compatibility.
|
|
4
5
|
*/
|
|
6
|
+
import { computeBackoff } from '../retry-engine.js';
|
|
5
7
|
/** Default base delay (1 second) */
|
|
6
8
|
const DEFAULT_BASE_MS = 1000;
|
|
7
9
|
/** Default maximum delay cap (30 seconds) */
|
|
8
10
|
const DEFAULT_MAX_MS = 30000;
|
|
9
11
|
/**
|
|
10
12
|
* Compute exponential backoff delay: min(base * 2^attempt, max).
|
|
11
|
-
*
|
|
13
|
+
* @deprecated Use `computeBackoff` from `../retry-engine` directly.
|
|
12
14
|
*/
|
|
13
15
|
export function backoffDelay(attempt, baseMs = DEFAULT_BASE_MS, maxMs = DEFAULT_MAX_MS) {
|
|
14
|
-
return
|
|
16
|
+
return computeBackoff(attempt, baseMs, maxMs, 0);
|
|
15
17
|
}
|
|
18
|
+
// IMP-03: Re-export unified retry engine for incremental migration
|
|
19
|
+
export { computeBackoff, withRetry, isRetryableError } from '../retry-engine.js';
|
|
16
20
|
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Latch field manager for API header/prompt stabilization.
|
|
3
|
+
* Values are locked after first set — subsequent set() calls are no-ops
|
|
4
|
+
* unless explicitly reset(). This prevents cache-busting from
|
|
5
|
+
* incidental parameter changes between API calls.
|
|
6
|
+
*/
|
|
7
|
+
export declare class PromptCacheLatch {
|
|
8
|
+
private latched;
|
|
9
|
+
private readonly disabled;
|
|
10
|
+
/**
|
|
11
|
+
* Latch a value. If already latched, this is a no-op (original preserved).
|
|
12
|
+
* Returns true if the value was newly latched, false if already locked.
|
|
13
|
+
* When disabled via AQE_PROMPT_CACHE_LATCH=false, always stores the new value.
|
|
14
|
+
*/
|
|
15
|
+
latch(key: string, value: unknown): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Get a latched value.
|
|
18
|
+
*/
|
|
19
|
+
get<T>(key: string): T | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Check if a key is latched.
|
|
22
|
+
*/
|
|
23
|
+
has(key: string): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Explicitly unlock and remove a latched value.
|
|
26
|
+
*/
|
|
27
|
+
reset(key: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Reset all latched values (e.g., on session boundary).
|
|
30
|
+
*/
|
|
31
|
+
resetAll(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get snapshot of all latched key-value pairs.
|
|
34
|
+
*/
|
|
35
|
+
getSnapshot(): Record<string, unknown>;
|
|
36
|
+
/**
|
|
37
|
+
* Number of latched values.
|
|
38
|
+
*/
|
|
39
|
+
get size(): number;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=prompt-cache-latch.d.ts.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Latch field manager for API header/prompt stabilization.
|
|
3
|
+
* Values are locked after first set — subsequent set() calls are no-ops
|
|
4
|
+
* unless explicitly reset(). This prevents cache-busting from
|
|
5
|
+
* incidental parameter changes between API calls.
|
|
6
|
+
*/
|
|
7
|
+
export class PromptCacheLatch {
|
|
8
|
+
latched = new Map();
|
|
9
|
+
disabled = process.env.AQE_PROMPT_CACHE_LATCH === 'false';
|
|
10
|
+
/**
|
|
11
|
+
* Latch a value. If already latched, this is a no-op (original preserved).
|
|
12
|
+
* Returns true if the value was newly latched, false if already locked.
|
|
13
|
+
* When disabled via AQE_PROMPT_CACHE_LATCH=false, always stores the new value.
|
|
14
|
+
*/
|
|
15
|
+
latch(key, value) {
|
|
16
|
+
if (this.disabled) {
|
|
17
|
+
this.latched.set(key, value);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (this.latched.has(key)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
this.latched.set(key, value);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get a latched value.
|
|
28
|
+
*/
|
|
29
|
+
get(key) {
|
|
30
|
+
return this.latched.get(key);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Check if a key is latched.
|
|
34
|
+
*/
|
|
35
|
+
has(key) {
|
|
36
|
+
return this.latched.has(key);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Explicitly unlock and remove a latched value.
|
|
40
|
+
*/
|
|
41
|
+
reset(key) {
|
|
42
|
+
this.latched.delete(key);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Reset all latched values (e.g., on session boundary).
|
|
46
|
+
*/
|
|
47
|
+
resetAll() {
|
|
48
|
+
this.latched.clear();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get snapshot of all latched key-value pairs.
|
|
52
|
+
*/
|
|
53
|
+
getSnapshot() {
|
|
54
|
+
return Object.fromEntries(this.latched);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Number of latched values.
|
|
58
|
+
*/
|
|
59
|
+
get size() {
|
|
60
|
+
return this.latched.size;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=prompt-cache-latch.js.map
|