@pensar/apex 2.6.1 → 2.7.0-canary.1572d9a4
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/build/{agent-ayreaj6z.js → agent-3g1b578v.js} +6 -5
- package/build/{agent-yby11zaq.js → agent-p8cezgbb.js} +7 -6
- package/build/{agent-runs-g37vkrjr.js → agent-runs-f86emmgg.js} +23 -20
- package/build/agent-vaq31je6.js +14 -0
- package/build/agent-vvdqga09.js +14 -0
- package/build/{apps-xn6km9yn.js → apps-3stwnmen.js} +16 -13
- package/build/{auth-d105wc64.js → auth-7md9kwda.js} +16 -13
- package/build/blackboxAgent-ct8bejef.js +14 -0
- package/build/{blackboxPentest-ps78v3w7.js → blackboxPentest-w2nr4md3.js} +21 -15
- package/build/{cli-c05y640n.js → cli-1j28cbhy.js} +1 -1
- package/build/{cli-d37a42dc.js → cli-2jz2jz06.js} +206 -90
- package/build/{cli-az3xq70v.js → cli-4a8dsz2k.js} +4 -4
- package/build/{cli-qgz1q9g5.js → cli-58781vcf.js} +1192 -1473
- package/build/{cli-gx71jcke.js → cli-7067zzeb.js} +1 -1
- package/build/{cli-3sp6nd8d.js → cli-81smmd5w.js} +5 -5
- package/build/{cli-k2nwxta0.js → cli-8b25dhky.js} +2 -2
- package/build/{cli-fy6vh2a7.js → cli-8sw5zpqz.js} +1 -1
- package/build/{cli-709rvekb.js → cli-cg3ypx5n.js} +14 -7
- package/build/{cli-dpsw2fe6.js → cli-e9v6zg6h.js} +40941 -40172
- package/build/cli-fjxmphg1.js +36 -0
- package/build/{cli-7eea4e2y.js → cli-gzb6qrzh.js} +31 -60
- package/build/{cli-65g6rcat.js → cli-khnf5xrf.js} +2 -1
- package/build/{cli-1ve18npr.js → cli-mdzt2e8j.js} +4 -2
- package/build/{cli-n2en7j5b.js → cli-n8mmw4c4.js} +1 -1
- package/build/cli-pndb7mh9.js +1193 -0
- package/build/cli-px6ehzqx.js +54 -0
- package/build/{cli-xtc2t6me.js → cli-qs4msn6x.js} +111 -47
- package/build/{cli-kb21qhvm.js → cli-rvybdhgn.js} +4 -3
- package/build/{cli-ae8jqxqr.js → cli-v739h7hb.js} +2 -2
- package/build/{cli-ngq9dr8n.js → cli-wm8ech0x.js} +3 -3
- package/build/cli.js +170 -51
- package/build/{config-zpqkd5cz.js → config-e5v1bkh1.js} +1 -1
- package/build/{fastStrike-mcjdvwez.js → fastStrike-efp0rjs3.js} +74 -17
- package/build/{fixes-kytx5dmj.js → fixes-926cw1ej.js} +16 -13
- package/build/{index-n65z6v7b.js → index-3t41p258.js} +7 -6
- package/build/{index-qv4cc65p.js → index-bv09af6g.js} +19 -15
- package/build/{index-je6hcsqr.js → index-bv6dtwse.js} +1 -1
- package/build/{index-4vqdgb42.js → index-jt52ffgn.js} +1657 -1400
- package/build/{index-ns4m4s01.js → index-np405b9e.js} +11 -7
- package/build/{index-r9yjkfrv.js → index-qys178kp.js} +5 -4
- package/build/{index-wqetp6gq.js → index-tpyzq2wq.js} +42 -11
- package/build/{index-fv64eb32.js → index-vrcdyebh.js} +2 -2
- package/build/{index-dr3tg1w3.js → index-z1g8vbtm.js} +1 -1
- package/build/{issues-eb3q9d3a.js → issues-sncyqh14.js} +16 -13
- package/build/{knowledge-fqsvtx0f.js → knowledge-esgvy5ws.js} +16 -13
- package/build/lance-sacfgs1z.js +232 -0
- package/build/lib/{chunk-9yksqgzr.js → chunk-4aevegnc.js} +77 -45
- package/build/lib/{chunk-9tt2021m.js → chunk-4kf4a15q.js} +13 -13
- package/build/lib/{chunk-fy3bbbqy.js → chunk-5avnedwm.js} +7 -1
- package/build/lib/{chunk-bb0ekhkw.js → chunk-5nz5tk3p.js} +76 -22
- package/build/lib/{chunk-4hwzqthr.js → chunk-7s8e5wrd.js} +3 -2
- package/build/lib/{chunk-yrnrbjes.js → chunk-85kpxwzs.js} +4 -2
- package/build/lib/{chunk-mg03jdmt.js → chunk-9jkzk9nc.js} +1 -1
- package/build/lib/{chunk-r4j8ybn9.js → chunk-9wwts6r6.js} +824 -77
- package/build/lib/{chunk-nhfax4gb.js → chunk-bxznzxdy.js} +5 -1
- package/build/lib/{chunk-r2dkp4tb.js → chunk-cqxm95md.js} +1 -1
- package/build/lib/{chunk-w66ce82a.js → chunk-e3agqspc.js} +12 -4
- package/build/lib/{chunk-ba41jh41.js → chunk-eh5yw385.js} +1137 -333
- package/build/lib/{chunk-1azdancq.js → chunk-ewc9r84m.js} +5 -1
- package/build/lib/{chunk-2njv7wz3.js → chunk-hbyxyxdc.js} +4 -0
- package/build/lib/{chunk-e8yy2k73.js → chunk-jhhwts6w.js} +28 -2
- package/build/lib/{chunk-1jvwqnem.js → chunk-kbxbd1kn.js} +108 -44
- package/build/lib/{chunk-7pwa92rn.js → chunk-mph5fvk7.js} +1 -1
- package/build/lib/chunk-psc23epq.js +107 -0
- package/build/lib/{chunk-acgbyf5h.js → chunk-qxad7qjd.js} +4 -2
- package/build/lib/{chunk-3c00n0cy.js → chunk-r0v3vvgm.js} +54 -33
- package/build/lib/{chunk-1yct6cra.js → chunk-rt13120a.js} +1 -1
- package/build/lib/{chunk-v3dk9j7k.js → chunk-sgya016v.js} +93 -22
- package/build/lib/{chunk-1fy8azee.js → chunk-txef92hq.js} +1 -1
- package/build/lib/{chunk-2qsq76xq.js → chunk-vcd90qrn.js} +189 -90
- package/build/lib/{chunk-7gjdygcx.js → chunk-vwr9w3ab.js} +2 -0
- package/build/lib/{chunk-z137x08b.js → chunk-wf6ak0m3.js} +92 -70
- package/build/lib/{chunk-xhdpgpkm.js → chunk-xft0ms9j.js} +2 -2
- package/build/lib/core/agents/agentRuntime.d.ts +3 -1
- package/build/lib/core/agents/defineAgent.d.ts +3 -2
- package/build/lib/core/agents/lance.d.ts +153 -0
- package/build/lib/core/agents/lanceJudge.d.ts +3 -0
- package/build/lib/core/agents/offSecAgent/index.d.ts +3 -1
- package/build/lib/core/agents/offSecAgent/index.js +16 -14
- package/build/lib/core/agents/offSecAgent/offensiveSecurityAgent.d.ts +4 -0
- package/build/lib/core/agents/offSecAgent/prompt.d.ts +3 -1
- package/build/lib/core/agents/offSecAgent/subagentSpawner.d.ts +18 -2
- package/build/lib/core/agents/offSecAgent/subagentSpawner.js +10 -8
- package/build/lib/core/agents/offSecAgent/toolExecutionContext.d.ts +3 -0
- package/build/lib/core/agents/offSecAgent/toolLifecycle.d.ts +1 -0
- package/build/lib/core/agents/offSecAgent/tools/index.js +10 -6
- package/build/lib/core/agents/offSecAgent/tools/listMemories.d.ts +11 -1
- package/build/lib/core/agents/offSecAgent/tools/reportError.d.ts +2 -1
- package/build/lib/core/agents/offSecAgent/tools/runPentestWorkflow.d.ts +20 -1
- package/build/lib/core/agents/offSecAgent/tools/spawnPentestAgent.d.ts +4 -7
- package/build/lib/core/agents/offSecAgent/tools/spawnPentestSwarm.d.ts +7 -1
- package/build/lib/core/agents/offSecAgent/tools/types.d.ts +6 -3
- package/build/lib/core/agents/offSecAgent/tools/whiteboxCandidates.d.ts +2 -2
- package/build/lib/core/agents/offSecAgent/types.d.ts +19 -3
- package/build/lib/core/agents/specialized/attackSurface/blackboxAgent.js +13 -13
- package/build/lib/core/agents/specialized/attackSurface/schemas.js +12 -12
- package/build/lib/core/agents/specialized/authenticationAgent/index.js +14 -14
- package/build/lib/core/agents/specialized/codeAgent/agent.js +13 -13
- package/build/lib/core/agents/specialized/codeAgent/prompts.d.ts +1 -0
- package/build/lib/core/agents/specialized/cvssScorer/index.d.ts +2 -1
- package/build/lib/core/agents/specialized/findingJudge/agent.js +11 -11
- package/build/lib/core/agents/specialized/findingJudge/index.d.ts +2 -1
- package/build/lib/core/agents/specialized/findingJudge/index.js +4 -4
- package/build/lib/core/agents/specialized/patching/index.js +14 -14
- package/build/lib/core/agents/specialized/pentest/agent.d.ts +18 -4
- package/build/lib/core/agents/specialized/pentest/agent.js +15 -13
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.d.ts +2 -1
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/index.js +13 -13
- package/build/lib/core/ai/ai.d.ts +29 -70
- package/build/lib/core/ai/ai.js +5 -3
- package/build/lib/core/ai/index.d.ts +1 -0
- package/build/lib/core/ai/index.js +16 -4
- package/build/lib/core/ai/models/claude-capabilities.d.ts +3 -2
- package/build/lib/core/ai/models/concentrate.d.ts +1 -0
- package/build/lib/core/ai/models/index.d.ts +1 -1
- package/build/lib/core/ai/providers/concentrate.d.ts +1 -0
- package/build/lib/core/ai/reasoning.d.ts +44 -0
- package/build/lib/core/ai/utils.d.ts +2 -0
- package/build/lib/core/ai/utils.js +5 -3
- package/build/lib/core/api/index.d.ts +6 -0
- package/build/lib/core/api/index.js +32 -23
- package/build/lib/core/api/lance.d.ts +6 -0
- package/build/lib/core/api/offesecAgent.d.ts +1 -0
- package/build/lib/core/api/reasoning.d.ts +12 -0
- package/build/lib/core/api/targetedPentest.d.ts +1 -0
- package/build/lib/core/api/targetedPentest.js +14 -14
- package/build/lib/core/cli/reasoning.d.ts +4 -0
- package/build/lib/core/config/config.d.ts +10 -2
- package/build/lib/core/config/customProviders.d.ts +11 -0
- package/build/lib/core/config/index.js +1 -1
- package/build/lib/core/eventBus.js +1 -1
- package/build/lib/core/findings/registry.d.ts +3 -1
- package/build/lib/core/findings/registry.js +4 -4
- package/build/lib/core/observability/index.js +1 -1
- package/build/lib/core/observability/telemetry.d.ts +4 -0
- package/build/lib/core/session/index.d.ts +47 -0
- package/build/lib/core/session/index.js +6 -4
- package/build/lib/core/session/persistence.d.ts +7 -0
- package/build/lib/core/session/persistence.js +8 -4
- package/build/lib/core/tools/backends/index.js +1 -1
- package/build/lib/core/tools/backends/resolve.d.ts +1 -0
- package/build/lib/core/workflows/fastStrike.d.ts +3 -1
- package/build/lib/core/workflows/pentest.d.ts +12 -2
- package/build/lib/core/workflows/pentest.js +19 -19
- package/build/lib/core/workflows/seams.js +5 -5
- package/build/lib/core/workflows/threatModel.d.ts +1 -0
- package/build/lib/core/workflows/whiteboxAttackSurface.d.ts +6 -4
- package/build/lib/core/workflows/whiteboxAttackSurface.js +15 -15
- package/build/lib/index.js +25 -25
- package/build/{logs-x62b7hk1.js → logs-bcbjpjp6.js} +16 -13
- package/build/{native-rollout-evidence-c9yhfqcs.js → native-rollout-evidence-rph1774m.js} +5 -5
- package/build/offesecAgent-81h1p6ee.js +32 -0
- package/build/pentest-2q20q6n1.js +23 -0
- package/build/{pentests-e0f32aqx.js → pentests-jgw031mc.js} +16 -13
- package/build/recordedRunClient-6axj6fba.js +11 -0
- package/build/subagentSpawner-a861gvt0.js +12 -0
- package/build/targetedPentest-6yxznt7s.js +91 -0
- package/build/{targets-xj9g3q0z.js → targets-bjah19dp.js} +16 -13
- package/build/threatModel-739kpexm.js +24 -0
- package/build/{uninstall-7s784q4a.js → uninstall-yxrn9edt.js} +1 -1
- package/build/{upload-4gvhwmvr.js → upload-34ewrjp5.js} +4 -4
- package/build/{utils-cjrz64pc.js → utils-fzm66efw.js} +5 -5
- package/package.json +2 -1
- package/src/cli/issues.test.ts +17 -1
- package/src/cli/lance-verifier.test.ts +57 -0
- package/src/cli/lance-verifier.ts +73 -0
- package/src/cli/lance.test.ts +71 -0
- package/src/cli/lance.ts +48 -0
- package/src/cli.ts +109 -19
- package/src/core/agents/agentRuntime.test.ts +42 -0
- package/src/core/agents/agentRuntime.ts +7 -2
- package/src/core/agents/defineAgent.ts +3 -1
- package/src/core/agents/lance.test.ts +421 -0
- package/src/core/agents/lance.ts +701 -0
- package/src/core/agents/lanceJudge.test.ts +166 -0
- package/src/core/agents/lanceJudge.ts +115 -0
- package/src/core/agents/offSecAgent/index.ts +3 -0
- package/src/core/agents/offSecAgent/interruptedStepFinalization.test.ts +51 -0
- package/src/core/agents/offSecAgent/lance.test.ts +188 -0
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.test.ts +92 -5
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.ts +244 -41
- package/src/core/agents/offSecAgent/prompt.test.ts +46 -0
- package/src/core/agents/offSecAgent/prompt.ts +52 -8
- package/src/core/agents/offSecAgent/selectiveConstruction.publicPath.test.ts +38 -0
- package/src/core/agents/offSecAgent/selectiveConstruction.test.ts +64 -0
- package/src/core/agents/offSecAgent/subagentSpawner.hooks.test.ts +11 -3
- package/src/core/agents/offSecAgent/subagentSpawner.reasoning.test.ts +167 -0
- package/src/core/agents/offSecAgent/subagentSpawner.ts +82 -28
- package/src/core/agents/offSecAgent/toolExecutionContext.test.ts +230 -0
- package/src/core/agents/offSecAgent/toolExecutionContext.ts +56 -0
- package/src/core/agents/offSecAgent/toolLifecycle.ts +2 -0
- package/src/core/agents/offSecAgent/tools/delegateAuth.ts +4 -2
- package/src/core/agents/offSecAgent/tools/documentFinding.test.ts +9 -4
- package/src/core/agents/offSecAgent/tools/documentFinding.ts +10 -9
- package/src/core/agents/offSecAgent/tools/listMemories.test.ts +230 -0
- package/src/core/agents/offSecAgent/tools/listMemories.ts +73 -6
- package/src/core/agents/offSecAgent/tools/reportError.test.ts +6 -0
- package/src/core/agents/offSecAgent/tools/reportError.ts +10 -2
- package/src/core/agents/offSecAgent/tools/runAttackSurface.ts +7 -4
- package/src/core/agents/offSecAgent/tools/runPentestWorkflow.test.ts +57 -0
- package/src/core/agents/offSecAgent/tools/runPentestWorkflow.ts +21 -1
- package/src/core/agents/offSecAgent/tools/runWhiteboxScan.ts +5 -2
- package/src/core/agents/offSecAgent/tools/spawnCodingAgent.ts +50 -67
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.test.ts +79 -3
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.ts +36 -16
- package/src/core/agents/offSecAgent/tools/spawnPentestSwarm.ts +28 -5
- package/src/core/agents/offSecAgent/tools/threatModelGenerator.ts +4 -3
- package/src/core/agents/offSecAgent/tools/types.ts +12 -2
- package/src/core/agents/offSecAgent/tools/updateTask.ts +5 -1
- package/src/core/agents/offSecAgent/tools/whiteboxCandidates.ts +11 -4
- package/src/core/agents/offSecAgent/types.ts +22 -1
- package/src/core/agents/specialized/codeAgent/agent.test.ts +7 -0
- package/src/core/agents/specialized/codeAgent/agent.ts +9 -2
- package/src/core/agents/specialized/codeAgent/prompts.ts +6 -0
- package/src/core/agents/specialized/cvssScorer/index.test.ts +2 -1
- package/src/core/agents/specialized/cvssScorer/index.ts +3 -0
- package/src/core/agents/specialized/findingJudge/index.ts +6 -0
- package/src/core/agents/specialized/pentest/agent.test.ts +155 -0
- package/src/core/agents/specialized/pentest/agent.ts +181 -52
- package/src/core/agents/specialized/pentest/results.test.ts +59 -4
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.concurrency.test.ts +59 -2
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.hooks.test.ts +127 -0
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.ts +74 -68
- package/src/core/ai/ai.durability-hooks.test.ts +25 -7
- package/src/core/ai/ai.lance.test.ts +581 -0
- package/src/core/ai/ai.operator-context.bench.test.ts +1390 -0
- package/src/core/ai/ai.recorded-context.test.ts +89 -8
- package/src/core/ai/ai.test.ts +81 -59
- package/src/core/ai/ai.ts +453 -327
- package/src/core/ai/compactionTelemetry.test.ts +69 -17
- package/src/core/ai/index.ts +11 -0
- package/src/core/ai/models/anthropic.ts +6 -0
- package/src/core/ai/models/bedrock.ts +18 -0
- package/src/core/ai/models/claude-capabilities.ts +29 -8
- package/src/core/ai/models/concentrate.ts +52 -0
- package/src/core/ai/models/index.ts +25 -4
- package/src/core/ai/models/models.test.ts +179 -7
- package/src/core/ai/models/openrouter-reasoning.json +219 -0
- package/src/core/ai/models/openrouter.ts +43 -1
- package/src/core/ai/providers/anthropic-models.test.ts +60 -1
- package/src/core/ai/providers/bedrock-models.test.ts +81 -0
- package/src/core/ai/providers/concentrate.test.ts +31 -0
- package/src/core/ai/providers/concentrate.ts +11 -0
- package/src/core/ai/providers/custom.test.ts +74 -0
- package/src/core/ai/providers/custom.ts +3 -1
- package/src/core/ai/providers/gateway-models.test.ts +16 -6
- package/src/core/ai/providers/pensarFormatters.ts +8 -1
- package/src/core/ai/reasoning.test.ts +313 -0
- package/src/core/ai/reasoning.ts +500 -0
- package/src/core/ai/streamIdleTimeout.test.ts +21 -0
- package/src/core/ai/utils.native-rollout-evidence.test.ts +21 -8
- package/src/core/ai/utils.ts +269 -163
- package/src/core/api/attackSurface.ts +1 -0
- package/src/core/api/blackboxPentest.ts +9 -1
- package/src/core/api/index.ts +17 -0
- package/src/core/api/lance.ts +23 -0
- package/src/core/api/offesecAgent.test.ts +51 -0
- package/src/core/api/offesecAgent.ts +15 -1
- package/src/core/api/reasoning.test.ts +213 -0
- package/src/core/api/reasoning.ts +44 -0
- package/src/core/api/recordedRun.loop.test.ts +5 -1
- package/src/core/api/targetedPentest.test.ts +14 -2
- package/src/core/api/targetedPentest.ts +52 -5
- package/src/core/cli/reasoning.test.ts +149 -0
- package/src/core/cli/reasoning.ts +95 -0
- package/src/core/config/config.test.ts +35 -0
- package/src/core/config/config.ts +11 -0
- package/src/core/config/customProviders.ts +21 -2
- package/src/core/eventBus.ts +1 -0
- package/src/core/findings/registry.test.ts +9 -1
- package/src/core/findings/registry.ts +6 -0
- package/src/core/observability/telemetry.test.ts +131 -79
- package/src/core/observability/telemetry.ts +5 -0
- package/src/core/runtime/sqliteRunObservation.test.ts +1 -1
- package/src/core/session/index.ts +38 -0
- package/src/core/session/persistence.test.ts +62 -0
- package/src/core/session/persistence.ts +56 -0
- package/src/core/tools/backends/resolve.ts +7 -0
- package/src/core/tools/backends/whiteboxJobs.test.ts +9 -8
- package/src/core/workflows/fastStrike.seams.test.ts +149 -0
- package/src/core/workflows/fastStrike.test.ts +18 -1
- package/src/core/workflows/fastStrike.ts +106 -11
- package/src/core/workflows/pentest.test.ts +104 -0
- package/src/core/workflows/pentest.ts +128 -7
- package/src/core/workflows/seams.test.ts +13 -0
- package/src/core/workflows/seams.ts +5 -1
- package/src/core/workflows/threatModel.ts +2 -0
- package/src/core/workflows/whiteboxAttackSurface.test.ts +74 -2
- package/src/core/workflows/whiteboxAttackSurface.ts +102 -73
- package/src/tui/command-registry.test.ts +12 -0
- package/src/tui/command-registry.ts +10 -0
- package/src/tui/components/chat/config-view.tsx +6 -10
- package/src/tui/components/chat/home-view.tsx +2 -2
- package/src/tui/components/chat/input-area.tsx +2 -2
- package/src/tui/components/chat/loading-indicator.tsx +20 -4
- package/src/tui/components/chat/message-list.tsx +1 -0
- package/src/tui/components/commands/__tests__/advanced-settings-lifecycle.tsx +164 -0
- package/src/tui/components/commands/advanced-settings.test.ts +34 -0
- package/src/tui/components/commands/advanced-settings.tsx +220 -31
- package/src/tui/components/commands/models-display.tsx +7 -1
- package/src/tui/components/model-picker/ModelPicker.tsx +65 -103
- package/src/tui/components/model-picker/ModelPickerDialog.tsx +8 -14
- package/src/tui/components/model-picker/__tests__/reasoning-control.tsx +162 -0
- package/src/tui/components/model-picker/reasoning-control.test.ts +15 -0
- package/src/tui/components/operator-dashboard/index.tsx +166 -50
- package/src/tui/components/operator-dashboard/logic.test.ts +144 -2
- package/src/tui/components/operator-dashboard/logic.ts +54 -3
- package/src/tui/components/operator-dashboard/run-events.test.ts +3 -1
- package/src/tui/components/shared/__tests__/tool-renderer-lifecycle.tsx +18 -0
- package/src/tui/components/shared/action-label.test.ts +9 -0
- package/src/tui/components/shared/compacting-icon.tsx +18 -0
- package/src/tui/components/shared/index.ts +1 -0
- package/src/tui/components/shared/tool-registry.ts +1 -0
- package/src/tui/components/shared/tool-renderer.tsx +21 -7
- package/src/tui/context/agent.tsx +32 -79
- package/src/tui/context/route.tsx +2 -0
- package/src/tui/index.tsx +1 -0
- package/src/tui/keybindings/registry.ts +2 -0
- package/build/agent-6w7egcf1.js +0 -13
- package/build/agent-9zx75feh.js +0 -13
- package/build/blackboxAgent-s56sgx9b.js +0 -13
- package/build/cli-g06s7edq.js +0 -11
- package/build/lib/chunk-z96pbjhd.js +0 -56
- package/build/offesecAgent-5whnpeta.js +0 -22
- package/build/pentest-e61hc38s.js +0 -22
- package/build/recordedRunClient-dp032c32.js +0 -11
- package/build/targetedPentest-rcbs4nvp.js +0 -57
- package/build/threatModel-jkxfa40s.js +0 -21
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import type { FindingPolicy } from "./types";
|
|
3
4
|
|
|
4
5
|
interface SessionPaths {
|
|
5
6
|
rootPath: string;
|
|
@@ -77,6 +78,7 @@ export function buildSessionWorkspaceSection(
|
|
|
77
78
|
agentCwd: string,
|
|
78
79
|
activeTools?: readonly string[],
|
|
79
80
|
fileWorkspaceRoot?: string,
|
|
81
|
+
findingPolicy: FindingPolicy = "native",
|
|
80
82
|
): string {
|
|
81
83
|
const sandboxMode = agentCwd === session.rootPath;
|
|
82
84
|
const providedFilesSection = buildProvidedFilesSection(
|
|
@@ -87,9 +89,14 @@ export function buildSessionWorkspaceSection(
|
|
|
87
89
|
session,
|
|
88
90
|
agentCwd,
|
|
89
91
|
{ sandboxMode, activeTools, fileWorkspaceRoot },
|
|
92
|
+
findingPolicy,
|
|
90
93
|
);
|
|
91
94
|
|
|
92
95
|
if (fileWorkspaceRoot) {
|
|
96
|
+
const artifactsGuidance =
|
|
97
|
+
findingPolicy === "external"
|
|
98
|
+
? `Session artifacts live at ${session.rootPath}. Follow the caller's output contract for findings; browser tools save their own evidence.`
|
|
99
|
+
: `Session artifacts live at ${session.rootPath}. Findings and published PoCs are written by \`document_vulnerability\`, and browser tools save their own evidence.`;
|
|
93
100
|
return `
|
|
94
101
|
|
|
95
102
|
# Working Directory and File Workspace
|
|
@@ -98,10 +105,17 @@ Your shell starts in ${agentCwd}. Native file tools are confined to ${fileWorksp
|
|
|
98
105
|
|
|
99
106
|
Create and edit helper scripts inside the file workspace. Use absolute helper paths with \`execute_command\` to check and run them. Do not prefix native file-tool paths with \`scratchpad/\` or \`provided_files/\` to reach session directories outside the file workspace.
|
|
100
107
|
|
|
101
|
-
|
|
108
|
+
${artifactsGuidance} Session logs and provided files outside the file workspace must be inspected through command tools or copied into the file workspace before native file tools can read them.${providedFilesSection}${sourceAssessmentSection}`;
|
|
102
109
|
}
|
|
103
110
|
|
|
104
111
|
if (sandboxMode) {
|
|
112
|
+
if (findingPolicy === "external") {
|
|
113
|
+
return `
|
|
114
|
+
|
|
115
|
+
# Session Workspace
|
|
116
|
+
|
|
117
|
+
Your shell is already set to the session directory. Use relative paths for session files. The session provides scratchpad/ for temporary work, logs/ for execution logs, evidence/ for browser evidence, and provided_files/ for supplied inputs. Follow the caller's output contract for findings.${providedFilesSection}${sourceAssessmentSection}`;
|
|
118
|
+
}
|
|
105
119
|
return `
|
|
106
120
|
|
|
107
121
|
# Session Workspace
|
|
@@ -119,6 +133,15 @@ The session directory (${session.rootPath}) contains these subdirectories:
|
|
|
119
133
|
Tools like \`document_vulnerability\` and browser evidence capture write to the correct subdirectories automatically.${providedFilesSection}${sourceAssessmentSection}`;
|
|
120
134
|
}
|
|
121
135
|
|
|
136
|
+
if (findingPolicy === "external") {
|
|
137
|
+
return `
|
|
138
|
+
|
|
139
|
+
# Working Directory
|
|
140
|
+
|
|
141
|
+
Your shell starts in the user's project directory: ${agentCwd}
|
|
142
|
+
Use relative paths to reference project files. Session artifacts are stored at ${session.rootPath}; use scratchpad/ for temporary work, logs/ for execution logs, and evidence/ for browser evidence. Follow the caller's output contract for findings.${providedFilesSection}${sourceAssessmentSection}`;
|
|
143
|
+
}
|
|
144
|
+
|
|
122
145
|
return `
|
|
123
146
|
|
|
124
147
|
# Working Directory
|
|
@@ -168,6 +191,7 @@ function buildSourceAssessmentSection(
|
|
|
168
191
|
activeTools?: readonly string[];
|
|
169
192
|
fileWorkspaceRoot?: string;
|
|
170
193
|
},
|
|
194
|
+
findingPolicy: FindingPolicy,
|
|
171
195
|
): string {
|
|
172
196
|
const codebasePath = session.config?.codebasePath;
|
|
173
197
|
// A helper workspace does not make the shell's cwd an authorized target
|
|
@@ -214,7 +238,8 @@ function buildSourceAssessmentSection(
|
|
|
214
238
|
"- Use `spawn_coding_agent` for independent deep dives.",
|
|
215
239
|
hasTool("create_whitebox_candidate") &&
|
|
216
240
|
"- Track unverified hypotheses with `create_whitebox_candidate`.",
|
|
217
|
-
|
|
241
|
+
findingPolicy !== "external" &&
|
|
242
|
+
hasTool("document_vulnerability") &&
|
|
218
243
|
"- Only call `document_vulnerability` after a PoC, crash reproducer, or dynamic check confirms exploitability.",
|
|
219
244
|
hasTool("start_whitebox_job") &&
|
|
220
245
|
hasTool("poll_whitebox_job") &&
|
|
@@ -238,12 +263,32 @@ ${toolGuidance}${repoEditBullet}`;
|
|
|
238
263
|
export interface BaseSystemPromptOptions {
|
|
239
264
|
/** When true, include the "Stay in the session folder" instruction. Defaults to true. */
|
|
240
265
|
sandboxMode?: boolean;
|
|
266
|
+
findingPolicy?: FindingPolicy;
|
|
241
267
|
}
|
|
242
268
|
|
|
243
269
|
export function buildBaseSystemPrompt(
|
|
244
270
|
options?: BaseSystemPromptOptions,
|
|
245
271
|
): string {
|
|
246
272
|
const sandboxMode = options?.sandboxMode ?? true;
|
|
273
|
+
const externalFindings = options?.findingPolicy === "external";
|
|
274
|
+
|
|
275
|
+
const exploitationCapability = externalFindings
|
|
276
|
+
? "- **Exploitation and proof development** — use the available tools only as far as the assigned objective requires"
|
|
277
|
+
: "- **Exploitation & proof-of-concept development** — provide PoC scripts inline to document_vulnerability which executes and validates them";
|
|
278
|
+
const reportingCapability = externalFindings
|
|
279
|
+
? "- **Reporting** — submit concise findings through the caller's requested output contract; the caller grades them after the run"
|
|
280
|
+
: "- **Reporting** — document confirmed findings with evidence, impact, and remediation";
|
|
281
|
+
const findingToolReference = externalFindings
|
|
282
|
+
? `## Findings
|
|
283
|
+
- Use the caller's requested output format for any discovered vulnerabilities. Include the affected surface, observed behavior, and likely security impact.`
|
|
284
|
+
: `## Findings & PoCs
|
|
285
|
+
- **document_vulnerability** — Create, execute, and validate a proof-of-concept script, then document the confirmed vulnerability with CVSS 4.0 scoring. Provide your POC script inline via pocContent. The tool handles execution, validation, scoring, and persistence.`;
|
|
286
|
+
const findingWorkRule = externalFindings
|
|
287
|
+
? "6. **Report findings through the requested output.** Focus on discovering vulnerabilities and gathering the evidence required by the user's task. Do not spend time on a separate in-run finding review."
|
|
288
|
+
: "6. **Document security work as you go.** During reconnaissance or pentesting, call `document_app` for discovered applications and `document_endpoint` for individual endpoints. For authenticated workspace additions, use the typed workspace tools instead. Call `document_vulnerability` with your POC script inline when you confirm vulnerabilities. Don't defer documentation to the end.";
|
|
289
|
+
const reportRule = externalFindings
|
|
290
|
+
? "5. **Follow the caller's output contract.** Keep intermediate files in scratchpad/ and submit final finding artifacts only where the caller requested."
|
|
291
|
+
: "5. **No reports in scratchpad.** Do NOT write synthesized report documents to scratchpad/ (e.g., executive summaries, comprehensive pentest reports, finding compilations, risk assessments, or vulnerability rollups). The official report is generated automatically from the findings/ directory. Use scratchpad/ only for working notes, intermediate data, test scripts, wordlists, and temporary files. Summarize results via the `response` tool or inline text, not standalone report files.";
|
|
247
292
|
|
|
248
293
|
const stayInSessionParagraph = sandboxMode
|
|
249
294
|
? `\n\n**Stay in the session folder.** Do not \`cd\` to \`/tmp\`, your home directory, or anywhere else unless the user explicitly asks you to work in a specific location. Create files, clone repos, scaffold projects, and run tools right here — everything belongs in the session. Use relative paths (e.g. \`scratchpad/notes.txt\`, \`test-app/\`) rather than absolute paths to external directories.`
|
|
@@ -258,9 +303,9 @@ You work interactively with the user. Execute the task they ask for, report your
|
|
|
258
303
|
You can perform the full lifecycle of a penetration test and support a wide range of cybersecurity tasks:
|
|
259
304
|
- **Reconnaissance & attack surface mapping** — subdomain enumeration, endpoint discovery, JS analysis, authenticated crawling
|
|
260
305
|
- **Vulnerability testing** — injection flaws, auth bypasses, access control issues, misconfigurations, business logic flaws
|
|
261
|
-
|
|
306
|
+
${exploitationCapability}
|
|
262
307
|
- **Source code analysis** — read and search codebases for security-relevant patterns, misconfigurations, and vulnerabilities
|
|
263
|
-
|
|
308
|
+
${reportingCapability}
|
|
264
309
|
|
|
265
310
|
# Tool Reference
|
|
266
311
|
|
|
@@ -311,8 +356,7 @@ You can perform the full lifecycle of a penetration test and support a wide rang
|
|
|
311
356
|
|
|
312
357
|
These tools use the authenticated API client in the running Apex process. Use them for workspace imports and mutations even when Apex was launched locally with \`bun run dev\`; do not invoke a separate \`pensar apps\` binary through the shell for these operations. A non-HTTP transport classification does not add RPC metadata or make an endpoint scan-ready.
|
|
313
358
|
|
|
314
|
-
|
|
315
|
-
- **document_vulnerability** — Create, execute, and validate a proof-of-concept script, then document the confirmed vulnerability with CVSS 4.0 scoring. Provide your POC script inline via pocContent. The tool handles execution, validation, scoring, and persistence.
|
|
359
|
+
${findingToolReference}
|
|
316
360
|
|
|
317
361
|
## Orchestration
|
|
318
362
|
- **run_attack_surface** — Launch a full attack surface discovery workflow. Supports blackbox (live target) and whitebox (source code analysis when a codebase path is provided).
|
|
@@ -340,7 +384,7 @@ Run \`pensar --help\` or \`pensar <command> --help\` for exact flags — the CLI
|
|
|
340
384
|
3. **Be thorough within the ask.** When given a task, see it through completely. Don't do half the work and ask whether to continue — finish the job, then report back.
|
|
341
385
|
4. **Use the right level of automation.** For large tasks (e.g., "pentest this entire application"), use orchestration tools like \`run_attack_surface\` and \`spawn_pentest_swarm\` to parallelize the work. For focused tasks (e.g., "check if this parameter is vulnerable to XSS"), work directly with \`http_request\`, \`execute_command\`, or the browser tools.
|
|
342
386
|
5. **Authenticate when needed.** If the user provides credentials or auth instructions, use them. Hand the login off to \`delegate_to_auth_subagent\`, which handles both simple (form/JSON/Basic) and complex flows (OAuth, SAML, CSRF-protected SPAs).
|
|
343
|
-
|
|
387
|
+
${findingWorkRule}
|
|
344
388
|
7. **Consult memories first.** When you begin testing a specific application, framework, or path, call \`list_memories\` to check for saved knowledge from previous sessions — past findings, useful payloads, endpoint patterns, or target-specific notes. Use relevant memories to inform your approach before starting from scratch.
|
|
345
389
|
|
|
346
390
|
# Command Execution
|
|
@@ -358,7 +402,7 @@ For long-running services (servers, listeners, watchers), background them with *
|
|
|
358
402
|
2. **Stay in scope.** Only test targets and systems explicitly provided by the user or discovered within the authorized scope. Respect any scope constraints in the session config.
|
|
359
403
|
3. **Handle failures gracefully.** If a tool call fails or a technique doesn't work, try alternative approaches. If your PoC approach fails repeatedly, pivot to a different technique.
|
|
360
404
|
4. **Summarize results.** After completing a task, give the user a clear summary of what you found, what you tried, and what the next steps could be.
|
|
361
|
-
|
|
405
|
+
${reportRule}`;
|
|
362
406
|
}
|
|
363
407
|
|
|
364
408
|
/**
|
|
@@ -201,6 +201,20 @@ describe("OffensiveSecurityAgent public-path construction counts", () => {
|
|
|
201
201
|
});
|
|
202
202
|
});
|
|
203
203
|
|
|
204
|
+
it("external Fast Strike never constructs the native finding tool", async () => {
|
|
205
|
+
await withRoot(async (root) => {
|
|
206
|
+
reset();
|
|
207
|
+
observed.armed = true;
|
|
208
|
+
makeAgent(root, [], { mode: "fast-strike", findingPolicy: "external" });
|
|
209
|
+
observed.armed = false;
|
|
210
|
+
expect(observed.constructed).toBe(42);
|
|
211
|
+
expect(stream().tools).not.toHaveProperty("document_vulnerability");
|
|
212
|
+
expect(stream().tools).toHaveProperty("execute_command");
|
|
213
|
+
expect(stream().tools).toHaveProperty("http_request");
|
|
214
|
+
expect(stream().tools).toHaveProperty("read_file");
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
204
218
|
it("selected seven plus five available conditional tools construct twelve", async () => {
|
|
205
219
|
await withRoot(async (root) => {
|
|
206
220
|
reset();
|
|
@@ -237,6 +251,30 @@ describe("OffensiveSecurityAgent public-path construction counts", () => {
|
|
|
237
251
|
});
|
|
238
252
|
|
|
239
253
|
describe("response injection on the real path", () => {
|
|
254
|
+
it("passes only the executed response tool's validated result to the resolver", async () => {
|
|
255
|
+
await withRoot(async (root) => {
|
|
256
|
+
reset();
|
|
257
|
+
const resolved = vi.fn(
|
|
258
|
+
(_streamResult: unknown, result: unknown) => result,
|
|
259
|
+
);
|
|
260
|
+
const agent = makeAgent(root, ["response"], {
|
|
261
|
+
responseSchema: z.object({ reportedFindings: z.array(z.string()) }),
|
|
262
|
+
resolveResult: resolved,
|
|
263
|
+
});
|
|
264
|
+
const response = stream().tools.response as {
|
|
265
|
+
execute: (input: unknown, options: unknown) => Promise<unknown>;
|
|
266
|
+
};
|
|
267
|
+
const finding = { reportedFindings: ["Observed cross-tenant access"] };
|
|
268
|
+
await response.execute(
|
|
269
|
+
{ result: finding },
|
|
270
|
+
{ toolCallId: "tc_response", messages: [] },
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
await expect(agent.responseCaptured).resolves.toEqual(finding);
|
|
274
|
+
expect(resolved).toHaveBeenCalledWith(expect.anything(), finding);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
240
278
|
it("fast-strike + responseSchema + non-enumerable own response extra still activates the injected response", async () => {
|
|
241
279
|
await withRoot(async (root) => {
|
|
242
280
|
reset();
|
|
@@ -289,6 +289,70 @@ describe("agent-level selective construction", () => {
|
|
|
289
289
|
expect(Object.keys(streamTools())).toContain("custom_extra");
|
|
290
290
|
});
|
|
291
291
|
|
|
292
|
+
it("external grading removes the finding tool before default-mode construction and extra-tool merge", () => {
|
|
293
|
+
const m = marker();
|
|
294
|
+
makeAgent(
|
|
295
|
+
baseInput({
|
|
296
|
+
findingPolicy: "external",
|
|
297
|
+
activeTools: [
|
|
298
|
+
"document_vulnerability",
|
|
299
|
+
"execute_command",
|
|
300
|
+
"http_request",
|
|
301
|
+
"spawn_pentest_agent",
|
|
302
|
+
],
|
|
303
|
+
extraTools: {
|
|
304
|
+
document_vulnerability: {
|
|
305
|
+
description: "caller override",
|
|
306
|
+
inputSchema: {},
|
|
307
|
+
execute: async () => "should not run",
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
}) as never,
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
expect(constructedSince(m)).toEqual([
|
|
314
|
+
"execute_command",
|
|
315
|
+
"http_request",
|
|
316
|
+
"spawn_pentest_agent",
|
|
317
|
+
]);
|
|
318
|
+
expect(streamTools()).not.toHaveProperty("document_vulnerability");
|
|
319
|
+
expect(streamTools()).toHaveProperty("spawn_pentest_agent");
|
|
320
|
+
expect(state.toolContexts.at(-1)).toMatchObject({
|
|
321
|
+
findingPolicy: "external",
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it("external Fast Strike retains discovery tools while excluding the finding tool", () => {
|
|
326
|
+
const m = marker();
|
|
327
|
+
makeAgent(
|
|
328
|
+
baseInput({
|
|
329
|
+
mode: "fast-strike",
|
|
330
|
+
findingPolicy: "external",
|
|
331
|
+
activeTools: [],
|
|
332
|
+
responseSchema: { parse: () => {} },
|
|
333
|
+
extraTools: {
|
|
334
|
+
document_vulnerability: {
|
|
335
|
+
description: "caller override",
|
|
336
|
+
inputSchema: {},
|
|
337
|
+
execute: async () => "should not run",
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
}) as never,
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
expect(constructedSince(m)).not.toContain("document_vulnerability");
|
|
344
|
+
expect(streamTools()).not.toHaveProperty("document_vulnerability");
|
|
345
|
+
for (const name of [
|
|
346
|
+
"browser_navigate",
|
|
347
|
+
"http_request",
|
|
348
|
+
"execute_command",
|
|
349
|
+
"read_file",
|
|
350
|
+
"response",
|
|
351
|
+
]) {
|
|
352
|
+
expect(streamTools()).toHaveProperty(name);
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
|
|
292
356
|
it("fast-strike keeps a builtin extra override at its builtin position in the provider tool map", () => {
|
|
293
357
|
// Baseline spread semantics: { ...builtinTools, ...extraTools } replaces
|
|
294
358
|
// the value but KEEPS the builtin insertion position. A name-only merge
|
|
@@ -29,19 +29,24 @@ import type { AIModel, UsageRecorder } from "../../ai";
|
|
|
29
29
|
import { AgentEventBus } from "../../eventBus";
|
|
30
30
|
import type { SessionInfo } from "../../session";
|
|
31
31
|
import { inProcessSubagentSpawner } from "./subagentSpawner";
|
|
32
|
-
import type { StreamIdFactory } from "./types";
|
|
32
|
+
import type { StreamIdFactory, ToolExecutionContext } from "./types";
|
|
33
33
|
|
|
34
34
|
// Sentinels: only referential identity is asserted, so shapes are irrelevant.
|
|
35
35
|
const middleware = { __sentinel: "mw" } as unknown as LanguageModelMiddleware;
|
|
36
36
|
const usageRecorder = { __sentinel: "usage" } as unknown as UsageRecorder;
|
|
37
37
|
const streamIdFactory = (() => "sid") as unknown as StreamIdFactory;
|
|
38
38
|
|
|
39
|
+
const toolExecutionContext: ToolExecutionContext = {
|
|
40
|
+
run: (_call, execute) => execute(),
|
|
41
|
+
};
|
|
42
|
+
|
|
39
43
|
const runtime = {
|
|
40
44
|
session: {} as SessionInfo,
|
|
41
45
|
model: "test-model" as AIModel,
|
|
42
46
|
languageModelMiddleware: middleware,
|
|
43
47
|
usageRecorder,
|
|
44
48
|
streamIdFactory,
|
|
49
|
+
toolExecutionContext,
|
|
45
50
|
};
|
|
46
51
|
|
|
47
52
|
afterEach(() => {
|
|
@@ -52,7 +57,7 @@ afterEach(() => {
|
|
|
52
57
|
});
|
|
53
58
|
|
|
54
59
|
describe("subagentSpawner durable-hook forwarding", () => {
|
|
55
|
-
it("forwards
|
|
60
|
+
it("forwards durability hooks through runAuthChild", async () => {
|
|
56
61
|
await inProcessSubagentSpawner.spawn({
|
|
57
62
|
spec: { type: "authentication", target: "https://example.com" },
|
|
58
63
|
runtime,
|
|
@@ -63,9 +68,10 @@ describe("subagentSpawner durable-hook forwarding", () => {
|
|
|
63
68
|
expect(mocks.authInput?.languageModelMiddleware).toBe(middleware);
|
|
64
69
|
expect(mocks.authInput?.usageRecorder).toBe(usageRecorder);
|
|
65
70
|
expect(mocks.authInput?.streamIdFactory).toBe(streamIdFactory);
|
|
71
|
+
expect(mocks.authInput?.toolExecutionContext).toBe(toolExecutionContext);
|
|
66
72
|
});
|
|
67
73
|
|
|
68
|
-
it("forwards
|
|
74
|
+
it("forwards durability hooks through runJudgeChild", async () => {
|
|
69
75
|
await inProcessSubagentSpawner.spawn({
|
|
70
76
|
spec: {
|
|
71
77
|
type: "finding-judge",
|
|
@@ -82,6 +88,7 @@ describe("subagentSpawner durable-hook forwarding", () => {
|
|
|
82
88
|
expect(mocks.judgeCtx?.languageModelMiddleware).toBe(middleware);
|
|
83
89
|
expect(mocks.judgeCtx?.usageRecorder).toBe(usageRecorder);
|
|
84
90
|
expect(mocks.judgeCtx?.streamIdFactory).toBe(streamIdFactory);
|
|
91
|
+
expect(mocks.judgeCtx?.toolExecutionContext).toBe(toolExecutionContext);
|
|
85
92
|
});
|
|
86
93
|
|
|
87
94
|
it("passes the hooks through as unset when the runtime omits them", async () => {
|
|
@@ -98,5 +105,6 @@ describe("subagentSpawner durable-hook forwarding", () => {
|
|
|
98
105
|
expect(mocks.authInput?.languageModelMiddleware).toBeUndefined();
|
|
99
106
|
expect(mocks.authInput?.usageRecorder).toBeUndefined();
|
|
100
107
|
expect(mocks.authInput?.streamIdFactory).toBeUndefined();
|
|
108
|
+
expect(mocks.authInput?.toolExecutionContext).toBeUndefined();
|
|
101
109
|
});
|
|
102
110
|
});
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import type { ReasoningSetting } from "../../ai";
|
|
3
|
+
import type { SessionInfo } from "../../session";
|
|
4
|
+
import {
|
|
5
|
+
inProcessSubagentSpawner,
|
|
6
|
+
type SubagentSpec,
|
|
7
|
+
type SubagentType,
|
|
8
|
+
} from "./subagentSpawner";
|
|
9
|
+
import { delegateAuth } from "./tools/delegateAuth";
|
|
10
|
+
import { runAttackSurface } from "./tools/runAttackSurface";
|
|
11
|
+
import { generateThreatModelForEndpoint } from "./tools/threatModelGenerator";
|
|
12
|
+
import type { ToolContext } from "./tools/types";
|
|
13
|
+
|
|
14
|
+
const mocks = vi.hoisted(() => {
|
|
15
|
+
const received = new Map<string, Record<string, unknown>>();
|
|
16
|
+
const agent = (type: string, result: unknown) =>
|
|
17
|
+
class {
|
|
18
|
+
drained = Promise.resolve();
|
|
19
|
+
constructor(input: Record<string, unknown>) {
|
|
20
|
+
received.set(type, input);
|
|
21
|
+
}
|
|
22
|
+
async consume() {
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
return { received, agent };
|
|
27
|
+
});
|
|
28
|
+
vi.mock("../specialized/pentest/agent", () => ({
|
|
29
|
+
TargetedPentestAgent: mocks.agent("pentest", { findings: [] }),
|
|
30
|
+
}));
|
|
31
|
+
vi.mock("../specialized/codeAgent/agent", () => ({
|
|
32
|
+
CodeAgent: mocks.agent("code", {
|
|
33
|
+
exposure: 1,
|
|
34
|
+
dataSensitivity: 1,
|
|
35
|
+
functionCriticality: 1,
|
|
36
|
+
securityIndicators: 1,
|
|
37
|
+
businessLogic: "fixture",
|
|
38
|
+
threatModel: "fixture",
|
|
39
|
+
pentestObjectives: [],
|
|
40
|
+
}),
|
|
41
|
+
}));
|
|
42
|
+
vi.mock("../specialized/whiteboxAttackSurface", () => ({
|
|
43
|
+
WhiteboxAttackSurfaceAgent: mocks.agent("whitebox-attack-surface", {
|
|
44
|
+
apps: [],
|
|
45
|
+
summary: {},
|
|
46
|
+
}),
|
|
47
|
+
}));
|
|
48
|
+
vi.mock("../specialized/attackSurface/blackboxAgent", () => ({
|
|
49
|
+
BlackboxAttackSurfaceAgent: mocks.agent("blackbox-attack-surface", {
|
|
50
|
+
targets: [],
|
|
51
|
+
}),
|
|
52
|
+
}));
|
|
53
|
+
vi.mock("../specialized/authenticationAgent/agent", () => ({
|
|
54
|
+
runAuthenticationAgent: async (input: Record<string, unknown>) => {
|
|
55
|
+
mocks.received.set("authentication", input);
|
|
56
|
+
return { success: false, summary: "fixture" };
|
|
57
|
+
},
|
|
58
|
+
}));
|
|
59
|
+
vi.mock("../specialized/findingJudge", () => ({
|
|
60
|
+
judgeFinding: async (_: unknown, input: Record<string, unknown>) => {
|
|
61
|
+
mocks.received.set("finding-judge", input);
|
|
62
|
+
return { verdict: "confirmed" };
|
|
63
|
+
},
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
const specs = {
|
|
67
|
+
pentest: {
|
|
68
|
+
type: "pentest",
|
|
69
|
+
target: "https://example.test",
|
|
70
|
+
objectives: ["test"],
|
|
71
|
+
},
|
|
72
|
+
code: { type: "code", codebasePath: "/fixture", objective: "test" },
|
|
73
|
+
"whitebox-attack-surface": {
|
|
74
|
+
type: "whitebox-attack-surface",
|
|
75
|
+
codebasePath: "/fixture",
|
|
76
|
+
},
|
|
77
|
+
"blackbox-attack-surface": {
|
|
78
|
+
type: "blackbox-attack-surface",
|
|
79
|
+
target: "https://example.test",
|
|
80
|
+
},
|
|
81
|
+
authentication: { type: "authentication", target: "https://example.test" },
|
|
82
|
+
"finding-judge": { type: "finding-judge", judgeInput: {} as never },
|
|
83
|
+
} satisfies { [T in SubagentType]: Extract<SubagentSpec, { type: T }> };
|
|
84
|
+
|
|
85
|
+
const selections = [
|
|
86
|
+
{ model: "gpt-6.1-sol", reasoning: "low" },
|
|
87
|
+
{ model: "claude-sonnet-4-5", reasoning: "disabled" },
|
|
88
|
+
{ model: "gpt-5.1", reasoning: "none" },
|
|
89
|
+
] satisfies Array<{ model: string; reasoning: ReasoningSetting }>;
|
|
90
|
+
|
|
91
|
+
beforeEach(() => mocks.received.clear());
|
|
92
|
+
|
|
93
|
+
describe.each(Object.values(specs))("$type child reasoning", (spec) => {
|
|
94
|
+
it.each(selections)("preserves $model / $reasoning", async (selection) => {
|
|
95
|
+
await inProcessSubagentSpawner.spawn({
|
|
96
|
+
spec,
|
|
97
|
+
runtime: { session: { id: "root" } as SessionInfo, ...selection },
|
|
98
|
+
});
|
|
99
|
+
expect(mocks.received.get(spec.type)).toMatchObject(selection);
|
|
100
|
+
});
|
|
101
|
+
it("converts legacy inputs before constructing the child", async () => {
|
|
102
|
+
await inProcessSubagentSpawner.spawn({
|
|
103
|
+
spec,
|
|
104
|
+
runtime: {
|
|
105
|
+
session: { id: "root" } as SessionInfo,
|
|
106
|
+
model: "concentrate:glm-5.3",
|
|
107
|
+
openAIReasoningEffort: "xhigh",
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
expect(mocks.received.get(spec.type)).toMatchObject({
|
|
111
|
+
model: "concentrate:glm-5.3",
|
|
112
|
+
reasoning: "max",
|
|
113
|
+
});
|
|
114
|
+
expect(mocks.received.get(spec.type)).not.toHaveProperty(
|
|
115
|
+
"openAIReasoningEffort",
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe.each(
|
|
121
|
+
selections,
|
|
122
|
+
)("delegating tools with $model / $reasoning", (selection) => {
|
|
123
|
+
const context = () =>
|
|
124
|
+
({
|
|
125
|
+
...selection,
|
|
126
|
+
session: { id: "root" } as SessionInfo,
|
|
127
|
+
agentCwd: "/fixture",
|
|
128
|
+
subagentSpawner: inProcessSubagentSpawner,
|
|
129
|
+
}) as ToolContext;
|
|
130
|
+
const options = { toolCallId: "call-child", messages: [] };
|
|
131
|
+
it.each([
|
|
132
|
+
"whitebox",
|
|
133
|
+
"blackbox",
|
|
134
|
+
])("run_attack_surface %s reaches the child", async (mode) => {
|
|
135
|
+
await runAttackSurface(context()).execute?.(
|
|
136
|
+
{
|
|
137
|
+
target: "https://example.test",
|
|
138
|
+
cwd: mode === "whitebox" ? "/fixture" : undefined,
|
|
139
|
+
toolCallDescription: "test",
|
|
140
|
+
},
|
|
141
|
+
options,
|
|
142
|
+
);
|
|
143
|
+
expect(mocks.received.get(`${mode}-attack-surface`)).toMatchObject(
|
|
144
|
+
selection,
|
|
145
|
+
);
|
|
146
|
+
});
|
|
147
|
+
it("delegate_to_auth_subagent reaches the child", async () => {
|
|
148
|
+
await delegateAuth(context()).execute?.(
|
|
149
|
+
{
|
|
150
|
+
target: "https://example.test",
|
|
151
|
+
reason: "test",
|
|
152
|
+
toolCallDescription: "test",
|
|
153
|
+
},
|
|
154
|
+
options,
|
|
155
|
+
);
|
|
156
|
+
expect(mocks.received.get("authentication")).toMatchObject(selection);
|
|
157
|
+
});
|
|
158
|
+
it("endpoint threat modeling reaches its code child", async () => {
|
|
159
|
+
const result = await generateThreatModelForEndpoint(context(), {
|
|
160
|
+
appName: "fixture",
|
|
161
|
+
routePath: "/test",
|
|
162
|
+
description: "test",
|
|
163
|
+
});
|
|
164
|
+
expect(result).not.toBeNull();
|
|
165
|
+
expect(mocks.received.get("code")).toMatchObject(selection);
|
|
166
|
+
});
|
|
167
|
+
});
|