@pensar/apex 2.4.0 → 2.5.0-canary.41357c27
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-nhs1w5w0.js → agent-092hrrbn.js} +11 -10
- package/build/{agent-5ejt5vpz.js → agent-jgdfbwse.js} +9 -8
- package/build/agent-z3ydv420.js +20 -0
- package/build/{apps-17wvz1d7.js → apps-pxwa5s9f.js} +72 -31
- package/build/{auth-z3h9859n.js → auth-j34f09ke.js} +25 -20
- package/build/authentication-jt9fq8y9.js +20 -0
- package/build/blackboxAgent-vwtk3hv1.js +20 -0
- package/build/blackboxPentest-nzn4xjd4.js +70 -0
- package/build/{cli-vnynf0js.js → cli-13vsx08y.js} +10 -4
- package/build/{cli-mavved45.js → cli-1e69fd35.js} +46 -25
- package/build/cli-53rm0rrz.js +15 -0
- package/build/cli-68260ckj.js +12136 -0
- package/build/{cli-tkc598ey.js → cli-70banr6y.js} +411 -280
- package/build/{cli-xshasbwe.js → cli-7hqdp86d.js} +34 -4
- package/build/cli-7q3ae3ft.js +6 -0
- package/build/cli-9pbk8m32.js +32 -0
- package/build/{cli-tznv8pf1.js → cli-9y49bzhd.js} +1 -1
- package/build/{cli-swpbx60z.js → cli-avmhkjtv.js} +1 -1481
- package/build/{cli-9rhzhgx2.js → cli-epqtwyeb.js} +1 -1
- package/build/cli-knd276ed.js +1485 -0
- package/build/{cli-repbyhkk.js → cli-mjd75xw4.js} +1129 -525
- package/build/{cli-5k33webc.js → cli-mtavwpav.js} +45 -43
- package/build/{cli-0n4r54hq.js → cli-naapss75.js} +1 -1
- package/build/{cli-gq40s5b3.js → cli-pd9j03q2.js} +5 -3
- package/build/{cli-qqt4gj1w.js → cli-pepts4ha.js} +5 -3
- package/build/{cli-32z0017y.js → cli-q2sq1qkn.js} +2 -2
- package/build/{cli-72cvcqhg.js → cli-x4e10v99.js} +1 -1
- package/build/{cli-2cbwdk78.js → cli-xan180ab.js} +1 -1
- package/build/{cli-vq52kp7j.js → cli-xp52xsqm.js} +23 -5
- package/build/{cli-k8kc47pq.js → cli-ygesx0vf.js} +3 -3
- package/build/{cli-b1adytsy.js → cli-yzhjh7x1.js} +28 -5
- package/build/cli.js +641 -95
- package/build/{config-f1mj4nhd.js → config-v87zm6cx.js} +18 -15
- package/build/{doctor-ekneewa3.js → doctor-705xb28k.js} +8 -7
- package/build/{fastStrike-8zka43xs.js → fastStrike-wp2tvcnq.js} +13 -10
- package/build/{fixes-b89s5haw.js → fixes-x8y42dh5.js} +25 -20
- package/build/getMachineId-bsd-xj3bn2fv.js +36 -0
- package/build/getMachineId-darwin-07jzjcx6.js +36 -0
- package/build/getMachineId-linux-ahngynxd.js +29 -0
- package/build/getMachineId-unsupported-vy43b44z.js +19 -0
- package/build/getMachineId-win-8x66cynz.js +38 -0
- package/build/{index-mtq7kmxz.js → index-5wh7gq37.js} +4 -2
- package/build/{index-sf16jm0m.js → index-6f06c8v0.js} +9 -7
- package/build/{index-hqjdg6fg.js → index-g0fvrp9n.js} +17 -9
- package/build/{index-y5w6n3tb.js → index-hdzja756.js} +2 -2
- package/build/{index-4ad3sdwk.js → index-q1hh6p80.js} +4 -4
- package/build/{index-ghwf5z3v.js → index-qpmdq6vj.js} +3 -3
- package/build/{index-6d22pyxt.js → index-sfwny7gx.js} +1756 -1213
- package/build/{index-rbzhk712.js → index-sx52n7s9.js} +11 -10
- package/build/{issues-xx5bs4md.js → issues-1g7j8ktr.js} +82 -26
- package/build/{logs-qtxe51w2.js → logs-6rjwnwz7.js} +25 -20
- package/build/{offesecAgent-b9e2xm6v.js → offesecAgent-frnz6ngh.js} +10 -9
- package/build/pentest-3w1jgsg7.js +30 -0
- package/build/{pentests-6ks3szc4.js → pentests-wxacefk4.js} +26 -21
- package/build/{targetedPentest-s1ptvq8e.js → targetedPentest-w1dze9hg.js} +11 -10
- package/build/{targets-sxygyj87.js → targets-vhxkvbmg.js} +27 -22
- package/build/threatModel-2k259rx1.js +29 -0
- package/build/{uninstall-tvsh81v8.js → uninstall-j8dmsaz5.js} +6 -3
- package/build/{upload-7wdyyqmr.js → upload-7pz6yt0n.js} +8 -7
- package/build/{utils-7fwdkqk6.js → utils-2gvfe1dz.js} +7 -6
- package/package.json +8 -2
- package/build/agent-mvpgvgks.js +0 -19
- package/build/authentication-3s97cpk4.js +0 -19
- package/build/blackboxAgent-gw0a1ca4.js +0 -19
- package/build/blackboxPentest-44333zss.js +0 -37
- package/build/main-mmjp338j.js +0 -324
- package/build/pentest-xtc1sjdw.js +0 -29
- package/build/threatModel-xsm6fwk5.js +0 -27
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectOSAndEnhancePrompt
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-9y49bzhd.js";
|
|
4
4
|
import {
|
|
5
5
|
parseTargetUrl
|
|
6
6
|
} from "./cli-c8131c4q.js";
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
create,
|
|
11
11
|
createLogger,
|
|
12
12
|
generateObjectResponse,
|
|
13
|
+
getActiveTraceCorrelation,
|
|
13
14
|
getApexTracer,
|
|
14
15
|
hasToolCall,
|
|
15
16
|
init_ai,
|
|
@@ -24,22 +25,25 @@ import {
|
|
|
24
25
|
list,
|
|
25
26
|
newMessageId,
|
|
26
27
|
newPartId,
|
|
28
|
+
newRunId,
|
|
27
29
|
newSessionId,
|
|
28
30
|
read,
|
|
31
|
+
registerActiveRootSpan,
|
|
29
32
|
require_tslib,
|
|
30
33
|
scopedLogger,
|
|
31
34
|
stepCountIs,
|
|
32
35
|
streamResponse,
|
|
36
|
+
unregisterActiveRootSpan,
|
|
33
37
|
withSubagentSessionBaggage,
|
|
34
38
|
write
|
|
35
|
-
} from "./cli-
|
|
39
|
+
} from "./cli-70banr6y.js";
|
|
36
40
|
import {
|
|
37
41
|
ensureValidToken,
|
|
38
42
|
getPensarApiUrl,
|
|
39
43
|
init_auth,
|
|
40
44
|
init_constants,
|
|
41
45
|
signGatewayRequest
|
|
42
|
-
} from "./cli-
|
|
46
|
+
} from "./cli-naapss75.js";
|
|
43
47
|
import {
|
|
44
48
|
_enum,
|
|
45
49
|
_null,
|
|
@@ -60,17 +64,23 @@ import {
|
|
|
60
64
|
optional,
|
|
61
65
|
preprocess,
|
|
62
66
|
record,
|
|
63
|
-
require_src,
|
|
64
67
|
safeParse,
|
|
65
68
|
string,
|
|
66
69
|
tool,
|
|
67
70
|
union,
|
|
68
71
|
unknown
|
|
69
|
-
} from "./cli-
|
|
72
|
+
} from "./cli-avmhkjtv.js";
|
|
70
73
|
import {
|
|
71
74
|
config,
|
|
72
75
|
init_config
|
|
73
|
-
} from "./cli-
|
|
76
|
+
} from "./cli-x4e10v99.js";
|
|
77
|
+
import {
|
|
78
|
+
getCurrentVersion,
|
|
79
|
+
init_installation
|
|
80
|
+
} from "./cli-13vsx08y.js";
|
|
81
|
+
import {
|
|
82
|
+
require_src
|
|
83
|
+
} from "./cli-knd276ed.js";
|
|
74
84
|
import {
|
|
75
85
|
__commonJS,
|
|
76
86
|
__require,
|
|
@@ -102763,12 +102773,7 @@ function camoufoxWindowOptions(window2) {
|
|
|
102763
102773
|
const [width, height] = window2;
|
|
102764
102774
|
return {
|
|
102765
102775
|
window: [width, height],
|
|
102766
|
-
screen: {
|
|
102767
|
-
minWidth: width,
|
|
102768
|
-
maxWidth: width,
|
|
102769
|
-
minHeight: height,
|
|
102770
|
-
maxHeight: height
|
|
102771
|
-
}
|
|
102776
|
+
screen: { minWidth: width, minHeight: height }
|
|
102772
102777
|
};
|
|
102773
102778
|
}
|
|
102774
102779
|
async function resolveCamoufoxLaunchOptions(headless, opts) {
|
|
@@ -104466,6 +104471,19 @@ function assertUrlInScope(url, ctx) {
|
|
|
104466
104471
|
throw new ScopeViolationError(hostname, allowedHosts);
|
|
104467
104472
|
}
|
|
104468
104473
|
}
|
|
104474
|
+
function assertFindingEndpointInScope(endpoint, ctx) {
|
|
104475
|
+
const allowedHosts = getAllowedHosts(ctx);
|
|
104476
|
+
if (allowedHosts.length === 0)
|
|
104477
|
+
return;
|
|
104478
|
+
if (!/^https?:\/\//i.test(endpoint.trim()))
|
|
104479
|
+
return;
|
|
104480
|
+
const hostname = extractHostname2(endpoint);
|
|
104481
|
+
if (!hostname)
|
|
104482
|
+
return;
|
|
104483
|
+
if (!isHostAllowed(hostname, allowedHosts)) {
|
|
104484
|
+
throw new ScopeViolationError(hostname, allowedHosts);
|
|
104485
|
+
}
|
|
104486
|
+
}
|
|
104469
104487
|
function extractHostsFromCommand(command) {
|
|
104470
104488
|
const hosts = new Set;
|
|
104471
104489
|
const urlPattern = /https?:\/\/[^\s"'`;|&)<>]+/gi;
|
|
@@ -105055,12 +105073,8 @@ const fs = require('fs');
|
|
|
105055
105073
|
...${JSON.stringify(CAMOUFOX_OPTIONS)},
|
|
105056
105074
|
headless: __headless,
|
|
105057
105075
|
window: __window,
|
|
105058
|
-
|
|
105059
|
-
|
|
105060
|
-
maxWidth: __window[0],
|
|
105061
|
-
minHeight: __window[1],
|
|
105062
|
-
maxHeight: __window[1],
|
|
105063
|
-
},
|
|
105076
|
+
// Floor only — exact-pinning a 720px height throws in browserforge.
|
|
105077
|
+
screen: { minWidth: __window[0], minHeight: __window[1] },
|
|
105064
105078
|
});
|
|
105065
105079
|
fs.writeFileSync('${SANDBOX_CAMOU_CACHE}', JSON.stringify(__camou));
|
|
105066
105080
|
}
|
|
@@ -106761,7 +106775,7 @@ IMPORTANT: Pass protectedEndpoints in authHints when you've discovered 401/403 e
|
|
|
106761
106775
|
if (credentials) {
|
|
106762
106776
|
ctx.session.credentialManager.addFromAuthCredentials(credentials);
|
|
106763
106777
|
}
|
|
106764
|
-
const { runAuthenticationAgent } = await import("./authentication-
|
|
106778
|
+
const { runAuthenticationAgent } = await import("./authentication-jt9fq8y9.js");
|
|
106765
106779
|
const localBus = new AgentEventBus;
|
|
106766
106780
|
AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
|
|
106767
106781
|
const result = await runAuthenticationAgent({
|
|
@@ -107555,7 +107569,7 @@ async function generateThreatModelForEndpoint(ctx, input) {
|
|
|
107555
107569
|
return threatModelLimiter(async () => {
|
|
107556
107570
|
if (ctx.abortSignal?.aborted)
|
|
107557
107571
|
return null;
|
|
107558
|
-
const { CodeAgent } = await import("./agent-
|
|
107572
|
+
const { CodeAgent } = await import("./agent-z3ydv420.js");
|
|
107559
107573
|
const subagentId = newSessionId();
|
|
107560
107574
|
const subagentName = `Threat Model: ${input.routePath}`;
|
|
107561
107575
|
ctx.eventBus?.emit("subagent-spawn", {
|
|
@@ -108044,6 +108058,16 @@ import {
|
|
|
108044
108058
|
} from "node:fs";
|
|
108045
108059
|
import { join as join13 } from "node:path";
|
|
108046
108060
|
|
|
108061
|
+
// src/lib/attack-path/types.ts
|
|
108062
|
+
init_zod();
|
|
108063
|
+
var AttackPathSchema = exports_external.array(exports_external.object({
|
|
108064
|
+
applicationId: exports_external.string().optional(),
|
|
108065
|
+
applicationName: exports_external.string().optional(),
|
|
108066
|
+
host: exports_external.string().optional(),
|
|
108067
|
+
relationshipType: exports_external.string().optional(),
|
|
108068
|
+
notes: exports_external.string().optional()
|
|
108069
|
+
}));
|
|
108070
|
+
|
|
108047
108071
|
// src/lib/cwe/types.ts
|
|
108048
108072
|
init_zod();
|
|
108049
108073
|
var CweEntrySchema = exports_external.object({
|
|
@@ -108366,6 +108390,47 @@ var MAX_SEVERITY = {
|
|
|
108366
108390
|
eq4: { 0: 6, 1: 5, 2: 4 },
|
|
108367
108391
|
eq5: { 0: 1, 1: 1, 2: 1 }
|
|
108368
108392
|
};
|
|
108393
|
+
var MAX_COMPOSED = {
|
|
108394
|
+
eq1: {
|
|
108395
|
+
0: ["AV:N/PR:N/UI:N/"],
|
|
108396
|
+
1: ["AV:A/PR:N/UI:N/", "AV:N/PR:L/UI:N/", "AV:N/PR:N/UI:P/"],
|
|
108397
|
+
2: ["AV:P/PR:N/UI:N/", "AV:A/PR:L/UI:P/"]
|
|
108398
|
+
},
|
|
108399
|
+
eq2: {
|
|
108400
|
+
0: ["AC:L/AT:N/"],
|
|
108401
|
+
1: ["AC:H/AT:N/", "AC:L/AT:P/"]
|
|
108402
|
+
},
|
|
108403
|
+
eq3: {
|
|
108404
|
+
0: {
|
|
108405
|
+
"0": ["VC:H/VI:H/VA:H/CR:H/IR:H/AR:H/"],
|
|
108406
|
+
"1": ["VC:H/VI:H/VA:L/CR:M/IR:M/AR:H/", "VC:H/VI:H/VA:H/CR:M/IR:M/AR:M/"]
|
|
108407
|
+
},
|
|
108408
|
+
1: {
|
|
108409
|
+
"0": ["VC:L/VI:H/VA:H/CR:H/IR:H/AR:H/", "VC:H/VI:L/VA:H/CR:H/IR:H/AR:H/"],
|
|
108410
|
+
"1": [
|
|
108411
|
+
"VC:L/VI:H/VA:L/CR:H/IR:M/AR:H/",
|
|
108412
|
+
"VC:L/VI:H/VA:H/CR:H/IR:M/AR:M/",
|
|
108413
|
+
"VC:H/VI:L/VA:H/CR:M/IR:H/AR:M/",
|
|
108414
|
+
"VC:H/VI:L/VA:L/CR:M/IR:H/AR:H/",
|
|
108415
|
+
"VC:L/VI:L/VA:H/CR:H/IR:H/AR:M/"
|
|
108416
|
+
]
|
|
108417
|
+
},
|
|
108418
|
+
2: {
|
|
108419
|
+
"1": ["VC:L/VI:L/VA:L/CR:H/IR:H/AR:H/"]
|
|
108420
|
+
}
|
|
108421
|
+
},
|
|
108422
|
+
eq4: {
|
|
108423
|
+
0: ["SC:H/SI:S/SA:S/"],
|
|
108424
|
+
1: ["SC:H/SI:H/SA:H/"],
|
|
108425
|
+
2: ["SC:L/SI:L/SA:L/"]
|
|
108426
|
+
},
|
|
108427
|
+
eq5: {
|
|
108428
|
+
0: ["E:A/"],
|
|
108429
|
+
1: ["E:P/"],
|
|
108430
|
+
2: ["E:U/"]
|
|
108431
|
+
}
|
|
108432
|
+
};
|
|
108433
|
+
var NO_IMPACT_METRICS = ["VC", "VI", "VA", "SC", "SI", "SA"];
|
|
108369
108434
|
var STEP = 0.1;
|
|
108370
108435
|
var EPSILON = 10 ** -6;
|
|
108371
108436
|
|
|
@@ -108414,6 +108479,12 @@ var ENVIRONMENTAL_METRICS = [
|
|
|
108414
108479
|
"MSA"
|
|
108415
108480
|
];
|
|
108416
108481
|
var SUPPLEMENTAL_METRICS = ["S", "AU", "R", "V", "RE", "U"];
|
|
108482
|
+
var KNOWN_METRICS = new Set([
|
|
108483
|
+
...BASE_METRICS,
|
|
108484
|
+
...THREAT_METRICS,
|
|
108485
|
+
...ENVIRONMENTAL_METRICS,
|
|
108486
|
+
...SUPPLEMENTAL_METRICS
|
|
108487
|
+
]);
|
|
108417
108488
|
function buildVectorString(metrics) {
|
|
108418
108489
|
const parts = ["CVSS:4.0"];
|
|
108419
108490
|
for (const metric of BASE_METRICS) {
|
|
@@ -108442,39 +108513,49 @@ function buildVectorString(metrics) {
|
|
|
108442
108513
|
}
|
|
108443
108514
|
return parts.join("/");
|
|
108444
108515
|
}
|
|
108445
|
-
|
|
108446
|
-
|
|
108447
|
-
|
|
108448
|
-
|
|
108449
|
-
|
|
108450
|
-
|
|
108451
|
-
|
|
108452
|
-
|
|
108516
|
+
var WORST_CASE_DEFAULTS = {
|
|
108517
|
+
E: "A",
|
|
108518
|
+
CR: "H",
|
|
108519
|
+
IR: "H",
|
|
108520
|
+
AR: "H"
|
|
108521
|
+
};
|
|
108522
|
+
function getEffectiveValue(metrics, metric) {
|
|
108523
|
+
const record3 = metrics;
|
|
108524
|
+
const selected = record3[metric] ?? "X";
|
|
108525
|
+
const worstCase = WORST_CASE_DEFAULTS[metric];
|
|
108526
|
+
if (worstCase !== undefined && selected === "X") {
|
|
108527
|
+
return worstCase;
|
|
108528
|
+
}
|
|
108529
|
+
const modified = record3[`M${metric}`];
|
|
108530
|
+
if (modified !== undefined && modified !== "X") {
|
|
108531
|
+
return modified;
|
|
108532
|
+
}
|
|
108533
|
+
return selected;
|
|
108453
108534
|
}
|
|
108454
108535
|
function computeEQ1(metrics) {
|
|
108455
|
-
const av = getEffectiveValue(metrics, "AV"
|
|
108456
|
-
const pr = getEffectiveValue(metrics, "PR"
|
|
108457
|
-
const ui = getEffectiveValue(metrics, "UI"
|
|
108536
|
+
const av = getEffectiveValue(metrics, "AV");
|
|
108537
|
+
const pr = getEffectiveValue(metrics, "PR");
|
|
108538
|
+
const ui = getEffectiveValue(metrics, "UI");
|
|
108458
108539
|
if (av === "N" && pr === "N" && ui === "N") {
|
|
108459
108540
|
return 0;
|
|
108460
108541
|
}
|
|
108461
|
-
if (
|
|
108542
|
+
if ((av === "N" || pr === "N" || ui === "N") && av !== "P") {
|
|
108462
108543
|
return 1;
|
|
108463
108544
|
}
|
|
108464
108545
|
return 2;
|
|
108465
108546
|
}
|
|
108466
108547
|
function computeEQ2(metrics) {
|
|
108467
|
-
const ac = getEffectiveValue(metrics, "AC"
|
|
108468
|
-
const at = getEffectiveValue(metrics, "AT"
|
|
108548
|
+
const ac = getEffectiveValue(metrics, "AC");
|
|
108549
|
+
const at = getEffectiveValue(metrics, "AT");
|
|
108469
108550
|
if (ac === "L" && at === "N") {
|
|
108470
108551
|
return 0;
|
|
108471
108552
|
}
|
|
108472
108553
|
return 1;
|
|
108473
108554
|
}
|
|
108474
108555
|
function computeEQ3(metrics) {
|
|
108475
|
-
const vc = getEffectiveValue(metrics, "VC"
|
|
108476
|
-
const vi = getEffectiveValue(metrics, "VI"
|
|
108477
|
-
const va = getEffectiveValue(metrics, "VA"
|
|
108556
|
+
const vc = getEffectiveValue(metrics, "VC");
|
|
108557
|
+
const vi = getEffectiveValue(metrics, "VI");
|
|
108558
|
+
const va = getEffectiveValue(metrics, "VA");
|
|
108478
108559
|
if (vc === "H" && vi === "H") {
|
|
108479
108560
|
return 0;
|
|
108480
108561
|
}
|
|
@@ -108484,11 +108565,11 @@ function computeEQ3(metrics) {
|
|
|
108484
108565
|
return 2;
|
|
108485
108566
|
}
|
|
108486
108567
|
function computeEQ4(metrics) {
|
|
108487
|
-
const msi = metrics
|
|
108488
|
-
const msa = metrics
|
|
108489
|
-
const sc = getEffectiveValue(metrics, "SC"
|
|
108490
|
-
const si =
|
|
108491
|
-
const sa =
|
|
108568
|
+
const msi = getEffectiveValue(metrics, "MSI");
|
|
108569
|
+
const msa = getEffectiveValue(metrics, "MSA");
|
|
108570
|
+
const sc = getEffectiveValue(metrics, "SC");
|
|
108571
|
+
const si = getEffectiveValue(metrics, "SI");
|
|
108572
|
+
const sa = getEffectiveValue(metrics, "SA");
|
|
108492
108573
|
if (msi === "S" || msa === "S") {
|
|
108493
108574
|
return 0;
|
|
108494
108575
|
}
|
|
@@ -108498,8 +108579,8 @@ function computeEQ4(metrics) {
|
|
|
108498
108579
|
return 2;
|
|
108499
108580
|
}
|
|
108500
108581
|
function computeEQ5(metrics) {
|
|
108501
|
-
const e = metrics
|
|
108502
|
-
if (e === "A"
|
|
108582
|
+
const e = getEffectiveValue(metrics, "E");
|
|
108583
|
+
if (e === "A") {
|
|
108503
108584
|
return 0;
|
|
108504
108585
|
}
|
|
108505
108586
|
if (e === "P") {
|
|
@@ -108508,12 +108589,12 @@ function computeEQ5(metrics) {
|
|
|
108508
108589
|
return 2;
|
|
108509
108590
|
}
|
|
108510
108591
|
function computeEQ6(metrics) {
|
|
108511
|
-
const cr = metrics
|
|
108512
|
-
const ir = metrics
|
|
108513
|
-
const ar = metrics
|
|
108514
|
-
const vc = getEffectiveValue(metrics, "VC"
|
|
108515
|
-
const vi = getEffectiveValue(metrics, "VI"
|
|
108516
|
-
const va = getEffectiveValue(metrics, "VA"
|
|
108592
|
+
const cr = getEffectiveValue(metrics, "CR");
|
|
108593
|
+
const ir = getEffectiveValue(metrics, "IR");
|
|
108594
|
+
const ar = getEffectiveValue(metrics, "AR");
|
|
108595
|
+
const vc = getEffectiveValue(metrics, "VC");
|
|
108596
|
+
const vi = getEffectiveValue(metrics, "VI");
|
|
108597
|
+
const va = getEffectiveValue(metrics, "VA");
|
|
108517
108598
|
if (cr === "H" && vc === "H" || ir === "H" && vi === "H" || ar === "H" && va === "H") {
|
|
108518
108599
|
return 0;
|
|
108519
108600
|
}
|
|
@@ -108529,116 +108610,130 @@ function computeMacroVector(metrics) {
|
|
|
108529
108610
|
return `${eq1}${eq2}${eq3}${eq4}${eq5}${eq6}`;
|
|
108530
108611
|
}
|
|
108531
108612
|
function hasNoImpact(metrics) {
|
|
108532
|
-
|
|
108533
|
-
const vi = getEffectiveValue(metrics, "VI", "MVI");
|
|
108534
|
-
const va = getEffectiveValue(metrics, "VA", "MVA");
|
|
108535
|
-
const sc = getEffectiveValue(metrics, "SC", "MSC");
|
|
108536
|
-
const si = metrics.MSI !== "X" && metrics.MSI ? metrics.MSI : metrics.SI;
|
|
108537
|
-
const sa = metrics.MSA !== "X" && metrics.MSA ? metrics.MSA : metrics.SA;
|
|
108538
|
-
return vc === "N" && vi === "N" && va === "N" && sc === "N" && si === "N" && sa === "N";
|
|
108613
|
+
return NO_IMPACT_METRICS.every((metric) => getEffectiveValue(metrics, metric) === "N");
|
|
108539
108614
|
}
|
|
108540
|
-
function
|
|
108541
|
-
|
|
108542
|
-
|
|
108543
|
-
|
|
108544
|
-
|
|
108545
|
-
|
|
108546
|
-
|
|
108547
|
-
|
|
108548
|
-
|
|
108549
|
-
|
|
108550
|
-
|
|
108615
|
+
function parseMacroVector(macroVector) {
|
|
108616
|
+
return {
|
|
108617
|
+
eq1: Number(macroVector[0]),
|
|
108618
|
+
eq2: Number(macroVector[1]),
|
|
108619
|
+
eq3: Number(macroVector[2]),
|
|
108620
|
+
eq4: Number(macroVector[3]),
|
|
108621
|
+
eq5: Number(macroVector[4]),
|
|
108622
|
+
eq6: Number(macroVector[5])
|
|
108623
|
+
};
|
|
108624
|
+
}
|
|
108625
|
+
function lowerMacroVectorScore(eq, step) {
|
|
108626
|
+
const stepped = { ...eq, ...step };
|
|
108627
|
+
return MACROVECTOR_LOOKUP[`${stepped.eq1}${stepped.eq2}${stepped.eq3}${stepped.eq4}${stepped.eq5}${stepped.eq6}`];
|
|
108628
|
+
}
|
|
108629
|
+
function lowerEq3Eq6Score(eq) {
|
|
108630
|
+
if (eq.eq3 === 0 && eq.eq6 === 0) {
|
|
108631
|
+
const viaEq6 = lowerMacroVectorScore(eq, { eq6: eq.eq6 + 1 });
|
|
108632
|
+
const viaEq3 = lowerMacroVectorScore(eq, { eq3: eq.eq3 + 1 });
|
|
108633
|
+
if (viaEq6 === undefined || viaEq3 === undefined) {
|
|
108634
|
+
return;
|
|
108635
|
+
}
|
|
108636
|
+
return Math.max(viaEq6, viaEq3);
|
|
108637
|
+
}
|
|
108638
|
+
if (eq.eq3 === 1 && eq.eq6 === 0) {
|
|
108639
|
+
return lowerMacroVectorScore(eq, { eq6: eq.eq6 + 1 });
|
|
108640
|
+
}
|
|
108641
|
+
if (eq.eq3 < 2) {
|
|
108642
|
+
return lowerMacroVectorScore(eq, { eq3: eq.eq3 + 1 });
|
|
108551
108643
|
}
|
|
108552
|
-
|
|
108553
|
-
|
|
108644
|
+
return lowerMacroVectorScore(eq, { eq3: eq.eq3 + 1, eq6: eq.eq6 + 1 });
|
|
108645
|
+
}
|
|
108646
|
+
function composeMaxVectors(eq) {
|
|
108647
|
+
const eq3Maxima = MAX_COMPOSED.eq3[eq.eq3]?.[eq.eq6];
|
|
108648
|
+
if (eq3Maxima === undefined) {
|
|
108649
|
+
throw new Error(`No max severity vector for eq3=${eq.eq3}, eq6=${eq.eq6}`);
|
|
108554
108650
|
}
|
|
108555
|
-
|
|
108556
|
-
|
|
108651
|
+
const vectors = [];
|
|
108652
|
+
for (const eq1Max of MAX_COMPOSED.eq1[eq.eq1]) {
|
|
108653
|
+
for (const eq2Max of MAX_COMPOSED.eq2[eq.eq2]) {
|
|
108654
|
+
for (const eq3Max of eq3Maxima) {
|
|
108655
|
+
for (const eq4Max of MAX_COMPOSED.eq4[eq.eq4]) {
|
|
108656
|
+
for (const eq5Max of MAX_COMPOSED.eq5[eq.eq5]) {
|
|
108657
|
+
vectors.push(eq1Max + eq2Max + eq3Max + eq4Max + eq5Max);
|
|
108658
|
+
}
|
|
108659
|
+
}
|
|
108660
|
+
}
|
|
108661
|
+
}
|
|
108557
108662
|
}
|
|
108558
|
-
return
|
|
108663
|
+
return vectors;
|
|
108664
|
+
}
|
|
108665
|
+
function extractMaxVectorValue(metric, maxVector) {
|
|
108666
|
+
const start = maxVector.indexOf(`${metric}:`);
|
|
108667
|
+
if (start < 0) {
|
|
108668
|
+
throw new Error(`Metric ${metric} missing from max vector ${maxVector}`);
|
|
108669
|
+
}
|
|
108670
|
+
const rest = maxVector.slice(start + metric.length + 1);
|
|
108671
|
+
const end = rest.indexOf("/");
|
|
108672
|
+
return end > 0 ? rest.slice(0, end) : rest;
|
|
108559
108673
|
}
|
|
108560
|
-
function
|
|
108561
|
-
const
|
|
108562
|
-
|
|
108563
|
-
|
|
108564
|
-
|
|
108674
|
+
function severityDistances(metrics, maxVector) {
|
|
108675
|
+
const distances = {};
|
|
108676
|
+
for (const [metric, levels] of Object.entries(METRIC_LEVELS)) {
|
|
108677
|
+
const value = getEffectiveValue(metrics, metric);
|
|
108678
|
+
const maxValue = extractMaxVectorValue(metric, maxVector);
|
|
108679
|
+
const level = levels[value];
|
|
108680
|
+
const maxLevel = levels[maxValue];
|
|
108681
|
+
if (level === undefined) {
|
|
108682
|
+
throw new Error(`Unknown value ${metric}:${value}`);
|
|
108683
|
+
}
|
|
108684
|
+
if (maxLevel === undefined) {
|
|
108685
|
+
throw new Error(`Unknown value ${metric}:${maxValue} in ${maxVector}`);
|
|
108686
|
+
}
|
|
108687
|
+
distances[metric] = level - maxLevel;
|
|
108688
|
+
}
|
|
108689
|
+
return distances;
|
|
108565
108690
|
}
|
|
108566
|
-
function interpolateScore(metrics, macroVector,
|
|
108567
|
-
const
|
|
108568
|
-
|
|
108569
|
-
const
|
|
108570
|
-
|
|
108571
|
-
|
|
108572
|
-
|
|
108573
|
-
|
|
108574
|
-
|
|
108575
|
-
|
|
108576
|
-
|
|
108577
|
-
|
|
108578
|
-
|
|
108579
|
-
|
|
108580
|
-
|
|
108581
|
-
|
|
108582
|
-
|
|
108583
|
-
|
|
108584
|
-
|
|
108585
|
-
|
|
108586
|
-
|
|
108587
|
-
|
|
108588
|
-
|
|
108589
|
-
|
|
108590
|
-
|
|
108591
|
-
|
|
108592
|
-
|
|
108593
|
-
|
|
108594
|
-
|
|
108595
|
-
|
|
108596
|
-
|
|
108597
|
-
|
|
108598
|
-
const
|
|
108599
|
-
|
|
108600
|
-
|
|
108601
|
-
|
|
108602
|
-
|
|
108603
|
-
|
|
108604
|
-
|
|
108605
|
-
|
|
108606
|
-
|
|
108607
|
-
|
|
108608
|
-
|
|
108609
|
-
|
|
108610
|
-
|
|
108611
|
-
|
|
108612
|
-
meanDistance += msd * normalizedDist;
|
|
108613
|
-
eqCount++;
|
|
108614
|
-
}
|
|
108615
|
-
}
|
|
108616
|
-
const eq4NextLower = getNextLowerScore(macroVector, 3);
|
|
108617
|
-
if (eq4NextLower !== null) {
|
|
108618
|
-
const msd = baseScore - eq4NextLower;
|
|
108619
|
-
const maxDepth = MAX_SEVERITY.eq4[eq4] || 1;
|
|
108620
|
-
const scDist = getMetricDistance(metrics, "SC");
|
|
108621
|
-
const siDist = getMetricDistance(metrics, "SI");
|
|
108622
|
-
const saDist = getMetricDistance(metrics, "SA");
|
|
108623
|
-
const severityDist = scDist + siDist + saDist;
|
|
108624
|
-
const normalizedDist = severityDist / (maxDepth * STEP);
|
|
108625
|
-
meanDistance += msd * normalizedDist;
|
|
108626
|
-
eqCount++;
|
|
108627
|
-
}
|
|
108628
|
-
const eq5NextLower = getNextLowerScore(macroVector, 4);
|
|
108629
|
-
if (eq5NextLower !== null) {
|
|
108630
|
-
const msd = baseScore - eq5NextLower;
|
|
108631
|
-
const maxDepth = MAX_SEVERITY.eq5[eq5] || 1;
|
|
108632
|
-
const eDist = getMetricDistance(metrics, "E");
|
|
108633
|
-
const normalizedDist = eDist / (maxDepth * STEP);
|
|
108634
|
-
meanDistance += msd * normalizedDist;
|
|
108635
|
-
eqCount++;
|
|
108636
|
-
}
|
|
108637
|
-
const avgDistance = eqCount > 0 ? meanDistance / eqCount : 0;
|
|
108638
|
-
let finalScore = baseScore - avgDistance;
|
|
108639
|
-
finalScore = Math.max(0, Math.min(10, finalScore));
|
|
108640
|
-
finalScore = Math.round(finalScore * 10) / 10;
|
|
108641
|
-
return finalScore;
|
|
108691
|
+
function interpolateScore(metrics, macroVector, macroScore) {
|
|
108692
|
+
const eq = parseMacroVector(macroVector);
|
|
108693
|
+
let distances;
|
|
108694
|
+
for (const maxVector of composeMaxVectors(eq)) {
|
|
108695
|
+
distances = severityDistances(metrics, maxVector);
|
|
108696
|
+
if (Object.values(distances).every((distance) => distance >= 0)) {
|
|
108697
|
+
break;
|
|
108698
|
+
}
|
|
108699
|
+
}
|
|
108700
|
+
if (distances === undefined) {
|
|
108701
|
+
throw new Error(`No max vectors composed for MacroVector ${macroVector}`);
|
|
108702
|
+
}
|
|
108703
|
+
const severityDistance = {
|
|
108704
|
+
eq1: distances.AV + distances.PR + distances.UI,
|
|
108705
|
+
eq2: distances.AC + distances.AT,
|
|
108706
|
+
eq3eq6: distances.VC + distances.VI + distances.VA + distances.CR + distances.IR + distances.AR,
|
|
108707
|
+
eq4: distances.SC + distances.SI + distances.SA
|
|
108708
|
+
};
|
|
108709
|
+
const lowerScore = {
|
|
108710
|
+
eq1: lowerMacroVectorScore(eq, { eq1: eq.eq1 + 1 }),
|
|
108711
|
+
eq2: lowerMacroVectorScore(eq, { eq2: eq.eq2 + 1 }),
|
|
108712
|
+
eq3eq6: lowerEq3Eq6Score(eq),
|
|
108713
|
+
eq4: lowerMacroVectorScore(eq, { eq4: eq.eq4 + 1 })
|
|
108714
|
+
};
|
|
108715
|
+
const macroVectorDepth = {
|
|
108716
|
+
eq1: MAX_SEVERITY.eq1[eq.eq1] * STEP,
|
|
108717
|
+
eq2: MAX_SEVERITY.eq2[eq.eq2] * STEP,
|
|
108718
|
+
eq3eq6: MAX_SEVERITY.eq3eq6[eq.eq3][eq.eq6] * STEP,
|
|
108719
|
+
eq4: MAX_SEVERITY.eq4[eq.eq4] * STEP
|
|
108720
|
+
};
|
|
108721
|
+
let existingLowerCount = 0;
|
|
108722
|
+
let proportionalDistance = 0;
|
|
108723
|
+
for (const key of ["eq1", "eq2", "eq3eq6", "eq4"]) {
|
|
108724
|
+
const lower = lowerScore[key];
|
|
108725
|
+
if (lower === undefined) {
|
|
108726
|
+
continue;
|
|
108727
|
+
}
|
|
108728
|
+
existingLowerCount++;
|
|
108729
|
+
proportionalDistance += (macroScore - lower) * (severityDistance[key] / macroVectorDepth[key]);
|
|
108730
|
+
}
|
|
108731
|
+
if (lowerMacroVectorScore(eq, { eq5: eq.eq5 + 1 }) !== undefined) {
|
|
108732
|
+
existingLowerCount++;
|
|
108733
|
+
}
|
|
108734
|
+
const meanDistance = existingLowerCount === 0 ? 0 : proportionalDistance / existingLowerCount;
|
|
108735
|
+
const score = Math.max(0, Math.min(10, macroScore - meanDistance));
|
|
108736
|
+
return Math.round((score + EPSILON) * 10) / 10;
|
|
108642
108737
|
}
|
|
108643
108738
|
function calculateCVSS4Score(metrics) {
|
|
108644
108739
|
if (hasNoImpact(metrics)) {
|
|
@@ -109480,7 +109575,7 @@ init_lazyLogger();
|
|
|
109480
109575
|
var log6 = scopedLogger(() => createLogger("FindingJudge"));
|
|
109481
109576
|
async function judgeFinding(input, ctx) {
|
|
109482
109577
|
try {
|
|
109483
|
-
const { FindingJudgeAgent } = await import("./agent-
|
|
109578
|
+
const { FindingJudgeAgent } = await import("./agent-jgdfbwse.js");
|
|
109484
109579
|
const agent = new FindingJudgeAgent({
|
|
109485
109580
|
finding: input,
|
|
109486
109581
|
model: ctx.model,
|
|
@@ -109581,7 +109676,8 @@ var documentVulnerabilityInputSchema = exports_external.object({
|
|
|
109581
109676
|
pocName: exports_external.string().describe("Short descriptive name for the POC"),
|
|
109582
109677
|
pocType: exports_external.enum(["bash", "python", "javascript"]).describe("Script language"),
|
|
109583
109678
|
pocContent: exports_external.string().describe("The full POC script content"),
|
|
109584
|
-
pocDescription: exports_external.string().describe("What this POC demonstrates")
|
|
109679
|
+
pocDescription: exports_external.string().describe("What this POC demonstrates"),
|
|
109680
|
+
attackPath: AttackPathSchema.optional().describe("Required ordered member-to-member hop chain when the finding spans multiple System members; do not leave this chain only in narrative fields")
|
|
109585
109681
|
});
|
|
109586
109682
|
function formatMateriality(input) {
|
|
109587
109683
|
return [
|
|
@@ -109651,11 +109747,24 @@ CRITICAL RULES — READ BEFORE CALLING:
|
|
|
109651
109747
|
- POC must exit 0 on success (vulnerability confirmed), non-zero on failure
|
|
109652
109748
|
- POC must print clear evidence of exploitation to stdout
|
|
109653
109749
|
- Fill the materiality checklist with the concrete exploit path, material security impact, affected non-public asset or abuse path, and why common false-positive traps do not apply
|
|
109750
|
+
- When a finding spans multiple System members, populate attackPath with every hop in order; do not leave the chain only in the description or evidence
|
|
109654
109751
|
- If the tool returns a POC failure or judge rejection, revise your approach and call again
|
|
109655
109752
|
- Do NOT use this for: positive observations, informational notes, testing limitations, or anything that is not an exploitable security vulnerability
|
|
109656
109753
|
- If you could not exploit a vulnerability, do NOT call this tool — mention it in your final response summary instead`,
|
|
109657
109754
|
inputSchema: documentVulnerabilityInputSchema,
|
|
109658
109755
|
execute: async (input) => {
|
|
109756
|
+
try {
|
|
109757
|
+
assertFindingEndpointInScope(input.endpoint, ctx);
|
|
109758
|
+
} catch (error) {
|
|
109759
|
+
if (error instanceof ScopeViolationError) {
|
|
109760
|
+
return {
|
|
109761
|
+
success: false,
|
|
109762
|
+
error: error.message,
|
|
109763
|
+
message: `Finding endpoint rejected — out of scope: ${error.message}`
|
|
109764
|
+
};
|
|
109765
|
+
}
|
|
109766
|
+
throw error;
|
|
109767
|
+
}
|
|
109659
109768
|
try {
|
|
109660
109769
|
const materializedEvidence = formatMateriality(input);
|
|
109661
109770
|
if (ctx.findingsRegistry) {
|
|
@@ -109870,7 +109979,8 @@ CRITICAL RULES — READ BEFORE CALLING:
|
|
|
109870
109979
|
vulnerabilityClass: input.vulnerabilityClass
|
|
109871
109980
|
},
|
|
109872
109981
|
severity,
|
|
109873
|
-
...evidenceFiles.length > 0 && { evidenceFiles }
|
|
109982
|
+
...evidenceFiles.length > 0 && { evidenceFiles },
|
|
109983
|
+
...input.attackPath && input.attackPath.length > 0 && { attackPath: input.attackPath }
|
|
109874
109984
|
};
|
|
109875
109985
|
if (isVulnerability && ctx.findingsRegistry) {
|
|
109876
109986
|
const check = await ctx.findingsRegistry.register(finding);
|
|
@@ -115366,9 +115476,10 @@ class PersistentShell {
|
|
|
115366
115476
|
${commandOutput}`;
|
|
115367
115477
|
}
|
|
115368
115478
|
const effectiveExit = cmd.forcedExitCode != null ? cmd.forcedExitCode : Number.isNaN(naturalExitCode) ? 1 : naturalExitCode;
|
|
115369
|
-
const
|
|
115479
|
+
const diskStderr = readTempfileCapped(cmd.errPath);
|
|
115370
115480
|
unlinkSafe(cmd.outPath);
|
|
115371
115481
|
unlinkSafe(cmd.errPath);
|
|
115482
|
+
const effectiveStderr = (diskStderr || cmd.stderr || "") + (cmd.forcedStderrSuffix ?? "");
|
|
115372
115483
|
const resolve4 = cmd.resolve;
|
|
115373
115484
|
this.current = null;
|
|
115374
115485
|
this.pendingCancel = null;
|
|
@@ -116106,7 +116217,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
|
|
|
116106
116217
|
});
|
|
116107
116218
|
if (cwd) {
|
|
116108
116219
|
try {
|
|
116109
|
-
const { WhiteboxAttackSurfaceAgent } = await import("./index-
|
|
116220
|
+
const { WhiteboxAttackSurfaceAgent } = await import("./index-sx52n7s9.js");
|
|
116110
116221
|
const localBus = new AgentEventBus;
|
|
116111
116222
|
AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
|
|
116112
116223
|
const agent = new WhiteboxAttackSurfaceAgent({
|
|
@@ -116161,7 +116272,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
|
|
|
116161
116272
|
}
|
|
116162
116273
|
}
|
|
116163
116274
|
try {
|
|
116164
|
-
const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-
|
|
116275
|
+
const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-vwtk3hv1.js");
|
|
116165
116276
|
const localBus = new AgentEventBus;
|
|
116166
116277
|
AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
|
|
116167
116278
|
const agent = new BlackboxAttackSurfaceAgent({
|
|
@@ -116239,7 +116350,7 @@ Omit \`cwd\` for blackbox mode (live target probing only).`,
|
|
|
116239
116350
|
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
116240
116351
|
}),
|
|
116241
116352
|
execute: async ({ target, cwd }) => {
|
|
116242
|
-
const { runPentestWorkflow: workflow } = await import("./pentest-
|
|
116353
|
+
const { runPentestWorkflow: workflow } = await import("./pentest-3w1jgsg7.js");
|
|
116243
116354
|
if (!ctx.model) {
|
|
116244
116355
|
return {
|
|
116245
116356
|
success: false,
|
|
@@ -116299,6 +116410,122 @@ function summarizeFindingsBySeverity(findings) {
|
|
|
116299
116410
|
return counts;
|
|
116300
116411
|
}
|
|
116301
116412
|
|
|
116413
|
+
// src/core/agents/offSecAgent/tools/smsListMessages.ts
|
|
116414
|
+
init_dist();
|
|
116415
|
+
init_zod();
|
|
116416
|
+
var SMS_LIST_MESSAGES_TOOL_NAME = "sms_list_messages";
|
|
116417
|
+
var SMS_TOOL_NAMES = [SMS_LIST_MESSAGES_TOOL_NAME];
|
|
116418
|
+
function hasPhoneNumberAuthCredential(session) {
|
|
116419
|
+
const creds = session.config?.authCredentials;
|
|
116420
|
+
const list2 = creds ? Array.isArray(creds) ? creds : [creds] : [];
|
|
116421
|
+
return list2.some((cred) => Boolean(cred.additionalFields?.phoneNumber));
|
|
116422
|
+
}
|
|
116423
|
+
function sessionHasSmsPasswordless(session) {
|
|
116424
|
+
const refs = session.credentialManager?.listReferences() ?? [];
|
|
116425
|
+
if (refs.some((ref) => ref.additionalFieldKeys?.includes("phoneNumber"))) {
|
|
116426
|
+
return true;
|
|
116427
|
+
}
|
|
116428
|
+
return hasPhoneNumberAuthCredential(session);
|
|
116429
|
+
}
|
|
116430
|
+
function requireAgentApi() {
|
|
116431
|
+
const base = process.env.AGENT_API_URL;
|
|
116432
|
+
const token = process.env.AGENT_API_TOKEN;
|
|
116433
|
+
if (!base || !token) {
|
|
116434
|
+
throw new Error("sms_list_messages requires AGENT_API_URL and AGENT_API_TOKEN (Console sandbox dispatch). Local CLI without Console cannot read inbound SMS.");
|
|
116435
|
+
}
|
|
116436
|
+
return { base: base.replace(/\/+$/, ""), token };
|
|
116437
|
+
}
|
|
116438
|
+
async function agentFetch(path, init) {
|
|
116439
|
+
const { token, ...rest } = init;
|
|
116440
|
+
return fetch(path, {
|
|
116441
|
+
...rest,
|
|
116442
|
+
headers: {
|
|
116443
|
+
Authorization: `Bearer ${token}`,
|
|
116444
|
+
...rest.headers ?? {}
|
|
116445
|
+
}
|
|
116446
|
+
});
|
|
116447
|
+
}
|
|
116448
|
+
function smsListMessages(ctx) {
|
|
116449
|
+
return tool({
|
|
116450
|
+
description: `Reserve or list inbound SMS on the stage-managed Mobile OTP (sms-passwordless) receiving number.
|
|
116451
|
+
|
|
116452
|
+
Reserve immediately before filling the target phone field and clicking send-code: call with reserve=true. The Console chooses and leases the receiving number from the signed session; never supply or request a phone number here.
|
|
116453
|
+
|
|
116454
|
+
After the target sends a code, sleep with execute_command (e.g. sleep 5), then call with sinceMs from the send-code click. Set claim=true to consume the newest unconsumed message (exclusive; other runs cannot reuse that OTP). This is a single request — it does not wait. A 429 means the shared number is busy; retry the reservation later rather than waiting in this tool.
|
|
116455
|
+
|
|
116456
|
+
Requires a Console sandbox (AGENT_API_URL).`,
|
|
116457
|
+
inputSchema: exports_external.object({
|
|
116458
|
+
reserve: exports_external.boolean().optional().describe("Reserve the session-bound shared number before requesting a code. Cannot be combined with sinceMs or claim."),
|
|
116459
|
+
sinceMs: exports_external.number().optional().describe("Epoch milliseconds of the send-code click. Required unless reserving; messages received before this timestamp are ignored."),
|
|
116460
|
+
claim: exports_external.boolean().optional().describe("Consume the newest unconsumed message so other runs cannot reuse the OTP. Defaults to false (list only)."),
|
|
116461
|
+
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
116462
|
+
}).strict().superRefine((input, refinementCtx) => {
|
|
116463
|
+
if (input.reserve) {
|
|
116464
|
+
if (input.sinceMs !== undefined || input.claim !== undefined) {
|
|
116465
|
+
refinementCtx.addIssue({
|
|
116466
|
+
code: "custom",
|
|
116467
|
+
message: "reserve=true cannot be combined with sinceMs or claim"
|
|
116468
|
+
});
|
|
116469
|
+
}
|
|
116470
|
+
return;
|
|
116471
|
+
}
|
|
116472
|
+
if (input.sinceMs === undefined) {
|
|
116473
|
+
refinementCtx.addIssue({
|
|
116474
|
+
code: "custom",
|
|
116475
|
+
path: ["sinceMs"],
|
|
116476
|
+
message: "sinceMs is required when listing SMS messages"
|
|
116477
|
+
});
|
|
116478
|
+
}
|
|
116479
|
+
}),
|
|
116480
|
+
execute: async ({ reserve, sinceMs, claim }) => {
|
|
116481
|
+
const { base, token } = requireAgentApi();
|
|
116482
|
+
const url = new URL(`${base}/agent/sms/messages`);
|
|
116483
|
+
if (reserve) {
|
|
116484
|
+
url.searchParams.set("reserve", "1");
|
|
116485
|
+
} else {
|
|
116486
|
+
if (sinceMs === undefined) {
|
|
116487
|
+
throw new Error("sms_list_messages requires sinceMs when listing");
|
|
116488
|
+
}
|
|
116489
|
+
url.searchParams.set("since", new Date(sinceMs).toISOString());
|
|
116490
|
+
if (claim)
|
|
116491
|
+
url.searchParams.set("claim", "1");
|
|
116492
|
+
}
|
|
116493
|
+
const res = await agentFetch(url.toString(), {
|
|
116494
|
+
method: "GET",
|
|
116495
|
+
token,
|
|
116496
|
+
signal: ctx.abortSignal
|
|
116497
|
+
});
|
|
116498
|
+
if (res.status === 429) {
|
|
116499
|
+
return {
|
|
116500
|
+
success: false,
|
|
116501
|
+
error: "The shared Mobile OTP number is busy. Retry the reservation later; this tool does not wait."
|
|
116502
|
+
};
|
|
116503
|
+
}
|
|
116504
|
+
if (res.status === 403) {
|
|
116505
|
+
return {
|
|
116506
|
+
success: false,
|
|
116507
|
+
error: "No Mobile OTP receiving number is configured for this session."
|
|
116508
|
+
};
|
|
116509
|
+
}
|
|
116510
|
+
if (res.status === 409) {
|
|
116511
|
+
return {
|
|
116512
|
+
success: false,
|
|
116513
|
+
error: "That SMS was already claimed. List without claim, or wait for a newer message."
|
|
116514
|
+
};
|
|
116515
|
+
}
|
|
116516
|
+
if (!res.ok) {
|
|
116517
|
+
throw new Error(`SMS list API error ${res.status} ${res.statusText}`);
|
|
116518
|
+
}
|
|
116519
|
+
const data = await res.json();
|
|
116520
|
+
return {
|
|
116521
|
+
success: true,
|
|
116522
|
+
messages: data.messages,
|
|
116523
|
+
claimed: data.claimed
|
|
116524
|
+
};
|
|
116525
|
+
}
|
|
116526
|
+
});
|
|
116527
|
+
}
|
|
116528
|
+
|
|
116302
116529
|
// src/core/utils/concurrency.ts
|
|
116303
116530
|
var import_api = __toESM(require_src(), 1);
|
|
116304
116531
|
async function runWithBoundedConcurrency(items, concurrency, fn, abortSignal) {
|
|
@@ -117817,7 +118044,7 @@ Returns an array of results with the text output from each agent.`,
|
|
|
117817
118044
|
});
|
|
117818
118045
|
}
|
|
117819
118046
|
async function runSingleCodingAgent(ctx, codebasePath, objective, agentIndex, name) {
|
|
117820
|
-
const { CodeAgent } = await import("./agent-
|
|
118047
|
+
const { CodeAgent } = await import("./agent-z3ydv420.js");
|
|
117821
118048
|
const childSessionId = newSessionId();
|
|
117822
118049
|
const subagentId = childSessionId;
|
|
117823
118050
|
ctx.eventBus?.emit("subagent-spawn", {
|
|
@@ -118298,13 +118525,17 @@ init_dist();
|
|
|
118298
118525
|
init_zod();
|
|
118299
118526
|
init_id();
|
|
118300
118527
|
var WORKER_DRAIN_GRACE_MS = 30000;
|
|
118528
|
+
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.`;
|
|
118301
118529
|
function spawnPentestAgent(ctx) {
|
|
118530
|
+
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.";
|
|
118302
118531
|
return tool({
|
|
118303
118532
|
description: `Spawn a single focused pentest sub-agent (worker) to test ONE objective at a time.
|
|
118304
118533
|
|
|
118305
118534
|
Use this AFTER stating your plan and performing light reconnaissance. Call this tool ONCE PER OBJECTIVE — do not batch objectives into a single spawn, because the UI surfaces each spawn as its own timeline.
|
|
118306
118535
|
|
|
118307
|
-
CRITICAL — \`target\` must be
|
|
118536
|
+
CRITICAL — \`target\` must be a FULL URL including the endpoint path the caller wants tested (e.g. https://example.com/api/users/{id}), not a bare domain. Use the orchestrator's assigned URL by default. Recon-supported sibling endpoints are allowed for a follow-up objective. ${targetScopeGuidance} Never invent a host or endpoint.
|
|
118537
|
+
|
|
118538
|
+
Authentication state is origin-specific. Before spawning a cross-service worker that needs authentication, establish and verify a session on its target origin and describe that status in \`context\`. The worker must verify protected access on its assigned origin. ${ORIGIN_AUTH_FAILURE_GUIDANCE}
|
|
118308
118539
|
|
|
118309
118540
|
Each spawn produces an independent TargetedPentestAgent that:
|
|
118310
118541
|
1. Tests the assigned objective(s) deeply (execute_command, http_request, browser tools)
|
|
@@ -118322,7 +118553,7 @@ False-positive discipline: workers should not call document_vulnerability for pu
|
|
|
118322
118553
|
Returns the worker's summary, objective results, and finding count — but NOT the findings themselves (those land in the shared registry).`,
|
|
118323
118554
|
inputSchema: exports_external.object({
|
|
118324
118555
|
name: exports_external.string().describe("Short human-readable label for this sub-agent shown in the UI (e.g. 'SQLi /api/users', 'IDOR orders', 'Final chain & explore')."),
|
|
118325
|
-
target: exports_external.string().describe(
|
|
118556
|
+
target: exports_external.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.`),
|
|
118326
118557
|
objectives: exports_external.array(exports_external.string()).min(1).describe("Testing objectives for this worker. For per-objective fan-out, pass exactly one objective. For the final exploratory pass, pass a single composite objective describing chaining + exploration."),
|
|
118327
118558
|
context: exports_external.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."),
|
|
118328
118559
|
toolCallDescription: exports_external.string().describe("Concise, human-readable description of what this spawn is doing (shown in the UI).")
|
|
@@ -118334,7 +118565,21 @@ Returns the worker's summary, objective results, and finding count — but NOT t
|
|
|
118334
118565
|
message: "spawn_pentest_agent requires a model in the tool context."
|
|
118335
118566
|
};
|
|
118336
118567
|
}
|
|
118337
|
-
|
|
118568
|
+
if (typeof target !== "string" || parseTargetUrl(target) === null) {
|
|
118569
|
+
return {
|
|
118570
|
+
success: false,
|
|
118571
|
+
message: `spawn_pentest_agent rejected: "target" is not a valid full URL (received ${JSON.stringify(target)}). ` + `Pass a valid full URL authorized by the assigned target or structured System Scope — do NOT invent, default, or substitute a target.`
|
|
118572
|
+
};
|
|
118573
|
+
}
|
|
118574
|
+
try {
|
|
118575
|
+
assertUrlInScope(target, ctx);
|
|
118576
|
+
} catch (error) {
|
|
118577
|
+
if (error instanceof ScopeViolationError) {
|
|
118578
|
+
return { success: false, message: error.message };
|
|
118579
|
+
}
|
|
118580
|
+
throw error;
|
|
118581
|
+
}
|
|
118582
|
+
const { TargetedPentestAgent } = await import("./agent-092hrrbn.js");
|
|
118338
118583
|
const findingsRegistry = ctx.findingsRegistry ?? FindingsRegistry.fromDirectory(ctx.session.findingsPath, {
|
|
118339
118584
|
model: ctx.model,
|
|
118340
118585
|
authConfig: ctx.authConfig,
|
|
@@ -118365,12 +118610,15 @@ Returns the worker's summary, objective results, and finding count — but NOT t
|
|
|
118365
118610
|
agent = new TargetedPentestAgent({
|
|
118366
118611
|
target,
|
|
118367
118612
|
grpc: workerInheritsGrpc(target, ctx.grpc, ctx.target) ? ctx.grpc : undefined,
|
|
118613
|
+
systemScope: ctx.systemScope,
|
|
118368
118614
|
objectives,
|
|
118369
118615
|
context: enrichedContext,
|
|
118370
118616
|
model: ctx.model,
|
|
118371
118617
|
session: ctx.session,
|
|
118372
118618
|
authConfig: ctx.authConfig,
|
|
118373
118619
|
abortSignal: ctx.abortSignal,
|
|
118620
|
+
onStepFinish: ctx.onStepFinish,
|
|
118621
|
+
onCacheMetrics: ctx.onCacheMetrics,
|
|
118374
118622
|
findingsRegistry,
|
|
118375
118623
|
eventBus: childBus,
|
|
118376
118624
|
subagentId,
|
|
@@ -118429,7 +118677,7 @@ function workerInheritsGrpc(target, grpc, orchestratorTarget) {
|
|
|
118429
118677
|
function buildSharedBrowserSessionContext(existingContext) {
|
|
118430
118678
|
const note = `## Shared Browser Session
|
|
118431
118679
|
You are driving the orchestrator's live Playwright browser (NOT a private copy):
|
|
118432
|
-
- You
|
|
118680
|
+
- You inherit authentication only for origins where the orchestrator established it. Verify protected access on your assigned origin first. ${ORIGIN_AUTH_FAILURE_GUIDANCE}
|
|
118433
118681
|
- Only one agent uses this browser at a time — the orchestrator is paused while you run — so you have exclusive control during your run.
|
|
118434
118682
|
- Your navigations, \`browser_evaluate\` mutations, cookies, and \`localStorage\`/\`sessionStorage\` writes PERSIST in this browser and are visible to the orchestrator and to workers spawned after you. Leave the session in a reasonable state (avoid logging out or wedging the page) when you finish.`;
|
|
118435
118683
|
if (!existingContext || existingContext.trim().length === 0) {
|
|
@@ -118468,7 +118716,7 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
118468
118716
|
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
118469
118717
|
}),
|
|
118470
118718
|
execute: async ({ targets }) => {
|
|
118471
|
-
const { runPentestSwarm, DEFAULT_CONCURRENCY: DEFAULT_CONCURRENCY2 } = await import("./pentest-
|
|
118719
|
+
const { runPentestSwarm, DEFAULT_CONCURRENCY: DEFAULT_CONCURRENCY2 } = await import("./pentest-3w1jgsg7.js");
|
|
118472
118720
|
if (!ctx.model) {
|
|
118473
118721
|
return {
|
|
118474
118722
|
success: false,
|
|
@@ -118490,6 +118738,8 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
118490
118738
|
abortSignal: ctx.abortSignal,
|
|
118491
118739
|
findingsRegistry,
|
|
118492
118740
|
eventBus: ctx.eventBus,
|
|
118741
|
+
onStepFinish: ctx.onStepFinish,
|
|
118742
|
+
onCacheMetrics: ctx.onCacheMetrics,
|
|
118493
118743
|
concurrency: DEFAULT_CONCURRENCY2,
|
|
118494
118744
|
enableThinking: ctx.enableThinking,
|
|
118495
118745
|
thinkingEffort: ctx.thinkingEffort,
|
|
@@ -119104,6 +119354,29 @@ async function handleSearchResponse(response) {
|
|
|
119104
119354
|
// src/core/api/apiClient.ts
|
|
119105
119355
|
init_auth();
|
|
119106
119356
|
init_config();
|
|
119357
|
+
|
|
119358
|
+
// src/core/api/clientIdentity.ts
|
|
119359
|
+
init_installation();
|
|
119360
|
+
var CLIENT_HEADERS = {
|
|
119361
|
+
client: "X-Pensar-Client",
|
|
119362
|
+
version: "X-Pensar-Client-Version",
|
|
119363
|
+
command: "X-Pensar-Command"
|
|
119364
|
+
};
|
|
119365
|
+
var CLIENT_NAME = "cli";
|
|
119366
|
+
var currentCommand;
|
|
119367
|
+
function getCurrentCommand() {
|
|
119368
|
+
return currentCommand;
|
|
119369
|
+
}
|
|
119370
|
+
function clientIdentityHeaders() {
|
|
119371
|
+
const command = getCurrentCommand();
|
|
119372
|
+
return {
|
|
119373
|
+
[CLIENT_HEADERS.client]: CLIENT_NAME,
|
|
119374
|
+
[CLIENT_HEADERS.version]: getCurrentVersion(),
|
|
119375
|
+
...command ? { [CLIENT_HEADERS.command]: command } : {}
|
|
119376
|
+
};
|
|
119377
|
+
}
|
|
119378
|
+
|
|
119379
|
+
// src/core/api/apiClient.ts
|
|
119107
119380
|
init_constants();
|
|
119108
119381
|
async function getAuthHeaders() {
|
|
119109
119382
|
const cfg = await config.get();
|
|
@@ -119117,7 +119390,8 @@ async function getAuthHeaders() {
|
|
|
119117
119390
|
}
|
|
119118
119391
|
const headers = {
|
|
119119
119392
|
"Content-Type": "application/json",
|
|
119120
|
-
Authorization: `Bearer ${validToken.token}
|
|
119393
|
+
Authorization: `Bearer ${validToken.token}`,
|
|
119394
|
+
...clientIdentityHeaders()
|
|
119121
119395
|
};
|
|
119122
119396
|
if (cfg.workspaceId) {
|
|
119123
119397
|
headers["X-Workspace-Id"] = cfg.workspaceId;
|
|
@@ -119151,6 +119425,12 @@ async function apiRequest(method, path, body) {
|
|
|
119151
119425
|
}
|
|
119152
119426
|
|
|
119153
119427
|
// src/core/api/apps.ts
|
|
119428
|
+
var ENDPOINT_TRANSPORTS = [
|
|
119429
|
+
"http",
|
|
119430
|
+
"grpc",
|
|
119431
|
+
"grpc_web",
|
|
119432
|
+
"connect"
|
|
119433
|
+
];
|
|
119154
119434
|
async function listApps(opts) {
|
|
119155
119435
|
const params = new URLSearchParams;
|
|
119156
119436
|
if (opts?.limit !== undefined)
|
|
@@ -119263,7 +119543,7 @@ var ENDPOINT_TYPES = [
|
|
|
119263
119543
|
"file-storage",
|
|
119264
119544
|
"asset"
|
|
119265
119545
|
];
|
|
119266
|
-
var
|
|
119546
|
+
var ENDPOINT_TRANSPORTS2 = [
|
|
119267
119547
|
"http",
|
|
119268
119548
|
"grpc",
|
|
119269
119549
|
"grpc_web",
|
|
@@ -119309,7 +119589,7 @@ var createWorkspaceEndpointInputSchema = exports_external.object({
|
|
|
119309
119589
|
endpoint: exports_external.string().min(1).describe("Endpoint path, URL, or route"),
|
|
119310
119590
|
description: exports_external.string().describe("Endpoint description"),
|
|
119311
119591
|
type: exports_external.enum(ENDPOINT_TYPES).optional(),
|
|
119312
|
-
transport: exports_external.enum(
|
|
119592
|
+
transport: exports_external.enum(ENDPOINT_TRANSPORTS2).nullish().transform((value) => value ?? undefined).optional().describe("Wire transport; defaults to http when omitted"),
|
|
119313
119593
|
location: exports_external.string().optional().describe("Source file path"),
|
|
119314
119594
|
startLineNumber: exports_external.number().int().min(0).optional(),
|
|
119315
119595
|
endLineNumber: exports_external.number().int().min(0).optional(),
|
|
@@ -119328,7 +119608,7 @@ var updateWorkspaceEndpointInputSchema = exports_external.object({
|
|
|
119328
119608
|
endpoint: exports_external.string().min(1).nullish().transform((value) => value ?? undefined).optional(),
|
|
119329
119609
|
description: exports_external.string().nullish().transform((value) => value ?? undefined).optional(),
|
|
119330
119610
|
type: exports_external.enum(ENDPOINT_TYPES).nullable().optional(),
|
|
119331
|
-
transport: exports_external.enum(
|
|
119611
|
+
transport: exports_external.enum(ENDPOINT_TRANSPORTS2).nullish().transform((value) => value ?? undefined).optional().describe("Corrected wire transport"),
|
|
119332
119612
|
location: exports_external.string().nullable().optional(),
|
|
119333
119613
|
startLineNumber: exports_external.number().int().min(0).nullable().optional(),
|
|
119334
119614
|
endLineNumber: exports_external.number().int().min(0).nullable().optional(),
|
|
@@ -119456,10 +119736,6 @@ Use only when the user explicitly asks to change or repair an existing workspace
|
|
|
119456
119736
|
});
|
|
119457
119737
|
}
|
|
119458
119738
|
|
|
119459
|
-
// src/core/agents/offSecAgent/tools/workspaceDomains.ts
|
|
119460
|
-
init_dist();
|
|
119461
|
-
init_zod();
|
|
119462
|
-
|
|
119463
119739
|
// src/core/api/domains.ts
|
|
119464
119740
|
async function listDomains() {
|
|
119465
119741
|
return apiRequest("GET", "/domains");
|
|
@@ -119469,6 +119745,8 @@ async function createDomain(data) {
|
|
|
119469
119745
|
}
|
|
119470
119746
|
|
|
119471
119747
|
// src/core/agents/offSecAgent/tools/workspaceDomains.ts
|
|
119748
|
+
init_dist();
|
|
119749
|
+
init_zod();
|
|
119472
119750
|
var toolCallDescription2 = exports_external.string().describe("A concise description of the workspace operation");
|
|
119473
119751
|
var listWorkspaceDomainsInputSchema = exports_external.object({
|
|
119474
119752
|
toolCallDescription: toolCallDescription2
|
|
@@ -124352,6 +124630,7 @@ function createAllTools(ctx) {
|
|
|
124352
124630
|
email_list_messages: emailListMessages(ctx),
|
|
124353
124631
|
email_search_messages: emailSearchMessages(ctx),
|
|
124354
124632
|
email_get_message: emailGetMessage(ctx),
|
|
124633
|
+
sms_list_messages: smsListMessages(ctx),
|
|
124355
124634
|
web_search: webSearch(ctx),
|
|
124356
124635
|
get_page: getPage(ctx),
|
|
124357
124636
|
...ctx.skillsRegistry ? { read_skill: readSkill(ctx) } : {},
|
|
@@ -124439,6 +124718,7 @@ var ALL_TOOL_NAMES = [
|
|
|
124439
124718
|
"email_get_attachments",
|
|
124440
124719
|
"email_mark_read",
|
|
124441
124720
|
"send_email",
|
|
124721
|
+
"sms_list_messages",
|
|
124442
124722
|
"web_search",
|
|
124443
124723
|
"get_page",
|
|
124444
124724
|
"checkpoint_state",
|
|
@@ -124510,6 +124790,7 @@ var PLAN_MODE_TOOL_NAMES = [
|
|
|
124510
124790
|
"email_get_message",
|
|
124511
124791
|
"email_search_messages",
|
|
124512
124792
|
"email_get_attachments",
|
|
124793
|
+
"sms_list_messages",
|
|
124513
124794
|
"web_search",
|
|
124514
124795
|
"get_page",
|
|
124515
124796
|
"write_plan",
|
|
@@ -124521,6 +124802,7 @@ var PLAN_MODE_TOOL_NAMES = [
|
|
|
124521
124802
|
var SKILL_TOOL_NAMES = ["read_skill"];
|
|
124522
124803
|
|
|
124523
124804
|
// src/core/agents/offSecAgent/trace.ts
|
|
124805
|
+
init_observability();
|
|
124524
124806
|
import { createHash as createHash2 } from "node:crypto";
|
|
124525
124807
|
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync13 } from "node:fs";
|
|
124526
124808
|
import { dirname as dirname8 } from "node:path";
|
|
@@ -124707,13 +124989,15 @@ class StepTraceWriter {
|
|
|
124707
124989
|
this.appendRecord(record3);
|
|
124708
124990
|
}
|
|
124709
124991
|
appendRecord(record3) {
|
|
124992
|
+
const correlation = getActiveTraceCorrelation();
|
|
124993
|
+
const enriched = correlation ? { ...record3, correlation } : record3;
|
|
124710
124994
|
try {
|
|
124711
|
-
appendFileSync3(this.tracePath, `${JSON.stringify(
|
|
124995
|
+
appendFileSync3(this.tracePath, `${JSON.stringify(enriched)}
|
|
124712
124996
|
`);
|
|
124713
124997
|
} catch {}
|
|
124714
124998
|
try {
|
|
124715
124999
|
this.eventBus?.emit("trace-record", {
|
|
124716
|
-
record:
|
|
125000
|
+
record: enriched,
|
|
124717
125001
|
subagentId: this.agentId ?? undefined
|
|
124718
125002
|
});
|
|
124719
125003
|
} catch {}
|
|
@@ -124723,8 +125007,8 @@ class StepTraceWriter {
|
|
|
124723
125007
|
// src/core/agents/offSecAgent/offensiveSecurityAgent.ts
|
|
124724
125008
|
init_dist();
|
|
124725
125009
|
init_ai();
|
|
124726
|
-
|
|
124727
|
-
import {
|
|
125010
|
+
var import_api2 = __toESM(require_src(), 1);
|
|
125011
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync14 } from "node:fs";
|
|
124728
125012
|
import { join as join27 } from "node:path";
|
|
124729
125013
|
init_id();
|
|
124730
125014
|
init_structured();
|
|
@@ -125006,9 +125290,464 @@ var OperatorSettingsObject = exports_external.object({
|
|
|
125006
125290
|
// src/core/agents/offSecAgent/offensiveSecurityAgent.ts
|
|
125007
125291
|
init_session();
|
|
125008
125292
|
init_lazyLogger();
|
|
125009
|
-
|
|
125293
|
+
|
|
125294
|
+
// src/core/agents/offSecAgent/interruptedStepFinalization.ts
|
|
125295
|
+
import { existsSync as existsSync18, readFileSync as readFileSync8 } from "node:fs";
|
|
125296
|
+
|
|
125297
|
+
// src/core/agents/offSecAgent/interruptedStepMessages.ts
|
|
125298
|
+
function buildSyntheticToolResults(input) {
|
|
125299
|
+
const output = {
|
|
125300
|
+
type: "error-text",
|
|
125301
|
+
value: `Tool execution aborted: ${input.reason}`
|
|
125302
|
+
};
|
|
125303
|
+
const parts = [];
|
|
125304
|
+
for (const [toolCallId, toolName] of input.inFlightTools) {
|
|
125305
|
+
const result = toolName === input.responseToolName && input.responseSubmitted ? { type: "text", value: "Response submitted." } : output;
|
|
125306
|
+
parts.push({
|
|
125307
|
+
type: "tool-result",
|
|
125308
|
+
toolCallId,
|
|
125309
|
+
toolName,
|
|
125310
|
+
output: result
|
|
125311
|
+
});
|
|
125312
|
+
}
|
|
125313
|
+
return parts;
|
|
125314
|
+
}
|
|
125315
|
+
function baseContainsToolCalls(msg, toolCallIds) {
|
|
125316
|
+
if (!Array.isArray(msg.content))
|
|
125317
|
+
return false;
|
|
125318
|
+
const contentToolIds = new Set(msg.content.filter((p) => p.type === "tool-call" && p.toolCallId).map((p) => p.toolCallId));
|
|
125319
|
+
return [...toolCallIds].every((id) => contentToolIds.has(id));
|
|
125320
|
+
}
|
|
125321
|
+
function buildInterruptedStepMessages(input) {
|
|
125322
|
+
const { base, inFlightTools, completedResults, syntheticParts } = input;
|
|
125323
|
+
const allToolCallIds = new Set([
|
|
125324
|
+
...inFlightTools.keys(),
|
|
125325
|
+
...completedResults.map((r) => r.toolCallId)
|
|
125326
|
+
]);
|
|
125327
|
+
const lastMsg = base[base.length - 1];
|
|
125328
|
+
const needsStepReconstruction = !lastMsg || lastMsg.role !== "assistant" || !baseContainsToolCalls(lastMsg, allToolCallIds);
|
|
125329
|
+
const appended = [];
|
|
125330
|
+
if (needsStepReconstruction) {
|
|
125331
|
+
const stepTools = [
|
|
125332
|
+
...inFlightTools,
|
|
125333
|
+
...completedResults.map((r) => [
|
|
125334
|
+
r.toolCallId,
|
|
125335
|
+
r.toolName
|
|
125336
|
+
])
|
|
125337
|
+
];
|
|
125338
|
+
const reconstructInput = (toolCallId) => {
|
|
125339
|
+
const raw = input.streamedArgText?.get(toolCallId);
|
|
125340
|
+
if (!raw)
|
|
125341
|
+
return {};
|
|
125342
|
+
try {
|
|
125343
|
+
return JSON.parse(raw);
|
|
125344
|
+
} catch {
|
|
125345
|
+
return { _partial: raw };
|
|
125346
|
+
}
|
|
125347
|
+
};
|
|
125348
|
+
appended.push({
|
|
125349
|
+
role: "assistant",
|
|
125350
|
+
content: stepTools.map(([toolCallId, toolName]) => ({
|
|
125351
|
+
type: "tool-call",
|
|
125352
|
+
toolCallId,
|
|
125353
|
+
toolName,
|
|
125354
|
+
input: reconstructInput(toolCallId)
|
|
125355
|
+
}))
|
|
125356
|
+
});
|
|
125357
|
+
}
|
|
125358
|
+
appended.push({
|
|
125359
|
+
role: "tool",
|
|
125360
|
+
content: [...completedResults, ...syntheticParts]
|
|
125361
|
+
});
|
|
125362
|
+
return { appended, needsStepReconstruction };
|
|
125363
|
+
}
|
|
125364
|
+
|
|
125365
|
+
// src/core/agents/offSecAgent/interruptedStepFinalization.ts
|
|
125366
|
+
function createInterruptedStepFinalizer(deps) {
|
|
125367
|
+
const debug = deps.debugLog;
|
|
125368
|
+
const readBaseFromDisk = deps.readBaseFromDisk ?? (() => {
|
|
125369
|
+
const path = deps.writer.messagesPath;
|
|
125370
|
+
if (!path || !existsSync18(path))
|
|
125371
|
+
return null;
|
|
125372
|
+
try {
|
|
125373
|
+
return JSON.parse(readFileSync8(path, "utf-8"));
|
|
125374
|
+
} catch {
|
|
125375
|
+
return null;
|
|
125376
|
+
}
|
|
125377
|
+
});
|
|
125378
|
+
return async (input) => {
|
|
125379
|
+
const { snapshot, reason } = input;
|
|
125380
|
+
const { inFlightTools, completedResults, streamedArgText } = snapshot;
|
|
125381
|
+
const syntheticParts = buildSyntheticToolResults({
|
|
125382
|
+
inFlightTools,
|
|
125383
|
+
reason,
|
|
125384
|
+
responseToolName: deps.responseToolName,
|
|
125385
|
+
responseSubmitted: deps.responseToolFired()
|
|
125386
|
+
});
|
|
125387
|
+
let emissionError;
|
|
125388
|
+
let hasEmissionError = false;
|
|
125389
|
+
if (debug) {
|
|
125390
|
+
const responseInFlight = [...inFlightTools.entries()].filter(([, n7]) => n7 === deps.responseToolName);
|
|
125391
|
+
if (responseInFlight.length > 0) {
|
|
125392
|
+
debug(`[response-debug] emitSyntheticToolResults closing ${responseInFlight.length} response call(s) ` + `ids=${responseInFlight.map(([id]) => id).join(",")} reason="${reason}" ` + `responseToolFired=${deps.responseToolFired()}`);
|
|
125393
|
+
}
|
|
125394
|
+
}
|
|
125395
|
+
for (const part of syntheticParts) {
|
|
125396
|
+
try {
|
|
125397
|
+
deps.eventBus.emit("tool-result", {
|
|
125398
|
+
toolCallId: part.toolCallId,
|
|
125399
|
+
toolName: part.toolName,
|
|
125400
|
+
result: part.output,
|
|
125401
|
+
sessionId: deps.sessionId,
|
|
125402
|
+
subagentId: deps.subagentId,
|
|
125403
|
+
partId: input.partIdFor?.(part.toolCallId),
|
|
125404
|
+
messageId: input.messageId
|
|
125405
|
+
});
|
|
125406
|
+
} catch (error) {
|
|
125407
|
+
if (!hasEmissionError) {
|
|
125408
|
+
emissionError = error;
|
|
125409
|
+
hasEmissionError = true;
|
|
125410
|
+
}
|
|
125411
|
+
}
|
|
125412
|
+
}
|
|
125413
|
+
if (!deps.writer.messagesPath) {
|
|
125414
|
+
if (hasEmissionError)
|
|
125415
|
+
throw emissionError;
|
|
125416
|
+
return;
|
|
125417
|
+
}
|
|
125418
|
+
deps.writer.cancelTimer();
|
|
125419
|
+
await deps.writer.waitForPendingWrites();
|
|
125420
|
+
let base = deps.writer.latest ?? [];
|
|
125421
|
+
if (base.length === 0) {
|
|
125422
|
+
base = readBaseFromDisk() ?? [];
|
|
125423
|
+
}
|
|
125424
|
+
const { appended, needsStepReconstruction } = buildInterruptedStepMessages({
|
|
125425
|
+
base,
|
|
125426
|
+
inFlightTools,
|
|
125427
|
+
completedResults,
|
|
125428
|
+
syntheticParts,
|
|
125429
|
+
streamedArgText
|
|
125430
|
+
});
|
|
125431
|
+
if (needsStepReconstruction && debug) {
|
|
125432
|
+
const responseReconstructed = [
|
|
125433
|
+
...inFlightTools,
|
|
125434
|
+
...completedResults.map((r) => [r.toolCallId, r.toolName])
|
|
125435
|
+
].filter(([, n7]) => n7 === deps.responseToolName).map(([id]) => id);
|
|
125436
|
+
if (responseReconstructed.length > 0) {
|
|
125437
|
+
debug(`[response-debug] step-reconstruction for response call(s) ` + `ids=${responseReconstructed.join(",")} ` + `preservedArgChars=${responseReconstructed.map((id) => streamedArgText?.get(id)?.length ?? 0).join(",")}`);
|
|
125438
|
+
}
|
|
125439
|
+
}
|
|
125440
|
+
const next = [...base, ...appended];
|
|
125441
|
+
deps.writer.setLatest(next);
|
|
125442
|
+
try {
|
|
125443
|
+
await deps.writer.enqueueWrite(next);
|
|
125444
|
+
deps.writer.markSyntheticsPersisted();
|
|
125445
|
+
} catch {}
|
|
125446
|
+
if (hasEmissionError)
|
|
125447
|
+
throw emissionError;
|
|
125448
|
+
};
|
|
125449
|
+
}
|
|
125450
|
+
|
|
125451
|
+
// src/core/agents/offSecAgent/messagePersistence.ts
|
|
125452
|
+
import { writeFile as writeFile7 } from "node:fs/promises";
|
|
125453
|
+
var PERSIST_INTERVAL_MS = 15000;
|
|
125454
|
+
|
|
125455
|
+
class AgentMessageWriter {
|
|
125456
|
+
intervalMs;
|
|
125457
|
+
writeImpl;
|
|
125458
|
+
path;
|
|
125459
|
+
pending = null;
|
|
125460
|
+
tail = Promise.resolve();
|
|
125461
|
+
persistTimer = null;
|
|
125462
|
+
syntheticsWritten = false;
|
|
125463
|
+
constructor(options) {
|
|
125464
|
+
this.path = options.messagesPath;
|
|
125465
|
+
this.intervalMs = options.intervalMs ?? PERSIST_INTERVAL_MS;
|
|
125466
|
+
this.writeImpl = options.writeImpl ?? ((p, contents) => writeFile7(p, contents));
|
|
125467
|
+
}
|
|
125468
|
+
get messagesPath() {
|
|
125469
|
+
return this.path;
|
|
125470
|
+
}
|
|
125471
|
+
get latest() {
|
|
125472
|
+
return this.pending;
|
|
125473
|
+
}
|
|
125474
|
+
setLatest(messages) {
|
|
125475
|
+
this.pending = messages;
|
|
125476
|
+
}
|
|
125477
|
+
get syntheticsPersisted() {
|
|
125478
|
+
return this.syntheticsWritten;
|
|
125479
|
+
}
|
|
125480
|
+
markSyntheticsPersisted() {
|
|
125481
|
+
this.syntheticsWritten = true;
|
|
125482
|
+
}
|
|
125483
|
+
schedulePersist() {
|
|
125484
|
+
if (this.persistTimer)
|
|
125485
|
+
return;
|
|
125486
|
+
this.persistTimer = setTimeout(() => {
|
|
125487
|
+
this.persistTimer = null;
|
|
125488
|
+
const toWrite = this.pending;
|
|
125489
|
+
if (!toWrite)
|
|
125490
|
+
return;
|
|
125491
|
+
this.enqueueWrite(toWrite).then(() => {
|
|
125492
|
+
if (this.pending === toWrite)
|
|
125493
|
+
this.pending = null;
|
|
125494
|
+
}).catch(() => {});
|
|
125495
|
+
}, this.intervalMs);
|
|
125496
|
+
}
|
|
125497
|
+
cancelTimer() {
|
|
125498
|
+
if (this.persistTimer) {
|
|
125499
|
+
clearTimeout(this.persistTimer);
|
|
125500
|
+
this.persistTimer = null;
|
|
125501
|
+
}
|
|
125502
|
+
}
|
|
125503
|
+
async enqueueWrite(messages) {
|
|
125504
|
+
const path = this.path;
|
|
125505
|
+
if (!path)
|
|
125506
|
+
return;
|
|
125507
|
+
const contents = JSON.stringify(messages);
|
|
125508
|
+
const write2 = this.tail.then(() => this.writeImpl(path, contents));
|
|
125509
|
+
this.tail = write2.catch(() => {});
|
|
125510
|
+
await write2;
|
|
125511
|
+
}
|
|
125512
|
+
async waitForPendingWrites() {
|
|
125513
|
+
let pending;
|
|
125514
|
+
do {
|
|
125515
|
+
pending = this.tail;
|
|
125516
|
+
await pending;
|
|
125517
|
+
} while (pending !== this.tail);
|
|
125518
|
+
}
|
|
125519
|
+
}
|
|
125520
|
+
|
|
125521
|
+
// src/core/agents/offSecAgent/streamDiagnostics.ts
|
|
125522
|
+
init_structured();
|
|
125523
|
+
init_lazyLogger();
|
|
125524
|
+
var STREAM_STALL_DEBUG = process.env.STREAM_STALL_DEBUG === "1" || process.env.STREAM_STALL_DEBUG === "true";
|
|
125525
|
+
var STREAM_STALL_TICK_MS = 15000;
|
|
125526
|
+
var STREAM_STALL_WARN_MS = 20000;
|
|
125527
|
+
var STREAM_GAP_RECOVERED_MS = 1e4;
|
|
125010
125528
|
var RESPONSE_DEBUG = process.env.RESPONSE_DEBUG === "1" || process.env.RESPONSE_DEBUG === "true";
|
|
125011
125529
|
var rlog = scopedLogger(() => createLogger("response-debug"));
|
|
125530
|
+
function responseArgBytes(input) {
|
|
125531
|
+
if (input == null)
|
|
125532
|
+
return 0;
|
|
125533
|
+
if (typeof input === "string")
|
|
125534
|
+
return input.length;
|
|
125535
|
+
try {
|
|
125536
|
+
return JSON.stringify(input).length;
|
|
125537
|
+
} catch {
|
|
125538
|
+
return -1;
|
|
125539
|
+
}
|
|
125540
|
+
}
|
|
125541
|
+
|
|
125542
|
+
class StreamDiagnostics {
|
|
125543
|
+
opts;
|
|
125544
|
+
stallEnabled;
|
|
125545
|
+
responseDebugEnabled;
|
|
125546
|
+
warn;
|
|
125547
|
+
responseArgChars = new Map;
|
|
125548
|
+
responseSawTerminal = new Map;
|
|
125549
|
+
lastChunkAt = Date.now();
|
|
125550
|
+
lastChunkType = "none";
|
|
125551
|
+
stallStepIndex = -1;
|
|
125552
|
+
stallTimer;
|
|
125553
|
+
constructor(options) {
|
|
125554
|
+
this.opts = options;
|
|
125555
|
+
this.stallEnabled = options.stallEnabled ?? STREAM_STALL_DEBUG;
|
|
125556
|
+
this.responseDebugEnabled = options.responseDebugEnabled ?? RESPONSE_DEBUG;
|
|
125557
|
+
this.warn = options.warn ?? ((message) => rlog.warn(message));
|
|
125558
|
+
}
|
|
125559
|
+
start() {
|
|
125560
|
+
if (!this.stallEnabled || this.stallTimer)
|
|
125561
|
+
return;
|
|
125562
|
+
const label = this.opts.sessionId;
|
|
125563
|
+
const sid = this.opts.subagentId;
|
|
125564
|
+
this.stallTimer = setInterval(() => {
|
|
125565
|
+
const gap = Date.now() - this.lastChunkAt;
|
|
125566
|
+
if (gap > STREAM_STALL_WARN_MS) {
|
|
125567
|
+
this.warn(`[stream-stall] no chunk for ${Math.round(gap / 1000)}s ` + `session=${label} subagent=${sid ?? "-"} step=${this.stallStepIndex} ` + `lastChunkType=${this.lastChunkType} ` + `inFlightTools=${[...this.opts.inFlightTools().values()].join(",")} ` + `responseToolFired=${this.opts.responseToolFired()}`);
|
|
125568
|
+
}
|
|
125569
|
+
}, STREAM_STALL_TICK_MS);
|
|
125570
|
+
}
|
|
125571
|
+
observeChunk(chunk) {
|
|
125572
|
+
if (this.stallEnabled) {
|
|
125573
|
+
const now = Date.now();
|
|
125574
|
+
const gap = now - this.lastChunkAt;
|
|
125575
|
+
this.lastChunkAt = now;
|
|
125576
|
+
this.lastChunkType = chunk.type;
|
|
125577
|
+
if (chunk.type === "start-step")
|
|
125578
|
+
this.stallStepIndex++;
|
|
125579
|
+
if (gap > STREAM_GAP_RECOVERED_MS) {
|
|
125580
|
+
this.warn(`[stream-gap] recovered after ${Math.round(gap / 1000)}s ` + `session=${this.opts.sessionId} chunkType=${chunk.type}`);
|
|
125581
|
+
}
|
|
125582
|
+
}
|
|
125583
|
+
if (this.responseDebugEnabled) {
|
|
125584
|
+
this.traceResponseTool(chunk);
|
|
125585
|
+
}
|
|
125586
|
+
}
|
|
125587
|
+
logSurfacedToolError(info) {
|
|
125588
|
+
if (!this.responseDebugEnabled)
|
|
125589
|
+
return;
|
|
125590
|
+
if (info.toolName !== this.opts.responseToolName)
|
|
125591
|
+
return;
|
|
125592
|
+
this.warn(`[response-debug] tool-error SURFACED id=${info.toolCallId} ` + `streamedArgChars=${info.streamedArgChars} ` + `finishReason=${info.finishReason ?? "unknown"} ` + `outputTokenTruncated=${info.truncated} error=${info.message.slice(0, 300)}`);
|
|
125593
|
+
}
|
|
125594
|
+
logClosingInFlightTool(info) {
|
|
125595
|
+
if (!this.responseDebugEnabled)
|
|
125596
|
+
return;
|
|
125597
|
+
if (info.toolName !== this.opts.responseToolName)
|
|
125598
|
+
return;
|
|
125599
|
+
this.warn(`[response-debug] CLOSING response as "did not complete" id=${info.toolCallId} ` + `streamedArgChars=${this.responseArgChars.get(info.toolCallId) ?? 0} ` + `sawTerminalChunk=${this.responseSawTerminal.get(info.toolCallId) ?? "none"} ` + `finishReason=${info.finishReason ?? "unknown"} outputTokenTruncated=${info.truncated} ` + `responseToolFired=${this.opts.responseToolFired()}`);
|
|
125600
|
+
}
|
|
125601
|
+
stop() {
|
|
125602
|
+
if (this.stallTimer)
|
|
125603
|
+
clearInterval(this.stallTimer);
|
|
125604
|
+
this.stallTimer = undefined;
|
|
125605
|
+
}
|
|
125606
|
+
traceResponseTool(chunk) {
|
|
125607
|
+
const idForChunk = chunk.toolCallId ?? chunk.id;
|
|
125608
|
+
const nameForChunk = chunk.toolName ?? (idForChunk ? this.opts.inFlightTools().get(idForChunk) : undefined);
|
|
125609
|
+
if (nameForChunk !== this.opts.responseToolName || !idForChunk) {
|
|
125610
|
+
if (chunk.type === "finish-step") {
|
|
125611
|
+
const responseInFlight = [...this.opts.inFlightTools().entries()].filter(([, n7]) => n7 === this.opts.responseToolName).map(([id]) => id).join(",");
|
|
125612
|
+
if (responseInFlight) {
|
|
125613
|
+
this.warn(`[response-debug] finish-step finishReason=${chunk.finishReason} ` + `responseInFlight=${responseInFlight} ` + `responseToolFired=${this.opts.responseToolFired()}`);
|
|
125614
|
+
}
|
|
125615
|
+
}
|
|
125616
|
+
return;
|
|
125617
|
+
}
|
|
125618
|
+
switch (chunk.type) {
|
|
125619
|
+
case "tool-input-start":
|
|
125620
|
+
this.responseArgChars.set(idForChunk, 0);
|
|
125621
|
+
this.warn(`[response-debug] tool-input-start id=${idForChunk} session=${this.opts.subagentId ?? this.opts.sessionId}`);
|
|
125622
|
+
break;
|
|
125623
|
+
case "tool-input-delta":
|
|
125624
|
+
this.responseArgChars.set(idForChunk, (this.responseArgChars.get(idForChunk) ?? 0) + (chunk.delta?.length ?? 0));
|
|
125625
|
+
break;
|
|
125626
|
+
case "tool-input-end":
|
|
125627
|
+
this.warn(`[response-debug] tool-input-end id=${idForChunk} argChars=${this.responseArgChars.get(idForChunk) ?? 0}`);
|
|
125628
|
+
break;
|
|
125629
|
+
case "tool-call": {
|
|
125630
|
+
this.responseSawTerminal.set(idForChunk, "tool-call");
|
|
125631
|
+
const inputBytes = responseArgBytes(chunk.input ?? chunk.args);
|
|
125632
|
+
this.warn(`[response-debug] tool-call id=${idForChunk} streamedArgChars=${this.responseArgChars.get(idForChunk) ?? 0} parsedInputBytes=${inputBytes} invalid=${chunk.invalid === true}`);
|
|
125633
|
+
break;
|
|
125634
|
+
}
|
|
125635
|
+
case "tool-error": {
|
|
125636
|
+
this.responseSawTerminal.set(idForChunk, "tool-error");
|
|
125637
|
+
const errMsg = chunk.error instanceof Error ? chunk.error.message : typeof chunk.error === "string" ? chunk.error : JSON.stringify(chunk.error)?.slice(0, 300);
|
|
125638
|
+
this.warn(`[response-debug] tool-error id=${idForChunk} streamedArgChars=${this.responseArgChars.get(idForChunk) ?? 0} stillInFlight=${this.opts.inFlightTools().has(idForChunk)} error=${errMsg}`);
|
|
125639
|
+
break;
|
|
125640
|
+
}
|
|
125641
|
+
case "tool-result":
|
|
125642
|
+
this.responseSawTerminal.set(idForChunk, "tool-result");
|
|
125643
|
+
this.warn(`[response-debug] tool-result id=${idForChunk} streamedArgChars=${this.responseArgChars.get(idForChunk) ?? 0}`);
|
|
125644
|
+
break;
|
|
125645
|
+
}
|
|
125646
|
+
}
|
|
125647
|
+
}
|
|
125648
|
+
|
|
125649
|
+
// src/core/agents/offSecAgent/toolLifecycle.ts
|
|
125650
|
+
class ToolLifecycleTracker {
|
|
125651
|
+
inFlight = new Map;
|
|
125652
|
+
completed = [];
|
|
125653
|
+
streamedArgs = new Map;
|
|
125654
|
+
errors = new Map;
|
|
125655
|
+
observePart(chunk) {
|
|
125656
|
+
switch (chunk.type) {
|
|
125657
|
+
case "tool-input-start":
|
|
125658
|
+
this.inFlight.set(chunk.id, chunk.toolName);
|
|
125659
|
+
this.streamedArgs.set(chunk.id, "");
|
|
125660
|
+
break;
|
|
125661
|
+
case "tool-input-delta":
|
|
125662
|
+
this.streamedArgs.set(chunk.id, (this.streamedArgs.get(chunk.id) ?? "") + (chunk.delta ?? ""));
|
|
125663
|
+
break;
|
|
125664
|
+
case "tool-call":
|
|
125665
|
+
this.inFlight.set(chunk.toolCallId, chunk.toolName);
|
|
125666
|
+
break;
|
|
125667
|
+
case "tool-error": {
|
|
125668
|
+
const toolCallId = chunk.toolCallId;
|
|
125669
|
+
this.inFlight.delete(toolCallId);
|
|
125670
|
+
const errMsg = chunk.error instanceof Error ? chunk.error.message : typeof chunk.error === "string" ? chunk.error : (() => {
|
|
125671
|
+
try {
|
|
125672
|
+
return JSON.stringify(chunk.error);
|
|
125673
|
+
} catch {
|
|
125674
|
+
return String(chunk.error);
|
|
125675
|
+
}
|
|
125676
|
+
})();
|
|
125677
|
+
const partialArgs = chunk.input !== undefined && chunk.input !== null && responseArgBytes(chunk.input) > 2 ? chunk.input : this.streamedArgs.get(toolCallId) ?? "";
|
|
125678
|
+
this.errors.set(toolCallId, {
|
|
125679
|
+
message: errMsg,
|
|
125680
|
+
input: partialArgs,
|
|
125681
|
+
toolName: chunk.toolName
|
|
125682
|
+
});
|
|
125683
|
+
break;
|
|
125684
|
+
}
|
|
125685
|
+
case "tool-result":
|
|
125686
|
+
this.inFlight.delete(chunk.toolCallId);
|
|
125687
|
+
this.completed.push({
|
|
125688
|
+
type: "tool-result",
|
|
125689
|
+
toolCallId: chunk.toolCallId,
|
|
125690
|
+
toolName: chunk.toolName,
|
|
125691
|
+
output: chunk.result ?? chunk.output
|
|
125692
|
+
});
|
|
125693
|
+
break;
|
|
125694
|
+
}
|
|
125695
|
+
}
|
|
125696
|
+
onStepPersisted() {
|
|
125697
|
+
this.completed.length = 0;
|
|
125698
|
+
}
|
|
125699
|
+
flushToolErrorsToResults() {
|
|
125700
|
+
const flushed = [];
|
|
125701
|
+
for (const [toolCallId, info] of this.errors) {
|
|
125702
|
+
this.completed.push({
|
|
125703
|
+
type: "tool-result",
|
|
125704
|
+
toolCallId,
|
|
125705
|
+
toolName: info.toolName,
|
|
125706
|
+
output: {
|
|
125707
|
+
type: "error-text",
|
|
125708
|
+
value: `Tool call failed: ${info.message}`
|
|
125709
|
+
}
|
|
125710
|
+
});
|
|
125711
|
+
flushed.push([toolCallId, info]);
|
|
125712
|
+
}
|
|
125713
|
+
this.errors.clear();
|
|
125714
|
+
return flushed;
|
|
125715
|
+
}
|
|
125716
|
+
clearToolErrors() {
|
|
125717
|
+
this.errors.clear();
|
|
125718
|
+
}
|
|
125719
|
+
clearInFlight() {
|
|
125720
|
+
this.inFlight.clear();
|
|
125721
|
+
}
|
|
125722
|
+
hasUnpersistedState() {
|
|
125723
|
+
return this.inFlight.size > 0 || this.completed.length > 0;
|
|
125724
|
+
}
|
|
125725
|
+
get inFlightTools() {
|
|
125726
|
+
return this.inFlight;
|
|
125727
|
+
}
|
|
125728
|
+
get toolErrors() {
|
|
125729
|
+
return this.errors;
|
|
125730
|
+
}
|
|
125731
|
+
get completedResults() {
|
|
125732
|
+
return this.completed;
|
|
125733
|
+
}
|
|
125734
|
+
get streamedArgText() {
|
|
125735
|
+
return this.streamedArgs;
|
|
125736
|
+
}
|
|
125737
|
+
snapshot() {
|
|
125738
|
+
return {
|
|
125739
|
+
inFlightTools: new Map(this.inFlight),
|
|
125740
|
+
completedResults: this.completed.map((r) => ({ ...r })),
|
|
125741
|
+
streamedArgText: new Map(this.streamedArgs),
|
|
125742
|
+
toolErrors: new Map(this.errors)
|
|
125743
|
+
};
|
|
125744
|
+
}
|
|
125745
|
+
}
|
|
125746
|
+
|
|
125747
|
+
// src/core/agents/offSecAgent/offensiveSecurityAgent.ts
|
|
125748
|
+
var log13 = scopedLogger(() => createLogger("approval-gate"));
|
|
125749
|
+
var RESPONSE_DEBUG2 = process.env.RESPONSE_DEBUG === "1" || process.env.RESPONSE_DEBUG === "true";
|
|
125750
|
+
var rlog2 = scopedLogger(() => createLogger("response-debug"));
|
|
125012
125751
|
var WORKSPACE_TOOL_NAME_SET = new Set(WORKSPACE_TOOL_NAMES);
|
|
125013
125752
|
var WORKSPACE_WRITE_TOOL_NAME_SET = new Set(WORKSPACE_WRITE_TOOL_NAMES);
|
|
125014
125753
|
var WORKSPACE_TARGET_RE = /\b(?:console|workspace)\b/i;
|
|
@@ -125058,21 +125797,6 @@ function filterWorkspaceToolsForRun(activeTools, prompt, hasInteractiveApprovalG
|
|
|
125058
125797
|
return true;
|
|
125059
125798
|
});
|
|
125060
125799
|
}
|
|
125061
|
-
var STREAM_STALL_DEBUG = process.env.STREAM_STALL_DEBUG === "1" || process.env.STREAM_STALL_DEBUG === "true";
|
|
125062
|
-
var STREAM_STALL_TICK_MS = 15000;
|
|
125063
|
-
var STREAM_STALL_WARN_MS = 20000;
|
|
125064
|
-
var STREAM_GAP_RECOVERED_MS = 1e4;
|
|
125065
|
-
function responseArgBytes(input) {
|
|
125066
|
-
if (input == null)
|
|
125067
|
-
return 0;
|
|
125068
|
-
if (typeof input === "string")
|
|
125069
|
-
return input.length;
|
|
125070
|
-
try {
|
|
125071
|
-
return JSON.stringify(input).length;
|
|
125072
|
-
} catch {
|
|
125073
|
-
return -1;
|
|
125074
|
-
}
|
|
125075
|
-
}
|
|
125076
125800
|
|
|
125077
125801
|
class OffensiveSecurityAgent {
|
|
125078
125802
|
_streamResult = null;
|
|
@@ -125091,18 +125815,19 @@ class OffensiveSecurityAgent {
|
|
|
125091
125815
|
drained = Promise.resolve();
|
|
125092
125816
|
subagentId;
|
|
125093
125817
|
subagentName;
|
|
125818
|
+
agentMode;
|
|
125094
125819
|
currentMessageId = null;
|
|
125095
125820
|
persistentShell;
|
|
125096
125821
|
browserSession;
|
|
125097
125822
|
ownsBrowserSession;
|
|
125098
125823
|
browserDisconnected = false;
|
|
125824
|
+
shellDisposed = false;
|
|
125099
125825
|
abortSignal;
|
|
125100
125826
|
userPrompt;
|
|
125101
125827
|
_session;
|
|
125102
|
-
|
|
125828
|
+
writer;
|
|
125829
|
+
finalizeInterruptedStep;
|
|
125103
125830
|
messagesPath = null;
|
|
125104
|
-
cancelPersistTimer = null;
|
|
125105
|
-
syntheticsPersisted = false;
|
|
125106
125831
|
static async create(input) {
|
|
125107
125832
|
let session = input.session;
|
|
125108
125833
|
if (!session) {
|
|
@@ -125127,6 +125852,7 @@ class OffensiveSecurityAgent {
|
|
|
125127
125852
|
this._session = input.session;
|
|
125128
125853
|
this.subagentId = input.subagentId;
|
|
125129
125854
|
this.subagentName = input.subagentName;
|
|
125855
|
+
this.agentMode = input.mode ?? "default";
|
|
125130
125856
|
this.abortSignal = input.abortSignal;
|
|
125131
125857
|
this.userPrompt = input.prompt;
|
|
125132
125858
|
this.eventBus = input.eventBus ?? new AgentEventBus;
|
|
@@ -125175,10 +125901,13 @@ class OffensiveSecurityAgent {
|
|
|
125175
125901
|
agentCwd,
|
|
125176
125902
|
target: input.target,
|
|
125177
125903
|
grpc: input.grpc,
|
|
125904
|
+
systemScope: input.systemScope,
|
|
125178
125905
|
abortSignal: input.abortSignal,
|
|
125179
125906
|
model: input.model,
|
|
125180
125907
|
authConfig: input.authConfig,
|
|
125181
125908
|
eventBus: this.eventBus,
|
|
125909
|
+
onStepFinish: input.forwardUsageCallbacksToSpawnedAgents ? input.onStepFinish : undefined,
|
|
125910
|
+
onCacheMetrics: input.forwardUsageCallbacksToSpawnedAgents ? input.onCacheMetrics : undefined,
|
|
125182
125911
|
sandbox: input.sandbox,
|
|
125183
125912
|
findingsRegistry: input.findingsRegistry,
|
|
125184
125913
|
attackSurfaceRegistry: input.attackSurfaceRegistry,
|
|
@@ -125210,8 +125939,8 @@ class OffensiveSecurityAgent {
|
|
|
125210
125939
|
...tools,
|
|
125211
125940
|
[RESPONSE_TOOL_NAME]: createResponseTool(input.responseSchema, (result) => {
|
|
125212
125941
|
this._responseToolFired = true;
|
|
125213
|
-
if (
|
|
125214
|
-
|
|
125942
|
+
if (RESPONSE_DEBUG2) {
|
|
125943
|
+
rlog2.warn(`[response-debug] response tool EXECUTED (captured) session=${this.busSessionId} ` + `resultBytes=${responseArgBytes(result)} — happy path`);
|
|
125215
125944
|
}
|
|
125216
125945
|
const customResolve = input.resolveResult;
|
|
125217
125946
|
if (customResolve) {
|
|
@@ -125259,7 +125988,11 @@ class OffensiveSecurityAgent {
|
|
|
125259
125988
|
const hasEmail = (input.session.config?.emailIntegration?.inboxes?.length ?? 0) > 0;
|
|
125260
125989
|
const hasSmtp = !!input.session.config?.smtpConfig;
|
|
125261
125990
|
const emailToolSet = new Set(EMAIL_TOOL_NAMES);
|
|
125991
|
+
const smsToolSet = new Set(SMS_TOOL_NAMES);
|
|
125992
|
+
const hasSms = sessionHasSmsPasswordless(input.session);
|
|
125262
125993
|
let activeTools = input.activeTools.filter((t) => {
|
|
125994
|
+
if (smsToolSet.has(t))
|
|
125995
|
+
return hasSms;
|
|
125263
125996
|
if (!emailToolSet.has(t))
|
|
125264
125997
|
return true;
|
|
125265
125998
|
if (t === SEND_EMAIL_TOOL_NAME)
|
|
@@ -125274,6 +126007,8 @@ class OffensiveSecurityAgent {
|
|
|
125274
126007
|
activeTools = Object.keys(tools).filter((t) => {
|
|
125275
126008
|
if (excluded.has(t))
|
|
125276
126009
|
return false;
|
|
126010
|
+
if (smsToolSet.has(t))
|
|
126011
|
+
return hasSms;
|
|
125277
126012
|
if (!emailToolSet.has(t))
|
|
125278
126013
|
return true;
|
|
125279
126014
|
if (t === SEND_EMAIL_TOOL_NAME)
|
|
@@ -125282,11 +126017,10 @@ class OffensiveSecurityAgent {
|
|
|
125282
126017
|
});
|
|
125283
126018
|
}
|
|
125284
126019
|
activeTools = filterWorkspaceToolsForRun(activeTools, input.prompt, input.approvalGate !== undefined);
|
|
125285
|
-
if (!
|
|
126020
|
+
if (!existsSync19(messagesDir)) {
|
|
125286
126021
|
mkdirSync14(messagesDir, { recursive: true });
|
|
125287
126022
|
}
|
|
125288
126023
|
this.messagesPath = join27(messagesDir, "messages.json");
|
|
125289
|
-
const messagesPath = this.messagesPath;
|
|
125290
126024
|
const initialMessagesRef = {
|
|
125291
126025
|
current: input.messages ? [...input.messages] : [
|
|
125292
126026
|
{
|
|
@@ -125295,26 +126029,17 @@ class OffensiveSecurityAgent {
|
|
|
125295
126029
|
}
|
|
125296
126030
|
]
|
|
125297
126031
|
};
|
|
125298
|
-
|
|
125299
|
-
|
|
125300
|
-
|
|
125301
|
-
|
|
125302
|
-
|
|
125303
|
-
|
|
125304
|
-
|
|
125305
|
-
|
|
125306
|
-
|
|
125307
|
-
|
|
125308
|
-
|
|
125309
|
-
}
|
|
125310
|
-
}, PERSIST_INTERVAL_MS);
|
|
125311
|
-
};
|
|
125312
|
-
this.cancelPersistTimer = () => {
|
|
125313
|
-
if (persistTimer) {
|
|
125314
|
-
clearTimeout(persistTimer);
|
|
125315
|
-
persistTimer = null;
|
|
125316
|
-
}
|
|
125317
|
-
};
|
|
126032
|
+
this.writer = new AgentMessageWriter({ messagesPath: this.messagesPath });
|
|
126033
|
+
this.finalizeInterruptedStep = createInterruptedStepFinalizer({
|
|
126034
|
+
eventBus: this.eventBus,
|
|
126035
|
+
sessionId: this.busSessionId,
|
|
126036
|
+
subagentId: this.subagentId,
|
|
126037
|
+
writer: this.writer,
|
|
126038
|
+
responseToolName: RESPONSE_TOOL_NAME,
|
|
126039
|
+
responseToolFired: () => this._responseToolFired,
|
|
126040
|
+
...RESPONSE_DEBUG2 ? { debugLog: (message) => rlog2.warn(message) } : {}
|
|
126041
|
+
});
|
|
126042
|
+
const schedulePersist = () => this.writer.schedulePersist();
|
|
125318
126043
|
const baseSystemPrompt = input.system ?? detectOSAndEnhancePrompt(buildBaseSystemPrompt({
|
|
125319
126044
|
sandboxMode: agentCwd === input.session.rootPath
|
|
125320
126045
|
}));
|
|
@@ -125339,10 +126064,10 @@ class OffensiveSecurityAgent {
|
|
|
125339
126064
|
sessionPath: messagesDir,
|
|
125340
126065
|
sessionId: this.busSessionId,
|
|
125341
126066
|
onStepFinish: async (event) => {
|
|
125342
|
-
this.
|
|
126067
|
+
this.writer.setLatest([
|
|
125343
126068
|
...initialMessagesRef.current,
|
|
125344
126069
|
...event.response.messages
|
|
125345
|
-
];
|
|
126070
|
+
]);
|
|
125346
126071
|
schedulePersist();
|
|
125347
126072
|
traceWriter.recordStep(event.response.messages, {
|
|
125348
126073
|
inputTokens: event.usage.inputTokens ?? 0,
|
|
@@ -125364,16 +126089,14 @@ class OffensiveSecurityAgent {
|
|
|
125364
126089
|
traceWriter.markSummarized();
|
|
125365
126090
|
},
|
|
125366
126091
|
onFinish: async (event) => {
|
|
125367
|
-
|
|
125368
|
-
|
|
125369
|
-
|
|
125370
|
-
}
|
|
125371
|
-
if (!this.syntheticsPersisted) {
|
|
125372
|
-
const finalMessages = this.latestMessages ?? [
|
|
126092
|
+
this.writer.cancelTimer();
|
|
126093
|
+
if (!this.writer.syntheticsPersisted) {
|
|
126094
|
+
const finalMessages = this.writer.latest ?? [
|
|
125373
126095
|
...initialMessagesRef.current,
|
|
125374
126096
|
...event.response.messages
|
|
125375
126097
|
];
|
|
125376
|
-
|
|
126098
|
+
this.writer.setLatest(finalMessages);
|
|
126099
|
+
await this.writer.enqueueWrite(finalMessages).catch(() => {});
|
|
125377
126100
|
}
|
|
125378
126101
|
await input.onFinish?.(event);
|
|
125379
126102
|
},
|
|
@@ -125425,205 +126148,34 @@ class OffensiveSecurityAgent {
|
|
|
125425
126148
|
return p;
|
|
125426
126149
|
}
|
|
125427
126150
|
};
|
|
125428
|
-
const
|
|
125429
|
-
const completedResults = [];
|
|
126151
|
+
const tracker = new ToolLifecycleTracker;
|
|
125430
126152
|
let streamError = null;
|
|
125431
|
-
const
|
|
125432
|
-
|
|
125433
|
-
|
|
125434
|
-
|
|
125435
|
-
|
|
125436
|
-
|
|
125437
|
-
|
|
125438
|
-
|
|
125439
|
-
if (STREAM_STALL_DEBUG) {
|
|
125440
|
-
const label = this._session.id;
|
|
125441
|
-
stallTimer = setInterval(() => {
|
|
125442
|
-
const gap = Date.now() - lastChunkAt;
|
|
125443
|
-
if (gap > STREAM_STALL_WARN_MS) {
|
|
125444
|
-
rlog.warn(`[stream-stall] no chunk for ${Math.round(gap / 1000)}s ` + `session=${label} subagent=${sid ?? "-"} step=${stallStepIndex} ` + `lastChunkType=${lastChunkType} ` + `inFlightTools=${[...inFlightTools.values()].join(",")} ` + `responseToolFired=${this._responseToolFired}`);
|
|
125445
|
-
}
|
|
125446
|
-
}, STREAM_STALL_TICK_MS);
|
|
125447
|
-
}
|
|
126153
|
+
const diagnostics = new StreamDiagnostics({
|
|
126154
|
+
sessionId: this._session.id,
|
|
126155
|
+
subagentId: sid,
|
|
126156
|
+
inFlightTools: () => tracker.inFlightTools,
|
|
126157
|
+
responseToolFired: () => this._responseToolFired,
|
|
126158
|
+
responseToolName: RESPONSE_TOOL_NAME
|
|
126159
|
+
});
|
|
126160
|
+
diagnostics.start();
|
|
125448
126161
|
try {
|
|
125449
126162
|
for await (const chunk of this.streamResult.fullStream) {
|
|
125450
|
-
|
|
125451
|
-
|
|
125452
|
-
const gap = now - lastChunkAt;
|
|
125453
|
-
lastChunkAt = now;
|
|
125454
|
-
lastChunkType = chunk.type;
|
|
125455
|
-
if (chunk.type === "start-step")
|
|
125456
|
-
stallStepIndex++;
|
|
125457
|
-
if (gap > STREAM_GAP_RECOVERED_MS) {
|
|
125458
|
-
rlog.warn(`[stream-gap] recovered after ${Math.round(gap / 1000)}s ` + `session=${this._session.id} chunkType=${chunk.type}`);
|
|
125459
|
-
}
|
|
125460
|
-
}
|
|
125461
|
-
if (RESPONSE_DEBUG) {
|
|
125462
|
-
const c = chunk;
|
|
125463
|
-
const idForChunk = c.toolCallId ?? c.id;
|
|
125464
|
-
const nameForChunk = c.toolName ?? (idForChunk ? inFlightTools.get(idForChunk) : undefined);
|
|
125465
|
-
if (nameForChunk === RESPONSE_TOOL_NAME && idForChunk) {
|
|
125466
|
-
if (chunk.type === "tool-input-start") {
|
|
125467
|
-
responseArgChars.set(idForChunk, 0);
|
|
125468
|
-
rlog.warn(`[response-debug] tool-input-start id=${idForChunk} session=${this.busSessionId}`);
|
|
125469
|
-
} else if (chunk.type === "tool-input-delta") {
|
|
125470
|
-
responseArgChars.set(idForChunk, (responseArgChars.get(idForChunk) ?? 0) + (c.delta?.length ?? 0));
|
|
125471
|
-
} else if (chunk.type === "tool-input-end") {
|
|
125472
|
-
rlog.warn(`[response-debug] tool-input-end id=${idForChunk} argChars=${responseArgChars.get(idForChunk) ?? 0}`);
|
|
125473
|
-
} else if (chunk.type === "tool-call") {
|
|
125474
|
-
responseSawTerminal.set(idForChunk, "tool-call");
|
|
125475
|
-
const inputBytes = responseArgBytes(c.input ?? c.args);
|
|
125476
|
-
const invalid = c.invalid === true;
|
|
125477
|
-
rlog.warn(`[response-debug] tool-call id=${idForChunk} streamedArgChars=${responseArgChars.get(idForChunk) ?? 0} parsedInputBytes=${inputBytes} invalid=${invalid}`);
|
|
125478
|
-
} else if (chunk.type === "tool-error") {
|
|
125479
|
-
responseSawTerminal.set(idForChunk, "tool-error");
|
|
125480
|
-
const errMsg = c.error instanceof Error ? c.error.message : typeof c.error === "string" ? c.error : JSON.stringify(c.error)?.slice(0, 300);
|
|
125481
|
-
rlog.warn(`[response-debug] tool-error id=${idForChunk} streamedArgChars=${responseArgChars.get(idForChunk) ?? 0} stillInFlight=${inFlightTools.has(idForChunk)} error=${errMsg}`);
|
|
125482
|
-
} else if (chunk.type === "tool-result") {
|
|
125483
|
-
responseSawTerminal.set(idForChunk, "tool-result");
|
|
125484
|
-
rlog.warn(`[response-debug] tool-result id=${idForChunk} streamedArgChars=${responseArgChars.get(idForChunk) ?? 0}`);
|
|
125485
|
-
} else if (chunk.type === "finish-step") {
|
|
125486
|
-
const fr = c.finishReason;
|
|
125487
|
-
rlog.warn(`[response-debug] finish-step finishReason=${fr} responseInFlight=${[
|
|
125488
|
-
...inFlightTools.entries()
|
|
125489
|
-
].filter(([, n7]) => n7 === RESPONSE_TOOL_NAME).map(([id]) => id).join(",")} responseToolFired=${this._responseToolFired}`);
|
|
125490
|
-
}
|
|
125491
|
-
}
|
|
125492
|
-
}
|
|
125493
|
-
switch (chunk.type) {
|
|
125494
|
-
case "start-step":
|
|
125495
|
-
ids.messageId = newMessageId();
|
|
125496
|
-
this.currentMessageId = ids.messageId;
|
|
125497
|
-
ids.textPartId = undefined;
|
|
125498
|
-
break;
|
|
125499
|
-
case "text-start":
|
|
125500
|
-
ids.textPartId = newPartId();
|
|
125501
|
-
break;
|
|
125502
|
-
case "text-end":
|
|
125503
|
-
ids.textPartId = undefined;
|
|
125504
|
-
break;
|
|
125505
|
-
case "tool-input-start":
|
|
125506
|
-
inFlightTools.set(chunk.id, chunk.toolName);
|
|
125507
|
-
streamedArgText.set(chunk.id, "");
|
|
125508
|
-
break;
|
|
125509
|
-
case "tool-input-delta": {
|
|
125510
|
-
const d = chunk;
|
|
125511
|
-
streamedArgText.set(d.id, (streamedArgText.get(d.id) ?? "") + (d.delta ?? ""));
|
|
125512
|
-
break;
|
|
125513
|
-
}
|
|
125514
|
-
case "tool-call":
|
|
125515
|
-
inFlightTools.set(chunk.toolCallId, chunk.toolName);
|
|
125516
|
-
break;
|
|
125517
|
-
case "tool-error": {
|
|
125518
|
-
const te2 = chunk;
|
|
125519
|
-
inFlightTools.delete(te2.toolCallId);
|
|
125520
|
-
const errMsg = te2.error instanceof Error ? te2.error.message : typeof te2.error === "string" ? te2.error : (() => {
|
|
125521
|
-
try {
|
|
125522
|
-
return JSON.stringify(te2.error);
|
|
125523
|
-
} catch {
|
|
125524
|
-
return String(te2.error);
|
|
125525
|
-
}
|
|
125526
|
-
})();
|
|
125527
|
-
const partialArgs = te2.input !== undefined && te2.input !== null && responseArgBytes(te2.input) > 2 ? te2.input : streamedArgText.get(te2.toolCallId) ?? "";
|
|
125528
|
-
toolErrors.set(te2.toolCallId, {
|
|
125529
|
-
message: errMsg,
|
|
125530
|
-
input: partialArgs,
|
|
125531
|
-
toolName: te2.toolName
|
|
125532
|
-
});
|
|
125533
|
-
break;
|
|
125534
|
-
}
|
|
125535
|
-
case "tool-result": {
|
|
125536
|
-
const tc = chunk;
|
|
125537
|
-
inFlightTools.delete(tc.toolCallId);
|
|
125538
|
-
completedResults.push({
|
|
125539
|
-
type: "tool-result",
|
|
125540
|
-
toolCallId: tc.toolCallId,
|
|
125541
|
-
toolName: tc.toolName,
|
|
125542
|
-
output: tc.result ?? tc.output
|
|
125543
|
-
});
|
|
125544
|
-
break;
|
|
125545
|
-
}
|
|
125546
|
-
case "finish-step": {
|
|
125547
|
-
completedResults.length = 0;
|
|
125548
|
-
const finishReason = chunk.finishReason;
|
|
125549
|
-
const truncated = finishReason === "length";
|
|
125550
|
-
for (const [toolCallId, info] of toolErrors) {
|
|
125551
|
-
if (RESPONSE_DEBUG && info.toolName === RESPONSE_TOOL_NAME) {
|
|
125552
|
-
rlog.warn(`[response-debug] tool-error SURFACED id=${toolCallId} ` + `streamedArgChars=${(streamedArgText.get(toolCallId) ?? "").length} ` + `finishReason=${finishReason ?? "unknown"} ` + `outputTokenTruncated=${truncated} error=${info.message.slice(0, 300)}`);
|
|
125553
|
-
}
|
|
125554
|
-
bus.emit("tool-result", {
|
|
125555
|
-
toolCallId,
|
|
125556
|
-
toolName: info.toolName,
|
|
125557
|
-
result: {
|
|
125558
|
-
type: "error-text",
|
|
125559
|
-
value: truncated ? `Tool call failed: the model's output was truncated at its max output tokens before the "${info.toolName}" arguments were complete. ${info.message}` : `Tool call failed: ${info.message}`
|
|
125560
|
-
},
|
|
125561
|
-
sessionId: this.busSessionId,
|
|
125562
|
-
subagentId: sid,
|
|
125563
|
-
partId: ids.toolPartId?.(toolCallId),
|
|
125564
|
-
messageId: ids.messageId
|
|
125565
|
-
});
|
|
125566
|
-
}
|
|
125567
|
-
toolErrors.clear();
|
|
125568
|
-
for (const [toolCallId, toolName] of inFlightTools) {
|
|
125569
|
-
if (RESPONSE_DEBUG && toolName === RESPONSE_TOOL_NAME) {
|
|
125570
|
-
rlog.warn(`[response-debug] CLOSING response as "did not complete" id=${toolCallId} ` + `streamedArgChars=${responseArgChars.get(toolCallId) ?? 0} ` + `sawTerminalChunk=${responseSawTerminal.get(toolCallId) ?? "none"} ` + `finishReason=${finishReason ?? "unknown"} outputTokenTruncated=${truncated} ` + `responseToolFired=${this._responseToolFired}`);
|
|
125571
|
-
}
|
|
125572
|
-
const result2 = toolName === RESPONSE_TOOL_NAME && this._responseToolFired ? { type: "text", value: "Response submitted." } : {
|
|
125573
|
-
type: "error-text",
|
|
125574
|
-
value: truncated ? "Tool call did not complete: the model's output was truncated at its max output tokens before the arguments were finalized." : "Tool call did not complete"
|
|
125575
|
-
};
|
|
125576
|
-
bus.emit("tool-result", {
|
|
125577
|
-
toolCallId,
|
|
125578
|
-
toolName,
|
|
125579
|
-
result: result2,
|
|
125580
|
-
sessionId: this.busSessionId,
|
|
125581
|
-
subagentId: sid,
|
|
125582
|
-
partId: ids.toolPartId?.(toolCallId),
|
|
125583
|
-
messageId: ids.messageId
|
|
125584
|
-
});
|
|
125585
|
-
}
|
|
125586
|
-
inFlightTools.clear();
|
|
125587
|
-
break;
|
|
125588
|
-
}
|
|
125589
|
-
}
|
|
126163
|
+
diagnostics.observeChunk(chunk);
|
|
126164
|
+
this.applyStreamPart(chunk, { ids, tracker, diagnostics });
|
|
125590
126165
|
bus.emitStreamPart(chunk, ids);
|
|
125591
126166
|
}
|
|
125592
126167
|
} catch (err) {
|
|
125593
126168
|
streamError = err;
|
|
125594
126169
|
} finally {
|
|
125595
|
-
|
|
125596
|
-
|
|
125597
|
-
|
|
125598
|
-
|
|
125599
|
-
|
|
125600
|
-
|
|
125601
|
-
|
|
125602
|
-
|
|
125603
|
-
bus.emit("tool-result", {
|
|
125604
|
-
toolCallId,
|
|
125605
|
-
toolName: info.toolName,
|
|
125606
|
-
result: result2,
|
|
125607
|
-
sessionId: this.busSessionId,
|
|
125608
|
-
subagentId: sid,
|
|
125609
|
-
partId: ids.toolPartId?.(toolCallId),
|
|
125610
|
-
messageId: ids.messageId
|
|
125611
|
-
});
|
|
125612
|
-
completedResults.push({
|
|
125613
|
-
type: "tool-result",
|
|
125614
|
-
toolCallId,
|
|
125615
|
-
toolName: info.toolName,
|
|
125616
|
-
output: result2
|
|
125617
|
-
});
|
|
125618
|
-
}
|
|
125619
|
-
toolErrors.clear();
|
|
125620
|
-
if (inFlightTools.size > 0 || completedResults.length > 0) {
|
|
125621
|
-
const reason = this.abortSignal?.aborted ? "Agent aborted by user" : streamError instanceof Error && streamError.message ? streamError.message : "Stream terminated unexpectedly";
|
|
125622
|
-
try {
|
|
125623
|
-
await this.emitSyntheticToolResults(inFlightTools, completedResults, reason, ids.toolPartId, ids.messageId, streamedArgText);
|
|
125624
|
-
} catch {}
|
|
126170
|
+
const finalizeError = await this.finalizeRun({
|
|
126171
|
+
tracker,
|
|
126172
|
+
diagnostics,
|
|
126173
|
+
ids,
|
|
126174
|
+
streamError
|
|
126175
|
+
});
|
|
126176
|
+
if (streamError === null && finalizeError !== null) {
|
|
126177
|
+
streamError = finalizeError;
|
|
125625
126178
|
}
|
|
125626
|
-
await this.disconnectOwnedBrowser();
|
|
125627
126179
|
}
|
|
125628
126180
|
if (streamError) {
|
|
125629
126181
|
throw streamError;
|
|
@@ -125639,22 +126191,35 @@ class OffensiveSecurityAgent {
|
|
|
125639
126191
|
}
|
|
125640
126192
|
return;
|
|
125641
126193
|
};
|
|
125642
|
-
const
|
|
125643
|
-
const
|
|
125644
|
-
|
|
125645
|
-
|
|
125646
|
-
|
|
126194
|
+
const isSubagent = Boolean(sid);
|
|
126195
|
+
const spanLabel = isSubagent ? this.subagentName ?? sid ?? "subagent" : this.agentMode;
|
|
126196
|
+
const runId = isSubagent ? undefined : newRunId();
|
|
126197
|
+
const runSpanAttributes = {
|
|
126198
|
+
"gen_ai.operation.name": "invoke_agent",
|
|
126199
|
+
"gen_ai.agent.name": spanLabel,
|
|
126200
|
+
"gen_ai.conversation.id": this.busSessionId,
|
|
126201
|
+
"pensar.session.id": this.busSessionId,
|
|
126202
|
+
...isSubagent ? {} : {
|
|
126203
|
+
"pensar.run.id": runId,
|
|
126204
|
+
"pensar.agent.mode": this.agentMode
|
|
125647
126205
|
}
|
|
125648
|
-
}
|
|
126206
|
+
};
|
|
126207
|
+
const runInSpan = () => getApexTracer().startActiveSpan(`invoke_agent ${spanLabel}`, { attributes: runSpanAttributes }, async (span) => {
|
|
126208
|
+
if (!isSubagent)
|
|
126209
|
+
registerActiveRootSpan(span);
|
|
125649
126210
|
try {
|
|
125650
126211
|
return await runConsume();
|
|
125651
126212
|
} catch (err) {
|
|
125652
126213
|
span.recordException(err);
|
|
126214
|
+
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
126215
|
+
span.setAttribute("error.type", err instanceof Error ? err.name : "Error");
|
|
125653
126216
|
throw err;
|
|
125654
126217
|
} finally {
|
|
126218
|
+
unregisterActiveRootSpan(span);
|
|
125655
126219
|
span.end();
|
|
125656
126220
|
}
|
|
125657
|
-
})
|
|
126221
|
+
});
|
|
126222
|
+
const drain = !isSubagent ? runInSpan() : withSubagentSessionBaggage(sid, runInSpan);
|
|
125658
126223
|
let rejectDrain;
|
|
125659
126224
|
this._drainRejection = new Promise((_2, reject) => {
|
|
125660
126225
|
rejectDrain = reject;
|
|
@@ -125678,6 +126243,141 @@ class OffensiveSecurityAgent {
|
|
|
125678
126243
|
await this.disconnectOwnedBrowser();
|
|
125679
126244
|
return result;
|
|
125680
126245
|
}
|
|
126246
|
+
applyStreamPart(chunk, ctx) {
|
|
126247
|
+
const { ids, tracker, diagnostics } = ctx;
|
|
126248
|
+
const sid = this.subagentId;
|
|
126249
|
+
const bus = this.eventBus;
|
|
126250
|
+
switch (chunk.type) {
|
|
126251
|
+
case "start-step":
|
|
126252
|
+
ids.messageId = newMessageId();
|
|
126253
|
+
this.currentMessageId = ids.messageId;
|
|
126254
|
+
ids.textPartId = undefined;
|
|
126255
|
+
break;
|
|
126256
|
+
case "text-start":
|
|
126257
|
+
ids.textPartId = newPartId();
|
|
126258
|
+
break;
|
|
126259
|
+
case "text-end":
|
|
126260
|
+
ids.textPartId = undefined;
|
|
126261
|
+
break;
|
|
126262
|
+
case "finish-step": {
|
|
126263
|
+
tracker.onStepPersisted();
|
|
126264
|
+
const finishReason = chunk.finishReason;
|
|
126265
|
+
const truncated = finishReason === "length";
|
|
126266
|
+
for (const [toolCallId, info] of tracker.toolErrors) {
|
|
126267
|
+
diagnostics.logSurfacedToolError({
|
|
126268
|
+
toolCallId,
|
|
126269
|
+
toolName: info.toolName,
|
|
126270
|
+
message: info.message,
|
|
126271
|
+
streamedArgChars: (tracker.streamedArgText.get(toolCallId) ?? "").length,
|
|
126272
|
+
finishReason,
|
|
126273
|
+
truncated
|
|
126274
|
+
});
|
|
126275
|
+
bus.emit("tool-result", {
|
|
126276
|
+
toolCallId,
|
|
126277
|
+
toolName: info.toolName,
|
|
126278
|
+
result: {
|
|
126279
|
+
type: "error-text",
|
|
126280
|
+
value: truncated ? `Tool call failed: the model's output was truncated at its max output tokens before the "${info.toolName}" arguments were complete. ${info.message}` : `Tool call failed: ${info.message}`
|
|
126281
|
+
},
|
|
126282
|
+
sessionId: this.busSessionId,
|
|
126283
|
+
subagentId: sid,
|
|
126284
|
+
partId: ids.toolPartId?.(toolCallId),
|
|
126285
|
+
messageId: ids.messageId
|
|
126286
|
+
});
|
|
126287
|
+
}
|
|
126288
|
+
tracker.clearToolErrors();
|
|
126289
|
+
for (const [toolCallId, toolName] of tracker.inFlightTools) {
|
|
126290
|
+
diagnostics.logClosingInFlightTool({
|
|
126291
|
+
toolCallId,
|
|
126292
|
+
toolName,
|
|
126293
|
+
finishReason,
|
|
126294
|
+
truncated
|
|
126295
|
+
});
|
|
126296
|
+
const result = toolName === RESPONSE_TOOL_NAME && this._responseToolFired ? { type: "text", value: "Response submitted." } : {
|
|
126297
|
+
type: "error-text",
|
|
126298
|
+
value: truncated ? "Tool call did not complete: the model's output was truncated at its max output tokens before the arguments were finalized." : "Tool call did not complete"
|
|
126299
|
+
};
|
|
126300
|
+
bus.emit("tool-result", {
|
|
126301
|
+
toolCallId,
|
|
126302
|
+
toolName,
|
|
126303
|
+
result,
|
|
126304
|
+
sessionId: this.busSessionId,
|
|
126305
|
+
subagentId: sid,
|
|
126306
|
+
partId: ids.toolPartId?.(toolCallId),
|
|
126307
|
+
messageId: ids.messageId
|
|
126308
|
+
});
|
|
126309
|
+
}
|
|
126310
|
+
tracker.clearInFlight();
|
|
126311
|
+
break;
|
|
126312
|
+
}
|
|
126313
|
+
default:
|
|
126314
|
+
tracker.observePart(chunk);
|
|
126315
|
+
}
|
|
126316
|
+
}
|
|
126317
|
+
async finalizeRun(input) {
|
|
126318
|
+
const { tracker, diagnostics, ids, streamError } = input;
|
|
126319
|
+
const sid = this.subagentId;
|
|
126320
|
+
const bus = this.eventBus;
|
|
126321
|
+
diagnostics.stop();
|
|
126322
|
+
let finalizationError;
|
|
126323
|
+
let hasFinalizationError = false;
|
|
126324
|
+
const recordFinalizationError = (error) => {
|
|
126325
|
+
if (hasFinalizationError)
|
|
126326
|
+
return;
|
|
126327
|
+
finalizationError = error;
|
|
126328
|
+
hasFinalizationError = true;
|
|
126329
|
+
};
|
|
126330
|
+
try {
|
|
126331
|
+
try {
|
|
126332
|
+
this.disposeOwnedShell();
|
|
126333
|
+
} catch (error) {
|
|
126334
|
+
recordFinalizationError(error);
|
|
126335
|
+
}
|
|
126336
|
+
for (const [toolCallId, info] of tracker.flushToolErrorsToResults()) {
|
|
126337
|
+
const result = {
|
|
126338
|
+
type: "error-text",
|
|
126339
|
+
value: `Tool call failed: ${info.message}`
|
|
126340
|
+
};
|
|
126341
|
+
try {
|
|
126342
|
+
bus.emit("tool-result", {
|
|
126343
|
+
toolCallId,
|
|
126344
|
+
toolName: info.toolName,
|
|
126345
|
+
result,
|
|
126346
|
+
sessionId: this.busSessionId,
|
|
126347
|
+
subagentId: sid,
|
|
126348
|
+
partId: ids.toolPartId?.(toolCallId),
|
|
126349
|
+
messageId: ids.messageId
|
|
126350
|
+
});
|
|
126351
|
+
} catch (error) {
|
|
126352
|
+
recordFinalizationError(error);
|
|
126353
|
+
}
|
|
126354
|
+
}
|
|
126355
|
+
if (tracker.hasUnpersistedState()) {
|
|
126356
|
+
const reason = this.abortSignal?.aborted ? "Agent aborted by user" : streamError instanceof Error && streamError.message ? streamError.message : "Stream terminated unexpectedly";
|
|
126357
|
+
try {
|
|
126358
|
+
await this.finalizeInterruptedStep({
|
|
126359
|
+
snapshot: tracker.snapshot(),
|
|
126360
|
+
reason,
|
|
126361
|
+
partIdFor: ids.toolPartId,
|
|
126362
|
+
messageId: ids.messageId
|
|
126363
|
+
});
|
|
126364
|
+
} catch (error) {
|
|
126365
|
+
recordFinalizationError(error);
|
|
126366
|
+
}
|
|
126367
|
+
}
|
|
126368
|
+
} catch (error) {
|
|
126369
|
+
recordFinalizationError(error);
|
|
126370
|
+
} finally {
|
|
126371
|
+
await this.disconnectOwnedBrowser();
|
|
126372
|
+
}
|
|
126373
|
+
return hasFinalizationError ? finalizationError : null;
|
|
126374
|
+
}
|
|
126375
|
+
disposeOwnedShell() {
|
|
126376
|
+
if (this.shellDisposed)
|
|
126377
|
+
return;
|
|
126378
|
+
this.shellDisposed = true;
|
|
126379
|
+
this.persistentShell?.dispose();
|
|
126380
|
+
}
|
|
125681
126381
|
async disconnectOwnedBrowser() {
|
|
125682
126382
|
if (this.browserDisconnected)
|
|
125683
126383
|
return;
|
|
@@ -125693,102 +126393,6 @@ class OffensiveSecurityAgent {
|
|
|
125693
126393
|
get response() {
|
|
125694
126394
|
return this.streamResult.response;
|
|
125695
126395
|
}
|
|
125696
|
-
async emitSyntheticToolResults(inFlightTools, completedResults, reason, partIdFor, messageId, streamedArgText) {
|
|
125697
|
-
const sid = this.subagentId;
|
|
125698
|
-
const output = {
|
|
125699
|
-
type: "error-text",
|
|
125700
|
-
value: `Tool execution aborted: ${reason}`
|
|
125701
|
-
};
|
|
125702
|
-
const syntheticParts = [];
|
|
125703
|
-
if (RESPONSE_DEBUG) {
|
|
125704
|
-
const responseInFlight = [...inFlightTools.entries()].filter(([, n7]) => n7 === RESPONSE_TOOL_NAME);
|
|
125705
|
-
if (responseInFlight.length > 0) {
|
|
125706
|
-
rlog.warn(`[response-debug] emitSyntheticToolResults closing ${responseInFlight.length} response call(s) ` + `ids=${responseInFlight.map(([id]) => id).join(",")} reason="${reason}" ` + `aborted=${this.abortSignal?.aborted === true} responseToolFired=${this._responseToolFired}`);
|
|
125707
|
-
}
|
|
125708
|
-
}
|
|
125709
|
-
for (const [toolCallId, toolName] of inFlightTools) {
|
|
125710
|
-
const result = toolName === RESPONSE_TOOL_NAME && this._responseToolFired ? { type: "text", value: "Response submitted." } : output;
|
|
125711
|
-
this.eventBus.emit("tool-result", {
|
|
125712
|
-
toolCallId,
|
|
125713
|
-
toolName,
|
|
125714
|
-
result,
|
|
125715
|
-
sessionId: this.busSessionId,
|
|
125716
|
-
subagentId: sid,
|
|
125717
|
-
partId: partIdFor?.(toolCallId),
|
|
125718
|
-
messageId
|
|
125719
|
-
});
|
|
125720
|
-
syntheticParts.push({
|
|
125721
|
-
type: "tool-result",
|
|
125722
|
-
toolCallId,
|
|
125723
|
-
toolName,
|
|
125724
|
-
output: result
|
|
125725
|
-
});
|
|
125726
|
-
}
|
|
125727
|
-
if (!this.messagesPath)
|
|
125728
|
-
return;
|
|
125729
|
-
this.cancelPersistTimer?.();
|
|
125730
|
-
let base = this.latestMessages ?? [];
|
|
125731
|
-
if (base.length === 0 && existsSync18(this.messagesPath)) {
|
|
125732
|
-
try {
|
|
125733
|
-
base = JSON.parse(readFileSync8(this.messagesPath, "utf-8"));
|
|
125734
|
-
} catch {}
|
|
125735
|
-
}
|
|
125736
|
-
const allToolCallIds = new Set([
|
|
125737
|
-
...inFlightTools.keys(),
|
|
125738
|
-
...completedResults.map((r) => r.toolCallId)
|
|
125739
|
-
]);
|
|
125740
|
-
const lastMsg = base[base.length - 1];
|
|
125741
|
-
const needsStepReconstruction = !lastMsg || lastMsg.role !== "assistant" || !this.baseContainsToolCalls(lastMsg, allToolCallIds);
|
|
125742
|
-
const appended = [];
|
|
125743
|
-
if (needsStepReconstruction) {
|
|
125744
|
-
const stepTools = [
|
|
125745
|
-
...inFlightTools,
|
|
125746
|
-
...completedResults.map((r) => [
|
|
125747
|
-
r.toolCallId,
|
|
125748
|
-
r.toolName
|
|
125749
|
-
])
|
|
125750
|
-
];
|
|
125751
|
-
const reconstructInput = (toolCallId) => {
|
|
125752
|
-
const raw = streamedArgText?.get(toolCallId);
|
|
125753
|
-
if (!raw)
|
|
125754
|
-
return {};
|
|
125755
|
-
try {
|
|
125756
|
-
return JSON.parse(raw);
|
|
125757
|
-
} catch {
|
|
125758
|
-
return { _partial: raw };
|
|
125759
|
-
}
|
|
125760
|
-
};
|
|
125761
|
-
if (RESPONSE_DEBUG) {
|
|
125762
|
-
const responseReconstructed = stepTools.filter(([, n7]) => n7 === RESPONSE_TOOL_NAME).map(([id]) => id);
|
|
125763
|
-
if (responseReconstructed.length > 0) {
|
|
125764
|
-
rlog.warn(`[response-debug] step-reconstruction for response call(s) ` + `ids=${responseReconstructed.join(",")} ` + `preservedArgChars=${responseReconstructed.map((id) => streamedArgText?.get(id)?.length ?? 0).join(",")}`);
|
|
125765
|
-
}
|
|
125766
|
-
}
|
|
125767
|
-
const toolCalls = stepTools.map(([toolCallId, toolName]) => ({
|
|
125768
|
-
type: "tool-call",
|
|
125769
|
-
toolCallId,
|
|
125770
|
-
toolName,
|
|
125771
|
-
input: reconstructInput(toolCallId)
|
|
125772
|
-
}));
|
|
125773
|
-
appended.push({ role: "assistant", content: toolCalls });
|
|
125774
|
-
}
|
|
125775
|
-
appended.push({
|
|
125776
|
-
role: "tool",
|
|
125777
|
-
content: [...completedResults, ...syntheticParts]
|
|
125778
|
-
});
|
|
125779
|
-
const next = [...base, ...appended];
|
|
125780
|
-
this.latestMessages = next;
|
|
125781
|
-
try {
|
|
125782
|
-
await writeFile7(this.messagesPath, JSON.stringify(next));
|
|
125783
|
-
this.syntheticsPersisted = true;
|
|
125784
|
-
} catch {}
|
|
125785
|
-
}
|
|
125786
|
-
baseContainsToolCalls(msg, toolCallIds) {
|
|
125787
|
-
if (!Array.isArray(msg.content))
|
|
125788
|
-
return false;
|
|
125789
|
-
const contentToolIds = new Set(msg.content.filter((p) => p.type === "tool-call" && p.toolCallId).map((p) => p.toolCallId));
|
|
125790
|
-
return [...toolCallIds].every((id) => contentToolIds.has(id));
|
|
125791
|
-
}
|
|
125792
126396
|
}
|
|
125793
126397
|
var AGENT_PAUSE_TOOLS = new Set([ASK_USER_QUESTIONS_TOOL_NAME]);
|
|
125794
126398
|
function wrapToolsWithApprovalGate(tools, gate, exemptToolNames) {
|
|
@@ -125828,4 +126432,4 @@ function wrapToolsWithApprovalGate(tools, gate, exemptToolNames) {
|
|
|
125828
126432
|
return wrapped;
|
|
125829
126433
|
}
|
|
125830
126434
|
|
|
125831
|
-
export { AgentEventBus, INTERNAL_ID_PATTERN, ApprovalGate, OPERATOR_MODES, OPERATOR_MODE_CYCLE, createInitialOperatorState, buildProvidedFilesSection, buildSessionWorkspaceSection, buildBaseSystemPrompt, BASE_SYSTEM_PROMPT, isMemoryEnabled, addMemory2 as addMemory, ASK_USER_QUESTIONS_TOOL_NAME, AskUserQuestionSchema, transformScriptToFunction, parseStorageStateResult, setHeadlessMode, setUserAgent, setViewportSize, PlaywrightMcpSession, createBrowserTools, ScopeViolationError, getAllowedHosts, isHostAllowed, extractHostname2 as extractHostname, assertUrlInScope, extractHostsFromCommand, assertCommandInScope, checkSandboxPlaywright, installSandboxPlaywright, ensureSandboxPlaywright, ensureSandboxBrowser, createSandboxBrowserTools, BROWSER_TOOL_NAMES, createBrowserToolset, checkpointState, completeAuthentication, crawlAuthenticated, createAttackSurfaceReport, createFile, createTask2 as createTask, delegateAuth, detectAuthScheme, documentApp, EndpointTransportEnum, GrpcEndpointMetadataSchema, toGrpcPentestContext, grpcAuthorityTarget, pLimit, documentEndpoint, CweEntrySchema, ValidatedCweEntrySchema, hasCanonicalName, documentVulnerability, createEmailToolset, EMAIL_TOOL_NAMES, SEND_EMAIL_TOOL_NAME, executeCommand, extractJsEndpoints, getMemory2 as getMemory, getPage, grep, httpRequest, listFiles, listMemories2 as listMemories, listTasksTool, readTempfileCapped, getApexTmpRoot, extractFallbackStdout, PersistentShell, probeAuthEndpoints, provideComparisonResults, readFile2 as readFile, readSkill, REPORT_ERROR_TOOL_NAME, ReportErrorReasonSchema, createReportErrorTool, PentestReportedError, RESPONSE_TOOL_NAME, createResponseTool, runAttackSurface, runPentestWorkflow, runWithBoundedConcurrency, spawnCodingAgent, FindingsRegistry, planFilePath, readPlan, hasPlan, spawnPentestAgent, spawnPentestSwarm, submitPlan, testEndpointVariations, updateFile, updateTask2 as updateTask, validateDiscovery, webSearch, apiRequest, listApps, getApp, createApp, updateApp, deleteApp, listEndpoints, getEndpoint, createEndpoint, updateEndpoint, deleteEndpoint, searchApps, searchEndpoints, listWorkspaceApps, createWorkspaceApp, updateWorkspaceApp, listWorkspaceEndpoints, createWorkspaceEndpoint, updateWorkspaceEndpoint, listWorkspaceDomains, createWorkspaceDomain, writePlan, createAllTools, ALL_TOOL_NAMES, FAST_STRIKE_EXCLUDED_TOOL_NAMES, PLAN_MODE_TOOL_NAMES, SKILL_TOOL_NAMES, StepTraceWriter, OffensiveSecurityAgent };
|
|
126435
|
+
export { AgentEventBus, INTERNAL_ID_PATTERN, ApprovalGate, OPERATOR_MODES, OPERATOR_MODE_CYCLE, createInitialOperatorState, buildProvidedFilesSection, buildSessionWorkspaceSection, buildBaseSystemPrompt, BASE_SYSTEM_PROMPT, isMemoryEnabled, addMemory2 as addMemory, ASK_USER_QUESTIONS_TOOL_NAME, AskUserQuestionSchema, transformScriptToFunction, parseStorageStateResult, setHeadlessMode, setUserAgent, setViewportSize, PlaywrightMcpSession, createBrowserTools, ScopeViolationError, getAllowedHosts, isHostAllowed, extractHostname2 as extractHostname, assertUrlInScope, extractHostsFromCommand, assertCommandInScope, checkSandboxPlaywright, installSandboxPlaywright, ensureSandboxPlaywright, ensureSandboxBrowser, createSandboxBrowserTools, BROWSER_TOOL_NAMES, createBrowserToolset, checkpointState, completeAuthentication, crawlAuthenticated, createAttackSurfaceReport, createFile, createTask2 as createTask, delegateAuth, detectAuthScheme, documentApp, EndpointTransportEnum, GrpcEndpointMetadataSchema, toGrpcPentestContext, grpcAuthorityTarget, pLimit, documentEndpoint, AttackPathSchema, CweEntrySchema, ValidatedCweEntrySchema, hasCanonicalName, documentVulnerability, createEmailToolset, EMAIL_TOOL_NAMES, SEND_EMAIL_TOOL_NAME, executeCommand, extractJsEndpoints, getMemory2 as getMemory, getPage, grep, httpRequest, listFiles, listMemories2 as listMemories, listTasksTool, readTempfileCapped, getApexTmpRoot, extractFallbackStdout, PersistentShell, probeAuthEndpoints, provideComparisonResults, readFile2 as readFile, readSkill, REPORT_ERROR_TOOL_NAME, ReportErrorReasonSchema, createReportErrorTool, PentestReportedError, RESPONSE_TOOL_NAME, createResponseTool, runAttackSurface, runPentestWorkflow, SMS_LIST_MESSAGES_TOOL_NAME, SMS_TOOL_NAMES, sessionHasSmsPasswordless, runWithBoundedConcurrency, spawnCodingAgent, FindingsRegistry, planFilePath, readPlan, hasPlan, spawnPentestAgent, spawnPentestSwarm, submitPlan, testEndpointVariations, updateFile, updateTask2 as updateTask, validateDiscovery, webSearch, apiRequest, ENDPOINT_TRANSPORTS, listApps, getApp, createApp, updateApp, deleteApp, listEndpoints, getEndpoint, createEndpoint, updateEndpoint, deleteEndpoint, searchApps, searchEndpoints, listWorkspaceApps, createWorkspaceApp, updateWorkspaceApp, listWorkspaceEndpoints, createWorkspaceEndpoint, updateWorkspaceEndpoint, listDomains, createDomain, listWorkspaceDomains, createWorkspaceDomain, writePlan, createAllTools, ALL_TOOL_NAMES, FAST_STRIKE_EXCLUDED_TOOL_NAMES, PLAN_MODE_TOOL_NAMES, SKILL_TOOL_NAMES, StepTraceWriter, OffensiveSecurityAgent };
|