@pensar/apex 2.6.1 → 2.7.0-canary.52c132f4
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-yby11zaq.js → agent-112gdg69.js} +6 -6
- package/build/agent-9bh42v64.js +13 -0
- package/build/agent-jg7v2yn0.js +13 -0
- package/build/{agent-runs-g37vkrjr.js → agent-runs-hhjzsysf.js} +18 -18
- package/build/{agent-ayreaj6z.js → agent-ydy5fq92.js} +5 -5
- package/build/{apps-xn6km9yn.js → apps-v4jc7eqb.js} +13 -13
- package/build/{auth-d105wc64.js → auth-bxkn5pcb.js} +13 -13
- package/build/{blackboxAgent-s56sgx9b.js → blackboxAgent-260yqknt.js} +6 -6
- package/build/{blackboxPentest-ps78v3w7.js → blackboxPentest-nbn588pb.js} +17 -12
- package/build/{cli-3sp6nd8d.js → cli-087apjgk.js} +2 -2
- package/build/{cli-1ve18npr.js → cli-1wtxf161.js} +3 -2
- package/build/{cli-d37a42dc.js → cli-3158x9wb.js} +101 -18
- package/build/{cli-fy6vh2a7.js → cli-35gz0ahm.js} +1 -1
- package/build/{cli-65g6rcat.js → cli-5xdefy58.js} +1 -1
- package/build/{cli-709rvekb.js → cli-6vpprmxb.js} +4 -2
- package/build/{cli-az3xq70v.js → cli-8hrdnq0e.js} +1 -1
- package/build/{cli-7eea4e2y.js → cli-ahk627k3.js} +6 -6
- package/build/{cli-c05y640n.js → cli-bc793xfp.js} +1 -1
- package/build/{cli-ae8jqxqr.js → cli-cs7hsb1w.js} +2 -2
- package/build/{cli-qgz1q9g5.js → cli-ene4g09p.js} +223 -76
- package/build/{cli-gx71jcke.js → cli-k8m6737j.js} +1 -1
- package/build/{cli-dpsw2fe6.js → cli-mm2vxyne.js} +360 -187
- package/build/{cli-ngq9dr8n.js → cli-mpmpfce6.js} +3 -3
- package/build/{cli-kb21qhvm.js → cli-np9x97h3.js} +4 -3
- package/build/{cli-k2nwxta0.js → cli-tb77javm.js} +2 -2
- package/build/{cli-xtc2t6me.js → cli-wa52mx4p.js} +103 -39
- package/build/{cli-n2en7j5b.js → cli-xe4wq07r.js} +1 -1
- package/build/cli.js +70 -40
- package/build/{config-zpqkd5cz.js → config-gpxx6m5z.js} +1 -1
- package/build/{fastStrike-mcjdvwez.js → fastStrike-v0r461wn.js} +67 -15
- package/build/{fixes-kytx5dmj.js → fixes-c51d83b4.js} +13 -13
- package/build/{index-qv4cc65p.js → index-269a90mm.js} +13 -13
- package/build/{index-wqetp6gq.js → index-3ggmqh6x.js} +12 -7
- package/build/{index-4vqdgb42.js → index-e97991ve.js} +1473 -1217
- package/build/{index-n65z6v7b.js → index-ffay4gb2.js} +6 -6
- package/build/{index-ns4m4s01.js → index-gw6t92t5.js} +4 -4
- package/build/{index-dr3tg1w3.js → index-kkt51z6t.js} +1 -1
- package/build/{index-fv64eb32.js → index-kmaq2ym2.js} +2 -2
- package/build/{index-je6hcsqr.js → index-wgas3zgb.js} +1 -1
- package/build/{index-r9yjkfrv.js → index-xfqh0wte.js} +4 -4
- package/build/{issues-eb3q9d3a.js → issues-sq3zya6y.js} +13 -13
- package/build/{knowledge-fqsvtx0f.js → knowledge-kzd0cgcm.js} +13 -13
- package/build/lib/{chunk-r4j8ybn9.js → chunk-0parq6kp.js} +87 -36
- package/build/lib/{chunk-v3dk9j7k.js → chunk-2rcfbtpx.js} +80 -21
- package/build/lib/{chunk-acgbyf5h.js → chunk-5axh2ztr.js} +3 -2
- package/build/lib/{chunk-yrnrbjes.js → chunk-5qdc4rc6.js} +4 -2
- package/build/lib/{chunk-xhdpgpkm.js → chunk-61pnyq94.js} +2 -2
- package/build/lib/{chunk-1azdancq.js → chunk-7p9f6cxx.js} +1 -1
- package/build/lib/{chunk-z137x08b.js → chunk-7sexq62c.js} +7 -5
- package/build/lib/{chunk-ba41jh41.js → chunk-7zayxxn6.js} +304 -129
- package/build/lib/{chunk-3c00n0cy.js → chunk-83nets1m.js} +8 -3
- package/build/lib/{chunk-e8yy2k73.js → chunk-ajfd3s37.js} +28 -2
- package/build/lib/{chunk-4hwzqthr.js → chunk-ay1fx18z.js} +3 -2
- package/build/lib/{chunk-1fy8azee.js → chunk-bgnq735r.js} +1 -1
- package/build/lib/{chunk-mg03jdmt.js → chunk-eaanxcjj.js} +1 -1
- package/build/lib/{chunk-w66ce82a.js → chunk-f28sa6x2.js} +4 -2
- package/build/lib/{chunk-z96pbjhd.js → chunk-f6xde44n.js} +13 -6
- package/build/lib/{chunk-1jvwqnem.js → chunk-fvgehnst.js} +104 -40
- package/build/lib/{chunk-2qsq76xq.js → chunk-fy2a1dm3.js} +128 -34
- package/build/lib/{chunk-7pwa92rn.js → chunk-jqy0ftnp.js} +1 -1
- package/build/lib/{chunk-bb0ekhkw.js → chunk-k6erk6fv.js} +69 -18
- package/build/lib/{chunk-9tt2021m.js → chunk-s338j54x.js} +9 -9
- package/build/lib/{chunk-1yct6cra.js → chunk-se6sk7e4.js} +1 -1
- package/build/lib/{chunk-nhfax4gb.js → chunk-tdprhz5x.js} +1 -1
- package/build/lib/{chunk-r2dkp4tb.js → chunk-wbt03786.js} +1 -1
- package/build/lib/{chunk-9yksqgzr.js → chunk-yk43cvgb.js} +20 -13
- package/build/lib/core/agents/agentRuntime.d.ts +2 -1
- package/build/lib/core/agents/defineAgent.d.ts +3 -2
- package/build/lib/core/agents/offSecAgent/index.d.ts +3 -1
- package/build/lib/core/agents/offSecAgent/index.js +10 -8
- package/build/lib/core/agents/offSecAgent/prompt.d.ts +3 -1
- package/build/lib/core/agents/offSecAgent/subagentSpawner.d.ts +2 -1
- package/build/lib/core/agents/offSecAgent/subagentSpawner.js +5 -5
- package/build/lib/core/agents/offSecAgent/tools/index.js +4 -4
- 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 +2 -1
- package/build/lib/core/agents/offSecAgent/types.d.ts +7 -1
- package/build/lib/core/agents/specialized/attackSurface/blackboxAgent.js +9 -9
- package/build/lib/core/agents/specialized/attackSurface/schemas.js +9 -9
- package/build/lib/core/agents/specialized/authenticationAgent/index.js +10 -10
- package/build/lib/core/agents/specialized/codeAgent/agent.js +9 -9
- package/build/lib/core/agents/specialized/codeAgent/prompts.d.ts +1 -0
- package/build/lib/core/agents/specialized/findingJudge/agent.js +8 -8
- package/build/lib/core/agents/specialized/findingJudge/index.js +3 -3
- package/build/lib/core/agents/specialized/patching/index.js +10 -10
- package/build/lib/core/agents/specialized/pentest/agent.d.ts +18 -4
- package/build/lib/core/agents/specialized/pentest/agent.js +11 -9
- package/build/lib/core/agents/specialized/whiteboxAttackSurface/index.js +9 -9
- package/build/lib/core/ai/ai.d.ts +23 -6
- package/build/lib/core/ai/ai.js +2 -2
- package/build/lib/core/ai/index.js +2 -2
- package/build/lib/core/ai/models/claude-capabilities.d.ts +3 -2
- package/build/lib/core/ai/models/index.d.ts +1 -1
- package/build/lib/core/ai/utils.d.ts +2 -0
- package/build/lib/core/ai/utils.js +4 -2
- package/build/lib/core/api/index.d.ts +3 -0
- package/build/lib/core/api/index.js +22 -19
- package/build/lib/core/api/targetedPentest.d.ts +1 -0
- package/build/lib/core/api/targetedPentest.js +10 -10
- package/build/lib/core/config/config.d.ts +3 -0
- package/build/lib/core/config/index.js +1 -1
- package/build/lib/core/findings/registry.js +3 -3
- package/build/lib/core/session/index.d.ts +12 -0
- package/build/lib/core/session/index.js +2 -2
- package/build/lib/core/session/persistence.d.ts +7 -0
- package/build/lib/core/session/persistence.js +7 -3
- package/build/lib/core/workflows/fastStrike.d.ts +3 -1
- package/build/lib/core/workflows/pentest.d.ts +8 -1
- package/build/lib/core/workflows/pentest.js +15 -15
- package/build/lib/core/workflows/seams.js +4 -4
- package/build/lib/core/workflows/whiteboxAttackSurface.js +11 -11
- package/build/lib/index.js +22 -22
- package/build/{logs-x62b7hk1.js → logs-yk8dk6aa.js} +13 -13
- package/build/{native-rollout-evidence-c9yhfqcs.js → native-rollout-evidence-krpdfdv7.js} +3 -3
- package/build/{offesecAgent-5whnpeta.js → offesecAgent-aw87gf37.js} +4 -4
- package/build/pentest-t0p4nw2a.js +22 -0
- package/build/{pentests-e0f32aqx.js → pentests-577n3x75.js} +13 -13
- package/build/recordedRunClient-d7947b0z.js +11 -0
- package/build/{targetedPentest-rcbs4nvp.js → targetedPentest-7v849dtm.js} +18 -11
- package/build/{targets-xj9g3q0z.js → targets-3vjxv3yj.js} +13 -13
- package/build/threatModel-n0grwkav.js +21 -0
- package/build/{uninstall-7s784q4a.js → uninstall-ctv33v8j.js} +1 -1
- package/build/{upload-4gvhwmvr.js → upload-rnec235r.js} +4 -4
- package/build/{utils-cjrz64pc.js → utils-6420gkkg.js} +3 -3
- package/package.json +1 -1
- package/src/cli.ts +48 -14
- package/src/core/agents/agentRuntime.test.ts +38 -0
- package/src/core/agents/agentRuntime.ts +5 -2
- package/src/core/agents/defineAgent.ts +3 -1
- package/src/core/agents/offSecAgent/index.ts +3 -0
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.test.ts +92 -5
- package/src/core/agents/offSecAgent/offensiveSecurityAgent.ts +70 -31
- 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.ts +12 -1
- package/src/core/agents/offSecAgent/tools/delegateAuth.ts +1 -0
- 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 +2 -0
- package/src/core/agents/offSecAgent/tools/runPentestWorkflow.test.ts +57 -0
- package/src/core/agents/offSecAgent/tools/runPentestWorkflow.ts +19 -1
- package/src/core/agents/offSecAgent/tools/runWhiteboxScan.ts +5 -2
- package/src/core/agents/offSecAgent/tools/spawnCodingAgent.ts +1 -0
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.test.ts +72 -2
- package/src/core/agents/offSecAgent/tools/spawnPentestAgent.ts +32 -11
- package/src/core/agents/offSecAgent/tools/spawnPentestSwarm.ts +25 -5
- package/src/core/agents/offSecAgent/tools/threatModelGenerator.ts +1 -0
- package/src/core/agents/offSecAgent/tools/types.ts +6 -1
- 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 +9 -0
- 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/pentest/agent.test.ts +116 -0
- package/src/core/agents/specialized/pentest/agent.ts +178 -49
- package/src/core/agents/specialized/pentest/results.test.ts +59 -4
- package/src/core/agents/specialized/whiteboxAttackSurface/endpointDocumentationAgent.ts +1 -0
- package/src/core/ai/ai.operator-context.bench.test.ts +1408 -0
- package/src/core/ai/ai.recorded-context.test.ts +74 -0
- package/src/core/ai/ai.test.ts +54 -0
- package/src/core/ai/ai.ts +299 -80
- package/src/core/ai/compactionTelemetry.test.ts +2 -2
- 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/index.ts +4 -1
- package/src/core/ai/models/models.test.ts +23 -0
- package/src/core/ai/models/openrouter.ts +6 -0
- 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/gateway-models.test.ts +16 -6
- package/src/core/ai/utils.native-rollout-evidence.test.ts +1 -0
- package/src/core/ai/utils.ts +189 -143
- package/src/core/api/blackboxPentest.ts +9 -1
- package/src/core/api/index.ts +9 -0
- package/src/core/api/targetedPentest.ts +19 -5
- package/src/core/config/config.test.ts +35 -0
- package/src/core/config/config.ts +5 -0
- package/src/core/observability/telemetry.test.ts +2 -3
- package/src/core/session/index.ts +5 -0
- package/src/core/session/persistence.test.ts +62 -0
- package/src/core/session/persistence.ts +56 -0
- 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 +103 -11
- package/src/core/workflows/pentest.test.ts +104 -0
- package/src/core/workflows/pentest.ts +110 -7
- package/src/core/workflows/seams.test.ts +13 -0
- package/src/core/workflows/seams.ts +5 -1
- package/src/core/workflows/whiteboxAttackSurface.ts +1 -0
- 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 +176 -0
- package/src/tui/components/commands/advanced-settings.test.ts +28 -0
- package/src/tui/components/commands/advanced-settings.tsx +237 -19
- package/src/tui/components/operator-dashboard/index.tsx +46 -9
- package/src/tui/components/operator-dashboard/logic.test.ts +106 -0
- package/src/tui/components/operator-dashboard/logic.ts +42 -2
- 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/route.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/pentest-e61hc38s.js +0 -22
- package/build/recordedRunClient-dp032c32.js +0 -11
- package/build/threatModel-jkxfa40s.js +0 -21
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
config2,
|
|
3
3
|
init_config
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-35gz0ahm.js";
|
|
5
5
|
import {
|
|
6
6
|
getPensarApiUrl2,
|
|
7
7
|
init_constants,
|
|
8
8
|
ensureValidToken2,
|
|
9
9
|
signGatewayRequest2,
|
|
10
10
|
init_auth
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-bc793xfp.js";
|
|
12
12
|
import {
|
|
13
13
|
parseTargetUrl
|
|
14
14
|
} from "./cli-0wsh8j2t.js";
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
normalizeStepUsage,
|
|
43
43
|
streamResponse,
|
|
44
44
|
generateObjectResponse
|
|
45
|
-
} from "./cli-
|
|
45
|
+
} from "./cli-mm2vxyne.js";
|
|
46
46
|
import {
|
|
47
47
|
init_v4,
|
|
48
48
|
tool
|
|
@@ -82,7 +82,7 @@ import {
|
|
|
82
82
|
import {
|
|
83
83
|
getCurrentVersion,
|
|
84
84
|
init_installation
|
|
85
|
-
} from "./cli-
|
|
85
|
+
} from "./cli-5xdefy58.js";
|
|
86
86
|
import {
|
|
87
87
|
require_src6
|
|
88
88
|
} from "./cli-bb02pjt0.js";
|
|
@@ -100316,11 +100316,12 @@ ${lines.join(`
|
|
|
100316
100316
|
|
|
100317
100317
|
${readGuidance} A \`README.md\` inside \`provided_files/\` may include per-file descriptions supplied by the user — check it first before diving into individual files.`;
|
|
100318
100318
|
}
|
|
100319
|
-
function buildSessionWorkspaceSection(session, agentCwd, activeTools, fileWorkspaceRoot) {
|
|
100319
|
+
function buildSessionWorkspaceSection(session, agentCwd, activeTools, fileWorkspaceRoot, findingPolicy = "native") {
|
|
100320
100320
|
const sandboxMode = agentCwd === session.rootPath;
|
|
100321
100321
|
const providedFilesSection = buildProvidedFilesSection(session.rootPath, fileWorkspaceRoot);
|
|
100322
|
-
const sourceAssessmentSection = buildSourceAssessmentSection(session, agentCwd, { sandboxMode, activeTools, fileWorkspaceRoot });
|
|
100322
|
+
const sourceAssessmentSection = buildSourceAssessmentSection(session, agentCwd, { sandboxMode, activeTools, fileWorkspaceRoot }, findingPolicy);
|
|
100323
100323
|
if (fileWorkspaceRoot) {
|
|
100324
|
+
const artifactsGuidance = findingPolicy === "external" ? `Session artifacts live at ${session.rootPath}. Follow the caller's output contract for findings; browser tools save their own evidence.` : `Session artifacts live at ${session.rootPath}. Findings and published PoCs are written by \`document_vulnerability\`, and browser tools save their own evidence.`;
|
|
100324
100325
|
return `
|
|
100325
100326
|
|
|
100326
100327
|
# Working Directory and File Workspace
|
|
@@ -100329,9 +100330,16 @@ Your shell starts in ${agentCwd}. Native file tools are confined to ${fileWorksp
|
|
|
100329
100330
|
|
|
100330
100331
|
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.
|
|
100331
100332
|
|
|
100332
|
-
|
|
100333
|
+
${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}`;
|
|
100333
100334
|
}
|
|
100334
100335
|
if (sandboxMode) {
|
|
100336
|
+
if (findingPolicy === "external") {
|
|
100337
|
+
return `
|
|
100338
|
+
|
|
100339
|
+
# Session Workspace
|
|
100340
|
+
|
|
100341
|
+
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}`;
|
|
100342
|
+
}
|
|
100335
100343
|
return `
|
|
100336
100344
|
|
|
100337
100345
|
# Session Workspace
|
|
@@ -100347,6 +100355,14 @@ The session directory (${session.rootPath}) contains these subdirectories:
|
|
|
100347
100355
|
- **provided_files/** — user-uploaded files (sample payloads, docs, test data); populated when the project has workspace files configured.
|
|
100348
100356
|
|
|
100349
100357
|
Tools like \`document_vulnerability\` and browser evidence capture write to the correct subdirectories automatically.${providedFilesSection}${sourceAssessmentSection}`;
|
|
100358
|
+
}
|
|
100359
|
+
if (findingPolicy === "external") {
|
|
100360
|
+
return `
|
|
100361
|
+
|
|
100362
|
+
# Working Directory
|
|
100363
|
+
|
|
100364
|
+
Your shell starts in the user's project directory: ${agentCwd}
|
|
100365
|
+
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}`;
|
|
100350
100366
|
}
|
|
100351
100367
|
return `
|
|
100352
100368
|
|
|
@@ -100381,7 +100397,7 @@ function buildSourceAssessmentSection(session, agentCwd, {
|
|
|
100381
100397
|
sandboxMode,
|
|
100382
100398
|
activeTools,
|
|
100383
100399
|
fileWorkspaceRoot
|
|
100384
|
-
}) {
|
|
100400
|
+
}, findingPolicy) {
|
|
100385
100401
|
const codebasePath = session.config?.codebasePath;
|
|
100386
100402
|
const hasSourceAccess = Boolean(codebasePath) || !sandboxMode && !fileWorkspaceRoot;
|
|
100387
100403
|
if (!hasSourceAccess)
|
|
@@ -100405,7 +100421,7 @@ The configured codebase path is ${codebasePath}, while your shell starts in ${ag
|
|
|
100405
100421
|
hasTool("run_whitebox_scan") && "- Use `run_whitebox_scan` for installed scanners.",
|
|
100406
100422
|
hasTool("spawn_coding_agent") && "- Use `spawn_coding_agent` for independent deep dives.",
|
|
100407
100423
|
hasTool("create_whitebox_candidate") && "- Track unverified hypotheses with `create_whitebox_candidate`.",
|
|
100408
|
-
hasTool("document_vulnerability") && "- Only call `document_vulnerability` after a PoC, crash reproducer, or dynamic check confirms exploitability.",
|
|
100424
|
+
findingPolicy !== "external" && hasTool("document_vulnerability") && "- Only call `document_vulnerability` after a PoC, crash reproducer, or dynamic check confirms exploitability.",
|
|
100409
100425
|
hasTool("start_whitebox_job") && hasTool("poll_whitebox_job") && "- Run builds, local servers, sanitizer runs, and microfuzzers through bounded whitebox jobs so logs and crashes are preserved as artifacts."
|
|
100410
100426
|
].filter(Boolean).join(`
|
|
100411
100427
|
`);
|
|
@@ -100421,6 +100437,14 @@ ${toolGuidance}${repoEditBullet}`;
|
|
|
100421
100437
|
}
|
|
100422
100438
|
function buildBaseSystemPrompt(options) {
|
|
100423
100439
|
const sandboxMode = options?.sandboxMode ?? true;
|
|
100440
|
+
const externalFindings = options?.findingPolicy === "external";
|
|
100441
|
+
const exploitationCapability = externalFindings ? "- **Exploitation and proof development** — use the available tools only as far as the assigned objective requires" : "- **Exploitation & proof-of-concept development** — provide PoC scripts inline to document_vulnerability which executes and validates them";
|
|
100442
|
+
const reportingCapability = externalFindings ? "- **Reporting** — submit concise findings through the caller's requested output contract; the caller grades them after the run" : "- **Reporting** — document confirmed findings with evidence, impact, and remediation";
|
|
100443
|
+
const findingToolReference = externalFindings ? `## Findings
|
|
100444
|
+
- Use the caller's requested output format for any discovered vulnerabilities. Include the affected surface, observed behavior, and likely security impact.` : `## Findings & PoCs
|
|
100445
|
+
- **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.`;
|
|
100446
|
+
const findingWorkRule = externalFindings ? "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." : "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.";
|
|
100447
|
+
const reportRule = externalFindings ? "5. **Follow the caller's output contract.** Keep intermediate files in scratchpad/ and submit final finding artifacts only where the caller requested." : "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.";
|
|
100424
100448
|
const stayInSessionParagraph = sandboxMode ? `
|
|
100425
100449
|
|
|
100426
100450
|
**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.` : "";
|
|
@@ -100433,9 +100457,9 @@ You work interactively with the user. Execute the task they ask for, report your
|
|
|
100433
100457
|
You can perform the full lifecycle of a penetration test and support a wide range of cybersecurity tasks:
|
|
100434
100458
|
- **Reconnaissance & attack surface mapping** — subdomain enumeration, endpoint discovery, JS analysis, authenticated crawling
|
|
100435
100459
|
- **Vulnerability testing** — injection flaws, auth bypasses, access control issues, misconfigurations, business logic flaws
|
|
100436
|
-
|
|
100460
|
+
${exploitationCapability}
|
|
100437
100461
|
- **Source code analysis** — read and search codebases for security-relevant patterns, misconfigurations, and vulnerabilities
|
|
100438
|
-
|
|
100462
|
+
${reportingCapability}
|
|
100439
100463
|
|
|
100440
100464
|
# Tool Reference
|
|
100441
100465
|
|
|
@@ -100486,8 +100510,7 @@ You can perform the full lifecycle of a penetration test and support a wide rang
|
|
|
100486
100510
|
|
|
100487
100511
|
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.
|
|
100488
100512
|
|
|
100489
|
-
|
|
100490
|
-
- **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.
|
|
100513
|
+
${findingToolReference}
|
|
100491
100514
|
|
|
100492
100515
|
## Orchestration
|
|
100493
100516
|
- **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).
|
|
@@ -100515,7 +100538,7 @@ Run \`pensar --help\` or \`pensar <command> --help\` for exact flags — the CLI
|
|
|
100515
100538
|
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.
|
|
100516
100539
|
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.
|
|
100517
100540
|
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).
|
|
100518
|
-
|
|
100541
|
+
${findingWorkRule}
|
|
100519
100542
|
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.
|
|
100520
100543
|
|
|
100521
100544
|
# Command Execution
|
|
@@ -100533,7 +100556,7 @@ For long-running services (servers, listeners, watchers), background them with *
|
|
|
100533
100556
|
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.
|
|
100534
100557
|
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.
|
|
100535
100558
|
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.
|
|
100536
|
-
|
|
100559
|
+
${reportRule}`;
|
|
100537
100560
|
}
|
|
100538
100561
|
var BASE_SYSTEM_PROMPT = buildBaseSystemPrompt();
|
|
100539
100562
|
|
|
@@ -112607,18 +112630,20 @@ function inProcessSeams(overrides) {
|
|
|
112607
112630
|
};
|
|
112608
112631
|
}
|
|
112609
112632
|
function resolveItemHooks(hooks, seams, item, index) {
|
|
112633
|
+
const itemHooks = seams.hooksForItem?.(item, index);
|
|
112610
112634
|
return {
|
|
112611
112635
|
...hooks,
|
|
112612
112636
|
contextRecorder: undefined,
|
|
112613
112637
|
inferenceRecorder: undefined,
|
|
112614
112638
|
toolExecutionRecorder: undefined,
|
|
112615
|
-
...
|
|
112639
|
+
...itemHooks,
|
|
112640
|
+
...hooks?.findingPolicy === "external" ? { findingPolicy: "external" } : {}
|
|
112616
112641
|
};
|
|
112617
112642
|
}
|
|
112618
112643
|
|
|
112619
112644
|
// src/core/agents/offSecAgent/subagentSpawner.ts
|
|
112620
112645
|
async function runSpawnedPentestWorker(spec, input) {
|
|
112621
|
-
const { TargetedPentestAgent } = await import("./agent-
|
|
112646
|
+
const { TargetedPentestAgent } = await import("./agent-112gdg69.js");
|
|
112622
112647
|
const hooks = resolveItemHooks(input.hooks, input.seams, spec, 0);
|
|
112623
112648
|
const agent = new TargetedPentestAgent({
|
|
112624
112649
|
target: spec.target,
|
|
@@ -112678,6 +112703,7 @@ var runPentestChild = async (spec, ctx) => {
|
|
|
112678
112703
|
openAIReasoningEffort: ctx.openAIReasoningEffort,
|
|
112679
112704
|
display: ctx.display,
|
|
112680
112705
|
hooks: {
|
|
112706
|
+
findingPolicy: ctx.findingPolicy,
|
|
112681
112707
|
backends: ctx.backends,
|
|
112682
112708
|
sandbox: ctx.sandbox,
|
|
112683
112709
|
languageModelMiddleware: ctx.languageModelMiddleware,
|
|
@@ -112695,8 +112721,9 @@ var runPentestChild = async (spec, ctx) => {
|
|
|
112695
112721
|
};
|
|
112696
112722
|
};
|
|
112697
112723
|
var runCodeChild = async (spec, ctx) => {
|
|
112698
|
-
const { CodeAgent } = await import("./agent-
|
|
112724
|
+
const { CodeAgent } = await import("./agent-9bh42v64.js");
|
|
112699
112725
|
const agent = new CodeAgent({
|
|
112726
|
+
findingPolicy: ctx.findingPolicy,
|
|
112700
112727
|
codebasePath: spec.codebasePath,
|
|
112701
112728
|
objective: spec.objective,
|
|
112702
112729
|
system: spec.system,
|
|
@@ -112727,8 +112754,9 @@ var runCodeChild = async (spec, ctx) => {
|
|
|
112727
112754
|
return { run: () => agent.consume(), drained: () => agent.drained };
|
|
112728
112755
|
};
|
|
112729
112756
|
var runWhiteboxChild = async (spec, ctx) => {
|
|
112730
|
-
const { WhiteboxAttackSurfaceAgent } = await import("./index-
|
|
112757
|
+
const { WhiteboxAttackSurfaceAgent } = await import("./index-ffay4gb2.js");
|
|
112731
112758
|
const agent = new WhiteboxAttackSurfaceAgent({
|
|
112759
|
+
findingPolicy: ctx.findingPolicy,
|
|
112732
112760
|
codebasePath: spec.codebasePath,
|
|
112733
112761
|
attackSurfaceRegistry: spec.attackSurfaceRegistry,
|
|
112734
112762
|
model: ctx.model,
|
|
@@ -112747,8 +112775,9 @@ var runWhiteboxChild = async (spec, ctx) => {
|
|
|
112747
112775
|
return { run: () => agent.consume(), drained: () => agent.drained };
|
|
112748
112776
|
};
|
|
112749
112777
|
var runBlackboxChild = async (spec, ctx) => {
|
|
112750
|
-
const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-
|
|
112778
|
+
const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-260yqknt.js");
|
|
112751
112779
|
const agent = new BlackboxAttackSurfaceAgent({
|
|
112780
|
+
findingPolicy: ctx.findingPolicy,
|
|
112752
112781
|
target: spec.target,
|
|
112753
112782
|
attackSurfaceRegistry: spec.attackSurfaceRegistry,
|
|
112754
112783
|
model: ctx.model,
|
|
@@ -112766,9 +112795,10 @@ var runBlackboxChild = async (spec, ctx) => {
|
|
|
112766
112795
|
return { run: () => agent.consume(), drained: () => agent.drained };
|
|
112767
112796
|
};
|
|
112768
112797
|
var runAuthChild = async (spec, ctx) => {
|
|
112769
|
-
const { runAuthenticationAgent } = await import("./agent-
|
|
112798
|
+
const { runAuthenticationAgent } = await import("./agent-jg7v2yn0.js");
|
|
112770
112799
|
return {
|
|
112771
112800
|
run: () => runAuthenticationAgent({
|
|
112801
|
+
findingPolicy: ctx.findingPolicy,
|
|
112772
112802
|
target: spec.target,
|
|
112773
112803
|
authHints: spec.authHints,
|
|
112774
112804
|
session: ctx.session,
|
|
@@ -112788,7 +112818,7 @@ var runAuthChild = async (spec, ctx) => {
|
|
|
112788
112818
|
};
|
|
112789
112819
|
};
|
|
112790
112820
|
var runJudgeChild = async (spec, ctx) => {
|
|
112791
|
-
const { judgeFinding } = await import("./index-
|
|
112821
|
+
const { judgeFinding } = await import("./index-gw6t92t5.js");
|
|
112792
112822
|
return {
|
|
112793
112823
|
run: () => judgeFinding(spec.judgeInput, {
|
|
112794
112824
|
model: ctx.model,
|
|
@@ -116817,6 +116847,7 @@ IMPORTANT: Pass protectedEndpoints in authHints when you've discovered 401/403 e
|
|
|
116817
116847
|
const result = await spawner.spawn({
|
|
116818
116848
|
spec: { type: "authentication", target, authHints },
|
|
116819
116849
|
runtime: {
|
|
116850
|
+
findingPolicy: ctx.findingPolicy,
|
|
116820
116851
|
session: ctx.session,
|
|
116821
116852
|
model: ctx.model,
|
|
116822
116853
|
authConfig: ctx.authConfig,
|
|
@@ -117692,6 +117723,7 @@ async function generateThreatModelForEndpoint(ctx, input) {
|
|
|
117692
117723
|
excludeTools: ["document_endpoint", "document_app"]
|
|
117693
117724
|
},
|
|
117694
117725
|
runtime: {
|
|
117726
|
+
findingPolicy: ctx.findingPolicy,
|
|
117695
117727
|
session: ctx.session,
|
|
117696
117728
|
model,
|
|
117697
117729
|
authConfig: ctx.authConfig,
|
|
@@ -124836,34 +124868,86 @@ Each directory entry is suffixed with "/" for easy identification.`,
|
|
|
124836
124868
|
// src/core/agents/offSecAgent/tools/listMemories.ts
|
|
124837
124869
|
init_dist();
|
|
124838
124870
|
init_zod();
|
|
124871
|
+
var PAGE_SIZE = 20;
|
|
124872
|
+
var PAGE_CHAR_BUDGET = 12000;
|
|
124839
124873
|
var listMemoriesInputSchema = object({
|
|
124840
124874
|
category: _enum(MEMORY_CATEGORIES).optional().describe('Filter by category: "app", "framework", or "general". ' + "Omit to list memories across all categories."),
|
|
124841
124875
|
tag: string().optional().describe("Optional tag to filter memories by (exact match)"),
|
|
124876
|
+
cursor: object({
|
|
124877
|
+
createdAt: string(),
|
|
124878
|
+
category: _enum(MEMORY_CATEGORIES),
|
|
124879
|
+
id: string()
|
|
124880
|
+
}).optional().describe("Pass the previous nextCursor to continue a listing"),
|
|
124842
124881
|
toolCallDescription: string().describe("A concise, human-readable description of what this tool call is doing (e.g., 'Listing stored recon notes')")
|
|
124843
124882
|
});
|
|
124883
|
+
function compareMemories(a, b) {
|
|
124884
|
+
const byCreatedAt = Date.parse(b.createdAt) - Date.parse(a.createdAt);
|
|
124885
|
+
if (byCreatedAt > 0 || byCreatedAt < 0)
|
|
124886
|
+
return byCreatedAt;
|
|
124887
|
+
return a.category.localeCompare(b.category) || a.id.localeCompare(b.id);
|
|
124888
|
+
}
|
|
124889
|
+
function previewSummary(memory) {
|
|
124890
|
+
const title = memory.title.slice(0, 160);
|
|
124891
|
+
const tags = memory.tags.slice(0, 8).map((tag) => tag.slice(0, 48));
|
|
124892
|
+
const truncated = title.length < memory.title.length || tags.length < memory.tags.length || tags.some((tag, index) => tag.length < (memory.tags[index]?.length ?? tag.length));
|
|
124893
|
+
return {
|
|
124894
|
+
id: memory.id,
|
|
124895
|
+
category: memory.category,
|
|
124896
|
+
title,
|
|
124897
|
+
tags,
|
|
124898
|
+
createdAt: memory.createdAt,
|
|
124899
|
+
...truncated ? { truncated: true } : {}
|
|
124900
|
+
};
|
|
124901
|
+
}
|
|
124844
124902
|
function listMemories2(ctx) {
|
|
124845
124903
|
return tool({
|
|
124846
124904
|
description: `List saved memories, optionally filtered by category and/or tag.
|
|
124847
124905
|
|
|
124848
|
-
Returns lightweight summaries (id, category, title, tags, createdAt)
|
|
124849
|
-
most recent first. Use
|
|
124850
|
-
|
|
124906
|
+
Returns up to 20 lightweight summaries (id, category, title, tags, createdAt)
|
|
124907
|
+
sorted by most recent first. Use nextCursor to continue until it is null;
|
|
124908
|
+
count is the current total matching memories. A fresh listing includes newer
|
|
124909
|
+
memories added ahead of a cursor. Titles and tags may be abbreviated in the
|
|
124910
|
+
listing. Use category + id with get_memory to retrieve full content.`,
|
|
124851
124911
|
inputSchema: listMemoriesInputSchema,
|
|
124852
|
-
execute: async ({ category, tag }, { toolCallId }) => {
|
|
124912
|
+
execute: async ({ category, tag, cursor }, { toolCallId }) => {
|
|
124853
124913
|
try {
|
|
124854
124914
|
const memories = await listMemories({ category, tag }, { sessionId: ctx.session.id, toolCallId });
|
|
124915
|
+
const ordered = [...memories].sort(compareMemories);
|
|
124916
|
+
let start = 0;
|
|
124917
|
+
if (cursor) {
|
|
124918
|
+
start = ordered.findIndex((memory) => compareMemories(memory, cursor) > 0);
|
|
124919
|
+
if (start < 0)
|
|
124920
|
+
start = ordered.length;
|
|
124921
|
+
}
|
|
124922
|
+
const page = [];
|
|
124923
|
+
let pageChars = 0;
|
|
124924
|
+
for (const memory of ordered.slice(start, start + PAGE_SIZE)) {
|
|
124925
|
+
const summary = previewSummary(memory);
|
|
124926
|
+
const chars = JSON.stringify(summary).length + 1;
|
|
124927
|
+
if (page.length > 0 && pageChars + chars > PAGE_CHAR_BUDGET)
|
|
124928
|
+
break;
|
|
124929
|
+
page.push(summary);
|
|
124930
|
+
pageChars += chars;
|
|
124931
|
+
}
|
|
124932
|
+
const last = page.at(-1);
|
|
124855
124933
|
return {
|
|
124856
124934
|
success: true,
|
|
124857
124935
|
error: "",
|
|
124858
|
-
memories,
|
|
124859
|
-
count: memories.length
|
|
124936
|
+
memories: page,
|
|
124937
|
+
count: memories.length,
|
|
124938
|
+
nextCursor: start + page.length < ordered.length && last ? {
|
|
124939
|
+
createdAt: last.createdAt,
|
|
124940
|
+
category: last.category,
|
|
124941
|
+
id: last.id
|
|
124942
|
+
} : null
|
|
124860
124943
|
};
|
|
124861
124944
|
} catch (err) {
|
|
124862
124945
|
return {
|
|
124863
124946
|
success: false,
|
|
124864
124947
|
error: err instanceof Error ? err.message : String(err),
|
|
124865
124948
|
memories: [],
|
|
124866
|
-
count: 0
|
|
124949
|
+
count: 0,
|
|
124950
|
+
nextCursor: null
|
|
124867
124951
|
};
|
|
124868
124952
|
}
|
|
124869
124953
|
}
|
|
@@ -125507,7 +125591,8 @@ var ReportErrorReasonSchema = _enum([
|
|
|
125507
125591
|
"blocked",
|
|
125508
125592
|
"other"
|
|
125509
125593
|
]);
|
|
125510
|
-
function createReportErrorTool(onError) {
|
|
125594
|
+
function createReportErrorTool(onError, findingPolicy = "native") {
|
|
125595
|
+
const vulnerabilityGuidance = findingPolicy === "external" ? "Do NOT use this for vulnerabilities (include them in your final response)" : "Do NOT use this for vulnerabilities (use document_vulnerability)";
|
|
125511
125596
|
return tool({
|
|
125512
125597
|
description: `Report a blocking error that prevents you from completing the pentest, and END your run.
|
|
125513
125598
|
|
|
@@ -125516,7 +125601,7 @@ Call this ONLY when you genuinely cannot continue, for example:
|
|
|
125516
125601
|
- The target is unreachable or responds in a way that makes testing impossible.
|
|
125517
125602
|
- Some other runtime condition blocks you from carrying out the objectives.
|
|
125518
125603
|
|
|
125519
|
-
|
|
125604
|
+
${vulnerabilityGuidance} or for normal completion (use response). Provide a clear, specific message describing exactly what blocked you — include the failing URL, status codes, or the auth step that failed where relevant — so it can be surfaced to the operator.`,
|
|
125520
125605
|
inputSchema: object({
|
|
125521
125606
|
reason: ReportErrorReasonSchema.describe("Coarse category of the blocking error."),
|
|
125522
125607
|
message: string().min(1).describe("Clear, specific explanation of what blocked you (the failing URL, status codes, or auth step where relevant).")
|
|
@@ -125600,6 +125685,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
|
|
|
125600
125685
|
attackSurfaceRegistry: ctx.attackSurfaceRegistry
|
|
125601
125686
|
},
|
|
125602
125687
|
runtime: {
|
|
125688
|
+
findingPolicy: ctx.findingPolicy,
|
|
125603
125689
|
session: ctx.session,
|
|
125604
125690
|
model: ctx.model,
|
|
125605
125691
|
authConfig: ctx.authConfig,
|
|
@@ -125652,6 +125738,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
|
|
|
125652
125738
|
attackSurfaceRegistry: ctx.attackSurfaceRegistry
|
|
125653
125739
|
},
|
|
125654
125740
|
runtime: {
|
|
125741
|
+
findingPolicy: ctx.findingPolicy,
|
|
125655
125742
|
session: ctx.session,
|
|
125656
125743
|
model: ctx.model,
|
|
125657
125744
|
authConfig: ctx.authConfig,
|
|
@@ -125849,13 +125936,14 @@ ${output.stderr}` : "");
|
|
|
125849
125936
|
init_dist();
|
|
125850
125937
|
init_zod();
|
|
125851
125938
|
function runPentestWorkflow(ctx) {
|
|
125939
|
+
const resultStep = ctx.findingPolicy === "external" ? "3. Return evidence-backed findings for the caller's evaluation" : "3. Aggregate findings and generate the final report";
|
|
125852
125940
|
return tool({
|
|
125853
125941
|
description: `Run the full autonomous penetration test pipeline against a target.
|
|
125854
125942
|
|
|
125855
125943
|
This single tool call executes the entire pentest workflow:
|
|
125856
125944
|
1. Attack surface discovery (blackbox or whitebox)
|
|
125857
125945
|
2. Spawn a swarm of targeted pentest agents
|
|
125858
|
-
|
|
125946
|
+
${resultStep}
|
|
125859
125947
|
|
|
125860
125948
|
Use this when you want to run a complete, end-to-end pentest. The workflow
|
|
125861
125949
|
handles session creation, concurrency, persistence, and reporting automatically.
|
|
@@ -125868,7 +125956,7 @@ Omit \`cwd\` for blackbox mode (live target probing only).`,
|
|
|
125868
125956
|
toolCallDescription: string().describe("A concise, human-readable description of what this tool call is doing")
|
|
125869
125957
|
}),
|
|
125870
125958
|
execute: async ({ target, cwd }) => {
|
|
125871
|
-
const { runPentestWorkflow: workflow } = await import("./pentest-
|
|
125959
|
+
const { runPentestWorkflow: workflow } = await import("./pentest-t0p4nw2a.js");
|
|
125872
125960
|
if (!ctx.model) {
|
|
125873
125961
|
return {
|
|
125874
125962
|
success: false,
|
|
@@ -125878,6 +125966,7 @@ Omit \`cwd\` for blackbox mode (live target probing only).`,
|
|
|
125878
125966
|
const startedAt = Date.now();
|
|
125879
125967
|
try {
|
|
125880
125968
|
const result = await workflow({
|
|
125969
|
+
findingPolicy: ctx.findingPolicy,
|
|
125881
125970
|
target,
|
|
125882
125971
|
cwd,
|
|
125883
125972
|
model: ctx.model,
|
|
@@ -125890,6 +125979,7 @@ Omit \`cwd\` for blackbox mode (live target probing only).`,
|
|
|
125890
125979
|
openAIReasoningEffort: ctx.openAIReasoningEffort,
|
|
125891
125980
|
surfaceIntegrationEnabled: ctx.surfaceIntegrationEnabled,
|
|
125892
125981
|
hooks: {
|
|
125982
|
+
findingPolicy: ctx.findingPolicy,
|
|
125893
125983
|
backends: ctx.backends,
|
|
125894
125984
|
subagentSpawner: ctx.subagentSpawner,
|
|
125895
125985
|
languageModelMiddleware: ctx.languageModelMiddleware,
|
|
@@ -125903,6 +125993,17 @@ Omit \`cwd\` for blackbox mode (live target probing only).`,
|
|
|
125903
125993
|
const elapsedSeconds = Math.round((Date.now() - startedAt) / 1000);
|
|
125904
125994
|
const minutes = Math.floor(elapsedSeconds / 60);
|
|
125905
125995
|
const seconds = elapsedSeconds % 60;
|
|
125996
|
+
if (ctx.findingPolicy === "external") {
|
|
125997
|
+
const reportedFindings = result.reportedFindings ?? [];
|
|
125998
|
+
return {
|
|
125999
|
+
success: true,
|
|
126000
|
+
totalFindings: reportedFindings.length,
|
|
126001
|
+
reportedFindings,
|
|
126002
|
+
objectiveResults: result.objectiveResults ?? [],
|
|
126003
|
+
duration: `${minutes}m ${seconds}s`,
|
|
126004
|
+
message: `Pentest complete. ${reportedFindings.length} finding(s) returned for external evaluation.`
|
|
126005
|
+
};
|
|
126006
|
+
}
|
|
125906
126007
|
return {
|
|
125907
126008
|
success: true,
|
|
125908
126009
|
totalFindings: result.findings.length,
|
|
@@ -125949,13 +126050,14 @@ var ScanKindSchema = _enum([
|
|
|
125949
126050
|
"fuzzing"
|
|
125950
126051
|
]);
|
|
125951
126052
|
function runWhiteboxScan(ctx) {
|
|
126053
|
+
const verificationGuidance = ctx.findingPolicy === "external" ? "as recoverable conditions. Static results are candidates only; assess them against the caller's evidence requirements." : `as recoverable conditions. Static results are candidates only; verify before
|
|
126054
|
+
calling document_vulnerability.`;
|
|
125952
126055
|
return tool({
|
|
125953
126056
|
description: `Run installed whitebox security scanners with bounded output.
|
|
125954
126057
|
|
|
125955
126058
|
The tool detects applicable scanner adapters for the repository and normalizes
|
|
125956
126059
|
results into concise summaries plus artifact paths. Missing tools are reported
|
|
125957
|
-
|
|
125958
|
-
calling document_vulnerability.`,
|
|
126060
|
+
${verificationGuidance}`,
|
|
125959
126061
|
inputSchema: object({
|
|
125960
126062
|
path: string().optional().describe("Repository root to scan; must stay under the configured codebase root."),
|
|
125961
126063
|
kind: ScanKindSchema.optional().describe("Restrict scan family"),
|
|
@@ -126241,6 +126343,7 @@ async function runSingleCodingAgent(ctx, spawner, codebasePath, objective, _agen
|
|
|
126241
126343
|
const result = await spawner.spawn({
|
|
126242
126344
|
spec: { type: "code", codebasePath, objective },
|
|
126243
126345
|
runtime: {
|
|
126346
|
+
findingPolicy: ctx.findingPolicy,
|
|
126244
126347
|
session: ctx.session,
|
|
126245
126348
|
model: ctx.model,
|
|
126246
126349
|
authConfig: ctx.authConfig,
|
|
@@ -126282,6 +126385,14 @@ init_zod();
|
|
|
126282
126385
|
var WORKER_DRAIN_GRACE_MS = 30000;
|
|
126283
126386
|
var ORIGIN_AUTH_FAILURE_GUIDANCE = `A 401/403 from one resource does not by itself prove authentication failure. Verify the session against a known protected or session endpoint and re-authenticate on the assigned origin only if needed. Call report_error with reason "authentication_failed" only if required authentication cannot be established and this blocks the assigned objective or all further testing; otherwise continue any reachable testing.`;
|
|
126284
126387
|
function spawnPentestAgent(ctx) {
|
|
126388
|
+
const externalFindings = ctx.findingPolicy === "external";
|
|
126389
|
+
const findingSteps = externalFindings ? `2. Reports concise evidence-backed findings in its response
|
|
126390
|
+
3. Leaves acceptance to the caller's external evaluator` : `2. Confirms vulnerabilities with POC scripts
|
|
126391
|
+
3. Documents findings to the shared findings registry only when the exploit path and material security impact are proven`;
|
|
126392
|
+
const findingGuidance = externalFindings ? "False-positive discipline: report a security weakness only when observations support a material abuse path. Include the affected target, evidence, and impact; do not add a separate in-run finding review." : "False-positive discipline: workers should not call document_vulnerability for public/unauthenticated behavior, missing best-practice controls, generic errors, local HTTP deployment context, or other low-signal observations unless they prove a material abuse path such as non-public data access, credentialed cross-origin abuse, state change, denial of service, account takeover, or another concrete exploit chain.";
|
|
126393
|
+
const returnGuidance = externalFindings ? "Returns the worker's summary, objective results, and reported findings so the parent can investigate chains." : "Returns the worker's summary, objective results, and finding count — but NOT the findings themselves (those land in the shared registry).";
|
|
126394
|
+
const exploratoryGuidance = externalFindings ? "Spawn a follow-up exploratory worker only when the assigned objective requires broader coverage or a credible untested lead remains. For detection-only work, finish once the requested evidence is sufficient." : 'After fanning out one worker per objective, call this tool ONE MORE TIME for a final "exploratory" worker. Pass it the URLs of any suspicious behaviors discovered by earlier workers and ask it to chain findings together and probe for additional, unspecified vulnerabilities.';
|
|
126395
|
+
const objectiveGuidance = externalFindings ? "Pass one focused objective per worker. A follow-up objective may cover a concrete chain or untested lead when the assignment calls for it." : "For per-objective fan-out, pass exactly one objective. For the final exploratory pass, pass a single composite objective describing chaining + exploration.";
|
|
126285
126396
|
const targetScopeGuidance = ctx.systemScope && ctx.systemScope.memberHosts.length > 0 ? `For a cross-service follow-up, you may instead use a full URL on one of these authorized System Scope members: ${ctx.systemScope.memberHosts.join(", ")}.` : "No structured System Scope is present, so keep the assigned host unchanged.";
|
|
126286
126397
|
return tool({
|
|
126287
126398
|
description: `Spawn a single focused pentest sub-agent (worker) to test ONE objective at a time.
|
|
@@ -126294,22 +126405,21 @@ Authentication state is origin-specific. Before spawning a cross-service worker
|
|
|
126294
126405
|
|
|
126295
126406
|
Each spawn produces an independent TargetedPentestAgent that:
|
|
126296
126407
|
1. Tests the assigned objective(s) deeply (execute_command, http_request, browser tools)
|
|
126297
|
-
|
|
126298
|
-
3. Documents findings to the shared findings registry only when the exploit path and material security impact are proven
|
|
126408
|
+
${findingSteps}
|
|
126299
126409
|
|
|
126300
126410
|
Cloned browser session — the worker gets its OWN isolated Chromium instance, but it is seeded at spawn time with a snapshot of your current cookies and localStorage. If you've already authenticated in your browser (or recon set up useful state), the worker starts already authenticated for the same origins. Critically, the worker's browser is a COPY: its navigations, form fills, \`localStorage.setItem\`, alerts, and any other browser-side mutations stay inside the worker's own browser and do NOT leak back to you or to sibling workers. If you want state to be visible to the next worker, set it up in YOUR browser before spawning.
|
|
126301
126411
|
|
|
126302
126412
|
The worker has no further spawn capability — it cannot recursively spawn other pentest agents.
|
|
126303
126413
|
|
|
126304
|
-
|
|
126414
|
+
${exploratoryGuidance}
|
|
126305
126415
|
|
|
126306
|
-
|
|
126416
|
+
${findingGuidance}
|
|
126307
126417
|
|
|
126308
|
-
|
|
126418
|
+
${returnGuidance}`,
|
|
126309
126419
|
inputSchema: object({
|
|
126310
126420
|
name: string().describe("Short human-readable label for this sub-agent shown in the UI (e.g. 'SQLi /api/users', 'IDOR orders', 'Final chain & explore')."),
|
|
126311
126421
|
target: string().describe(`Full target URL INCLUDING the endpoint path you want this worker to focus on (e.g. 'https://example.com/api/users/{id}', 'https://example.com/login'). Use the orchestrator's assigned URL by default and never strip it to a bare domain. A recon-supported sibling endpoint is allowed when it belongs to the objective. ${targetScopeGuidance} Never invent a host or endpoint.`),
|
|
126312
|
-
objectives: array(string()).min(1).describe(
|
|
126422
|
+
objectives: array(string()).min(1).describe(`Testing objectives for this worker. ${objectiveGuidance}`),
|
|
126313
126423
|
context: string().optional().describe("Additional grounding context for the worker — e.g. summaries of what earlier workers found, suspicious endpoints to chain, or application-specific guidance. Treated as guidance, not as code to read."),
|
|
126314
126424
|
toolCallDescription: string().describe("Concise, human-readable description of what this spawn is doing (shown in the UI).")
|
|
126315
126425
|
}),
|
|
@@ -126345,7 +126455,7 @@ Returns the worker's summary, objective results, and finding count — but NOT t
|
|
|
126345
126455
|
const spawner = ctx.subagentSpawner;
|
|
126346
126456
|
let subagentId = "";
|
|
126347
126457
|
try {
|
|
126348
|
-
const { findings, objectiveResults } = await spawner.spawn({
|
|
126458
|
+
const { findings, reportedFindings, objectiveResults } = await spawner.spawn({
|
|
126349
126459
|
spec: {
|
|
126350
126460
|
type: "pentest",
|
|
126351
126461
|
target,
|
|
@@ -126358,6 +126468,7 @@ Returns the worker's summary, objective results, and finding count — but NOT t
|
|
|
126358
126468
|
browserSession: sharedBrowserSession
|
|
126359
126469
|
},
|
|
126360
126470
|
runtime: {
|
|
126471
|
+
findingPolicy: ctx.findingPolicy,
|
|
126361
126472
|
session: ctx.session,
|
|
126362
126473
|
model: ctx.model,
|
|
126363
126474
|
authConfig: ctx.authConfig,
|
|
@@ -126390,9 +126501,10 @@ Returns the worker's summary, objective results, and finding count — but NOT t
|
|
|
126390
126501
|
return {
|
|
126391
126502
|
success: true,
|
|
126392
126503
|
subagentId,
|
|
126393
|
-
findingsCount: findings.length,
|
|
126504
|
+
findingsCount: externalFindings ? reportedFindings?.length ?? 0 : findings.length,
|
|
126505
|
+
...externalFindings ? { reportedFindings: reportedFindings ?? [] } : {},
|
|
126394
126506
|
objectiveResults,
|
|
126395
|
-
message: `Worker '${name}' complete. Documented ${findings.length} finding(s).`
|
|
126507
|
+
message: externalFindings ? `Worker '${name}' complete. Reported ${reportedFindings?.length ?? 0} finding(s) for external evaluation.` : `Worker '${name}' complete. Documented ${findings.length} finding(s).`
|
|
126396
126508
|
};
|
|
126397
126509
|
} catch (error) {
|
|
126398
126510
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -126432,15 +126544,19 @@ init_structured();
|
|
|
126432
126544
|
init_lazyLogger();
|
|
126433
126545
|
var log8 = scopedLogger(() => createLogger("spawn-pentest-swarm"));
|
|
126434
126546
|
function spawnPentestSwarm(ctx) {
|
|
126547
|
+
const externalFindings = ctx.findingPolicy === "external";
|
|
126548
|
+
const findingSteps = externalFindings ? `2. Surface concise evidence-backed findings in its response
|
|
126549
|
+
3. Leave finding acceptance to the caller's evaluator` : `2. Create POC scripts for confirmed vulnerabilities
|
|
126550
|
+
3. Document findings with evidence and remediation`;
|
|
126551
|
+
const findingDestination = externalFindings ? "Reported findings are returned to this caller; no native finding review runs." : "All findings are written to the shared session directory.";
|
|
126435
126552
|
return tool({
|
|
126436
126553
|
description: `Launch a swarm of targeted pentest sub-agents to test multiple targets in parallel.
|
|
126437
126554
|
|
|
126438
126555
|
Call this AFTER completing attack surface discovery. Each entry in 'targets' spawns an independent TargetedPentestAgent that will:
|
|
126439
126556
|
1. Test the specified target for the given objectives
|
|
126440
|
-
|
|
126441
|
-
3. Document findings with evidence and remediation
|
|
126557
|
+
${findingSteps}
|
|
126442
126558
|
|
|
126443
|
-
|
|
126559
|
+
${findingDestination}
|
|
126444
126560
|
|
|
126445
126561
|
Pass every target you want tested — the swarm handles concurrency automatically.`,
|
|
126446
126562
|
inputSchema: object({
|
|
@@ -126453,7 +126569,7 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
126453
126569
|
toolCallDescription: string().describe("A concise, human-readable description of what this tool call is doing")
|
|
126454
126570
|
}),
|
|
126455
126571
|
execute: async ({ targets }) => {
|
|
126456
|
-
const { runPentestSwarm, DEFAULT_CONCURRENCY } = await import("./pentest-
|
|
126572
|
+
const { runPentestSwarm, DEFAULT_CONCURRENCY } = await import("./pentest-t0p4nw2a.js");
|
|
126457
126573
|
if (!ctx.model) {
|
|
126458
126574
|
return {
|
|
126459
126575
|
success: false,
|
|
@@ -126469,6 +126585,7 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
126469
126585
|
const total = targets.length;
|
|
126470
126586
|
log8.info(`Spawning pentest swarm: ${total} agents (concurrency: ${DEFAULT_CONCURRENCY})`);
|
|
126471
126587
|
const swarmResults = await runPentestSwarm({
|
|
126588
|
+
findingPolicy: ctx.findingPolicy,
|
|
126472
126589
|
targets,
|
|
126473
126590
|
model: ctx.model,
|
|
126474
126591
|
session: ctx.session,
|
|
@@ -126484,6 +126601,7 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
126484
126601
|
openAIReasoningEffort: ctx.openAIReasoningEffort,
|
|
126485
126602
|
display: ctx.display,
|
|
126486
126603
|
hooks: {
|
|
126604
|
+
findingPolicy: ctx.findingPolicy,
|
|
126487
126605
|
backends: ctx.backends,
|
|
126488
126606
|
subagentSpawner: ctx.subagentSpawner,
|
|
126489
126607
|
languageModelMiddleware: ctx.languageModelMiddleware,
|
|
@@ -126494,7 +126612,7 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
126494
126612
|
sandbox: ctx.sandbox
|
|
126495
126613
|
}
|
|
126496
126614
|
});
|
|
126497
|
-
const totalFindings = swarmResults.reduce((sum, r) => sum + (r?.findings.length ?? 0), 0);
|
|
126615
|
+
const totalFindings = swarmResults.reduce((sum, r) => sum + (externalFindings ? r?.reportedFindings?.length ?? 0 : r?.findings.length ?? 0), 0);
|
|
126498
126616
|
const failedCount = swarmResults.filter((r) => r == null).length;
|
|
126499
126617
|
return {
|
|
126500
126618
|
success: true,
|
|
@@ -126503,7 +126621,11 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
126503
126621
|
failedTargets: failedCount,
|
|
126504
126622
|
results: targets.map((t, i) => ({
|
|
126505
126623
|
target: t.target,
|
|
126506
|
-
findingsCount: swarmResults[i]?.findings.length ?? 0,
|
|
126624
|
+
findingsCount: externalFindings ? swarmResults[i]?.reportedFindings?.length ?? 0 : swarmResults[i]?.findings.length ?? 0,
|
|
126625
|
+
...externalFindings ? {
|
|
126626
|
+
reportedFindings: swarmResults[i]?.reportedFindings ?? [],
|
|
126627
|
+
objectiveResults: swarmResults[i]?.objectiveResults ?? []
|
|
126628
|
+
} : {},
|
|
126507
126629
|
error: swarmResults[i] == null ? "Agent failed" : undefined
|
|
126508
126630
|
})),
|
|
126509
126631
|
message: `Swarm complete. ${totalFindings} findings across ${total} targets. ${failedCount > 0 ? `${failedCount} targets failed.` : "All targets tested successfully."}`
|
|
@@ -126758,12 +126880,13 @@ var updateTaskInputSchema = object({
|
|
|
126758
126880
|
observation: string().optional().describe("Intermediate observations or notes from testing")
|
|
126759
126881
|
});
|
|
126760
126882
|
function updateTask2(ctx) {
|
|
126883
|
+
const completedGuidance = ctx.findingPolicy === "external" ? "vulnerability identified with supporting evidence, OR conclusively determined the endpoint is not vulnerable / materiality is not met for this technique." : "vulnerability found and documented via document_vulnerability, OR conclusively determined the endpoint is not vulnerable / materiality is not met for this technique. Documentation is NOT required to complete a non-vulnerable task.";
|
|
126761
126884
|
return tool({
|
|
126762
126885
|
description: `Update a task's status and record results.
|
|
126763
126886
|
|
|
126764
126887
|
Status transitions:
|
|
126765
126888
|
- "in_progress" — Set when you START testing a task. Pick one pending task at a time.
|
|
126766
|
-
- "completed" — Set when testing is done:
|
|
126889
|
+
- "completed" — Set when testing is done: ${completedGuidance}
|
|
126767
126890
|
- "failed" — Set when the technique didn't work: rate limited, blocked by WAF, dead end, or approach not applicable. Then create a NEW task with an alternative technique.
|
|
126768
126891
|
|
|
126769
126892
|
Always include a result or observation explaining the outcome.`,
|
|
@@ -127115,12 +127238,13 @@ var CandidateStateSchema = _enum([
|
|
|
127115
127238
|
"deferred"
|
|
127116
127239
|
]);
|
|
127117
127240
|
function createWhiteboxCandidate2(ctx) {
|
|
127241
|
+
const candidateGuidance = ctx.findingPolicy === "external" ? "for the caller's final evaluation. Candidates keep hypotheses, source-to-sink traces, scanner artifacts, fuzzing logs, and verification status separate from reported findings." : `for document_vulnerability. Candidates keep hypotheses, source-to-sink traces,
|
|
127242
|
+
scanner artifacts, fuzzing logs, and verification status out of official findings.`;
|
|
127118
127243
|
return tool({
|
|
127119
127244
|
description: `Create a whitebox vulnerability candidate.
|
|
127120
127245
|
|
|
127121
127246
|
Use this for plausible source-code findings that are not yet confirmed enough
|
|
127122
|
-
|
|
127123
|
-
scanner artifacts, fuzzing logs, and verification status out of official findings.`,
|
|
127247
|
+
${candidateGuidance}`,
|
|
127124
127248
|
inputSchema: object({
|
|
127125
127249
|
title: string(),
|
|
127126
127250
|
vulnerabilityClass: string(),
|
|
@@ -127147,7 +127271,7 @@ scanner artifacts, fuzzing logs, and verification status out of official finding
|
|
|
127147
127271
|
artifactPaths: candidate.artifacts.map((artifact) => artifact.path),
|
|
127148
127272
|
nextActions: [
|
|
127149
127273
|
"Move candidate to investigating after reading source context.",
|
|
127150
|
-
"Attempt a reproducer or dynamic verification before document_vulnerability."
|
|
127274
|
+
ctx.findingPolicy === "external" ? "Gather the evidence required by the caller before reporting this candidate." : "Attempt a reproducer or dynamic verification before document_vulnerability."
|
|
127151
127275
|
],
|
|
127152
127276
|
truncated: false
|
|
127153
127277
|
};
|
|
@@ -127191,7 +127315,7 @@ State machine: hypothesis -> investigating -> repro_attempted -> confirmed (requ
|
|
|
127191
127315
|
data: { candidate },
|
|
127192
127316
|
artifactPaths: candidate.artifacts.map((artifact) => artifact.path),
|
|
127193
127317
|
nextActions: candidate.state === "confirmed" ? [
|
|
127194
|
-
"Use document_vulnerability only if the proof demonstrates exploitability."
|
|
127318
|
+
ctx.findingPolicy === "external" ? "Report only the evidence-backed conclusion to the caller." : "Use document_vulnerability only if the proof demonstrates exploitability."
|
|
127195
127319
|
] : [
|
|
127196
127320
|
"Continue tracing or verification based on the candidate state."
|
|
127197
127321
|
],
|
|
@@ -128662,6 +128786,7 @@ class OffensiveSecurityAgent {
|
|
|
128662
128786
|
const tasksDir = input.tasksDir ?? (taskDriven ? input.subagentId ? join28(input.session.rootPath, "subagents", `${input.subagentId}-tasks`) : join28(input.session.rootPath, "tasks") : undefined);
|
|
128663
128787
|
const credentialManager = input.credentialManager ?? input.session.credentialManager;
|
|
128664
128788
|
const toolCtx = {
|
|
128789
|
+
findingPolicy: input.findingPolicy,
|
|
128665
128790
|
...input.attackSurfaceArtifactsPath ? { attackSurfaceArtifactsPath: input.attackSurfaceArtifactsPath } : {},
|
|
128666
128791
|
session: input.session,
|
|
128667
128792
|
agentCwd,
|
|
@@ -128738,9 +128863,13 @@ class OffensiveSecurityAgent {
|
|
|
128738
128863
|
activeTools = [...activeTools, RESPONSE_TOOL_NAME];
|
|
128739
128864
|
}
|
|
128740
128865
|
}
|
|
128866
|
+
if (input.findingPolicy === "external") {
|
|
128867
|
+
activeTools = activeTools.filter((name) => name !== "document_vulnerability");
|
|
128868
|
+
}
|
|
128741
128869
|
activeTools = filterWorkspaceToolsForRun(activeTools, input.prompt, input.approvalGate !== undefined);
|
|
128742
128870
|
const builtinTools = createToolsForNames(toolCtx, activeTools);
|
|
128743
|
-
|
|
128871
|
+
const extraTools = input.findingPolicy === "external" && input.extraTools ? Object.fromEntries(Object.entries(input.extraTools).filter(([name]) => name !== "document_vulnerability")) : input.extraTools;
|
|
128872
|
+
let tools = extraTools ? { ...builtinTools, ...extraTools } : { ...builtinTools };
|
|
128744
128873
|
if (input.toolExecutionRecorder) {
|
|
128745
128874
|
tools = wrapRecordedTools(tools, input.toolExecutionRecorder);
|
|
128746
128875
|
}
|
|
@@ -128765,7 +128894,7 @@ class OffensiveSecurityAgent {
|
|
|
128765
128894
|
get: () => Promise.race([sr.response, this._drainRejection])
|
|
128766
128895
|
}
|
|
128767
128896
|
});
|
|
128768
|
-
return customResolve(guarded);
|
|
128897
|
+
return customResolve(guarded, result);
|
|
128769
128898
|
}).then((resolved) => {
|
|
128770
128899
|
this._capturedResponse = resolved;
|
|
128771
128900
|
this._resolveResponseCaptured(resolved);
|
|
@@ -128803,13 +128932,27 @@ class OffensiveSecurityAgent {
|
|
|
128803
128932
|
mkdirSync10(messagesDir, { recursive: true });
|
|
128804
128933
|
}
|
|
128805
128934
|
this.messagesPath = join28(messagesDir, "messages.json");
|
|
128806
|
-
const
|
|
128807
|
-
current:
|
|
128808
|
-
|
|
128809
|
-
|
|
128810
|
-
|
|
128811
|
-
|
|
128812
|
-
|
|
128935
|
+
const preparedContextRef = {
|
|
128936
|
+
current: {
|
|
128937
|
+
messages: input.messages ? [...input.messages] : [
|
|
128938
|
+
{
|
|
128939
|
+
role: "user",
|
|
128940
|
+
content: [{ type: "text", text: input.prompt }]
|
|
128941
|
+
}
|
|
128942
|
+
],
|
|
128943
|
+
responseMessageOffset: 0
|
|
128944
|
+
}
|
|
128945
|
+
};
|
|
128946
|
+
const legacyMessages = (responseMessages) => [
|
|
128947
|
+
...preparedContextRef.current.messages,
|
|
128948
|
+
...responseMessages.slice(preparedContextRef.current.responseMessageOffset)
|
|
128949
|
+
];
|
|
128950
|
+
const persistedMessages = (messages) => {
|
|
128951
|
+
let first = 0;
|
|
128952
|
+
while (messages[first]?.role === "system" && messages[first]?.providerOptions) {
|
|
128953
|
+
first++;
|
|
128954
|
+
}
|
|
128955
|
+
return first === 0 ? messages : messages.slice(first);
|
|
128813
128956
|
};
|
|
128814
128957
|
this.writer = new AgentMessageWriter({ messagesPath: this.messagesPath });
|
|
128815
128958
|
this.finalizeInterruptedStep = createInterruptedStepFinalizer({
|
|
@@ -128823,10 +128966,11 @@ class OffensiveSecurityAgent {
|
|
|
128823
128966
|
});
|
|
128824
128967
|
const schedulePersist = () => this.writer.schedulePersist();
|
|
128825
128968
|
const baseSystemPrompt = input.system ?? buildBaseSystemPrompt({
|
|
128826
|
-
sandboxMode: agentCwd === input.session.rootPath
|
|
128969
|
+
sandboxMode: agentCwd === input.session.rootPath,
|
|
128970
|
+
findingPolicy: input.findingPolicy
|
|
128827
128971
|
});
|
|
128828
128972
|
const commandPlatform = resolveCommandPlatform(toolCtx);
|
|
128829
|
-
const workspaceSection = buildSessionWorkspaceSection(input.session, agentCwd, activeTools, fileWorkspaceRoot);
|
|
128973
|
+
const workspaceSection = buildSessionWorkspaceSection(input.session, agentCwd, activeTools, fileWorkspaceRoot, input.findingPolicy);
|
|
128830
128974
|
const bundledAssets = input.backends || input.sandbox ? null : buildBundledAssetsSection();
|
|
128831
128975
|
const assembleBaseSystemPrompt = (facts) => {
|
|
128832
128976
|
const sections = [baseSystemPrompt];
|
|
@@ -128863,6 +129007,12 @@ class OffensiveSecurityAgent {
|
|
|
128863
129007
|
usageRecorder: input.usageRecorder,
|
|
128864
129008
|
contextRecorder: input.contextRecorder,
|
|
128865
129009
|
inferenceRecorder: input.inferenceRecorder,
|
|
129010
|
+
onContextPrepared: (context) => {
|
|
129011
|
+
preparedContextRef.current = {
|
|
129012
|
+
messages: [...context.messages],
|
|
129013
|
+
responseMessageOffset: context.responseMessageOffset
|
|
129014
|
+
};
|
|
129015
|
+
},
|
|
128866
129016
|
sessionPath: messagesDir,
|
|
128867
129017
|
sessionId: this.busSessionId,
|
|
128868
129018
|
onStepFinish: async (event) => {
|
|
@@ -128873,11 +129023,8 @@ class OffensiveSecurityAgent {
|
|
|
128873
129023
|
await input.onStepFinish?.(event);
|
|
128874
129024
|
return;
|
|
128875
129025
|
}
|
|
128876
|
-
const canonical = input.contextRecorder?.latest() ??
|
|
128877
|
-
|
|
128878
|
-
...event.response.messages
|
|
128879
|
-
];
|
|
128880
|
-
this.writer.setLatest(canonical);
|
|
129026
|
+
const canonical = input.contextRecorder?.latest() ?? legacyMessages(event.response.messages);
|
|
129027
|
+
this.writer.setLatest(persistedMessages(canonical));
|
|
128881
129028
|
schedulePersist();
|
|
128882
129029
|
traceWriter.recordStep(event.response.messages, stepUsage);
|
|
128883
129030
|
this.eventBus.emit("step-finish", {
|
|
@@ -128890,16 +129037,16 @@ class OffensiveSecurityAgent {
|
|
|
128890
129037
|
await input.onStepFinish?.(event);
|
|
128891
129038
|
},
|
|
128892
129039
|
onSummarized: () => {
|
|
128893
|
-
|
|
129040
|
+
preparedContextRef.current = {
|
|
129041
|
+
messages: [],
|
|
129042
|
+
responseMessageOffset: 0
|
|
129043
|
+
};
|
|
128894
129044
|
traceWriter.markSummarized();
|
|
128895
129045
|
},
|
|
128896
129046
|
onFinish: async (event) => {
|
|
128897
129047
|
this.writer.cancelTimer();
|
|
128898
129048
|
if (!this.writer.syntheticsPersisted) {
|
|
128899
|
-
const finalMessages = input.contextRecorder?.latest() ?? this.writer.latest ??
|
|
128900
|
-
...initialMessagesRef.current,
|
|
128901
|
-
...event.response.messages
|
|
128902
|
-
];
|
|
129049
|
+
const finalMessages = persistedMessages(input.contextRecorder?.latest() ?? this.writer.latest ?? legacyMessages(event.response.messages));
|
|
128903
129050
|
this.writer.setLatest(finalMessages);
|
|
128904
129051
|
await this.writer.enqueueWrite(finalMessages).catch(() => {});
|
|
128905
129052
|
}
|