@pensar/apex 2.4.0 → 2.5.0-canary.aa559068
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-48xj79bj.js +20 -0
- package/build/{agent-nhs1w5w0.js → agent-7q3c9cjt.js} +11 -10
- package/build/{agent-5ejt5vpz.js → agent-ve8pkr6q.js} +9 -8
- package/build/{apps-17wvz1d7.js → apps-4rsrnftx.js} +72 -31
- package/build/{auth-z3h9859n.js → auth-0w07dbg2.js} +25 -20
- package/build/authentication-87zzmjdd.js +20 -0
- package/build/blackboxAgent-x0e1wqjx.js +20 -0
- package/build/blackboxPentest-0hwj49dr.js +70 -0
- package/build/{cli-32z0017y.js → cli-12ky98ey.js} +2 -2
- package/build/{cli-5k33webc.js → cli-2ar3m569.js} +45 -43
- package/build/cli-53rm0rrz.js +15 -0
- package/build/{cli-72cvcqhg.js → cli-54egv3xw.js} +1 -1
- package/build/cli-68260ckj.js +12136 -0
- package/build/{cli-gq40s5b3.js → cli-6cq67y5m.js} +5 -3
- package/build/{cli-mavved45.js → cli-7735d17s.js} +46 -25
- package/build/cli-7q3ae3ft.js +6 -0
- package/build/{cli-tznv8pf1.js → cli-8mws7sa5.js} +1 -1
- package/build/cli-9pbk8m32.js +32 -0
- package/build/{cli-swpbx60z.js → cli-avmhkjtv.js} +1 -1481
- package/build/{cli-9rhzhgx2.js → cli-eaaqeve1.js} +1 -1
- package/build/{cli-qqt4gj1w.js → cli-g0whajsq.js} +5 -3
- package/build/{cli-vq52kp7j.js → cli-gb1s7k3v.js} +17 -5
- package/build/{cli-2cbwdk78.js → cli-h8xsqggy.js} +1 -1
- package/build/{cli-0n4r54hq.js → cli-jsw8vt43.js} +1 -1
- package/build/cli-knd276ed.js +1485 -0
- package/build/{cli-repbyhkk.js → cli-kya26m6f.js} +1136 -525
- package/build/{cli-k8kc47pq.js → cli-mmyn6wmb.js} +3 -3
- package/build/{cli-tkc598ey.js → cli-qwv4jsj2.js} +371 -279
- package/build/{cli-xshasbwe.js → cli-r3w58pmq.js} +30 -4
- package/build/{cli-vnynf0js.js → cli-w51z9qjr.js} +10 -4
- package/build/{cli-b1adytsy.js → cli-whp0f8gp.js} +28 -5
- package/build/cli.js +553 -95
- package/build/{config-f1mj4nhd.js → config-z9k13rvy.js} +18 -15
- package/build/{doctor-ekneewa3.js → doctor-tc5zs6pn.js} +8 -7
- package/build/{fastStrike-8zka43xs.js → fastStrike-ssm7df42.js} +13 -10
- package/build/{fixes-b89s5haw.js → fixes-av9nq0hq.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-hqjdg6fg.js → index-1ppbwgf9.js} +17 -9
- package/build/{index-mtq7kmxz.js → index-5wh7gq37.js} +4 -2
- package/build/{index-6d22pyxt.js → index-718m7jw9.js} +1669 -1193
- package/build/{index-rbzhk712.js → index-gng8ebqf.js} +11 -10
- package/build/{index-y5w6n3tb.js → index-hhcjyc6j.js} +2 -2
- package/build/{index-sf16jm0m.js → index-mffgf5hg.js} +9 -7
- package/build/{index-ghwf5z3v.js → index-p1atm3ha.js} +3 -3
- package/build/{index-4ad3sdwk.js → index-vvkvwmyr.js} +4 -4
- package/build/{issues-xx5bs4md.js → issues-hfg8jydv.js} +72 -26
- package/build/{logs-qtxe51w2.js → logs-0rd1z7ct.js} +25 -20
- package/build/{offesecAgent-b9e2xm6v.js → offesecAgent-j4epj93p.js} +10 -9
- package/build/pentest-dp9w88pw.js +30 -0
- package/build/{pentests-6ks3szc4.js → pentests-enyxjtg6.js} +26 -21
- package/build/{targetedPentest-s1ptvq8e.js → targetedPentest-kwabfy86.js} +11 -10
- package/build/{targets-sxygyj87.js → targets-7x0pcmws.js} +27 -22
- package/build/threatModel-zwk5eb6r.js +29 -0
- package/build/{uninstall-tvsh81v8.js → uninstall-psm9btpt.js} +6 -3
- package/build/{upload-7wdyyqmr.js → upload-dybnknjs.js} +8 -7
- package/build/{utils-7fwdkqk6.js → utils-dsfk965b.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-8mws7sa5.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,6 +25,7 @@ import {
|
|
|
24
25
|
list,
|
|
25
26
|
newMessageId,
|
|
26
27
|
newPartId,
|
|
28
|
+
newRunId,
|
|
27
29
|
newSessionId,
|
|
28
30
|
read,
|
|
29
31
|
require_tslib,
|
|
@@ -32,14 +34,14 @@ import {
|
|
|
32
34
|
streamResponse,
|
|
33
35
|
withSubagentSessionBaggage,
|
|
34
36
|
write
|
|
35
|
-
} from "./cli-
|
|
37
|
+
} from "./cli-qwv4jsj2.js";
|
|
36
38
|
import {
|
|
37
39
|
ensureValidToken,
|
|
38
40
|
getPensarApiUrl,
|
|
39
41
|
init_auth,
|
|
40
42
|
init_constants,
|
|
41
43
|
signGatewayRequest
|
|
42
|
-
} from "./cli-
|
|
44
|
+
} from "./cli-jsw8vt43.js";
|
|
43
45
|
import {
|
|
44
46
|
_enum,
|
|
45
47
|
_null,
|
|
@@ -60,17 +62,23 @@ import {
|
|
|
60
62
|
optional,
|
|
61
63
|
preprocess,
|
|
62
64
|
record,
|
|
63
|
-
require_src,
|
|
64
65
|
safeParse,
|
|
65
66
|
string,
|
|
66
67
|
tool,
|
|
67
68
|
union,
|
|
68
69
|
unknown
|
|
69
|
-
} from "./cli-
|
|
70
|
+
} from "./cli-avmhkjtv.js";
|
|
70
71
|
import {
|
|
71
72
|
config,
|
|
72
73
|
init_config
|
|
73
|
-
} from "./cli-
|
|
74
|
+
} from "./cli-54egv3xw.js";
|
|
75
|
+
import {
|
|
76
|
+
getCurrentVersion,
|
|
77
|
+
init_installation
|
|
78
|
+
} from "./cli-w51z9qjr.js";
|
|
79
|
+
import {
|
|
80
|
+
require_src
|
|
81
|
+
} from "./cli-knd276ed.js";
|
|
74
82
|
import {
|
|
75
83
|
__commonJS,
|
|
76
84
|
__require,
|
|
@@ -102763,12 +102771,7 @@ function camoufoxWindowOptions(window2) {
|
|
|
102763
102771
|
const [width, height] = window2;
|
|
102764
102772
|
return {
|
|
102765
102773
|
window: [width, height],
|
|
102766
|
-
screen: {
|
|
102767
|
-
minWidth: width,
|
|
102768
|
-
maxWidth: width,
|
|
102769
|
-
minHeight: height,
|
|
102770
|
-
maxHeight: height
|
|
102771
|
-
}
|
|
102774
|
+
screen: { minWidth: width, minHeight: height }
|
|
102772
102775
|
};
|
|
102773
102776
|
}
|
|
102774
102777
|
async function resolveCamoufoxLaunchOptions(headless, opts) {
|
|
@@ -104466,6 +104469,19 @@ function assertUrlInScope(url, ctx) {
|
|
|
104466
104469
|
throw new ScopeViolationError(hostname, allowedHosts);
|
|
104467
104470
|
}
|
|
104468
104471
|
}
|
|
104472
|
+
function assertFindingEndpointInScope(endpoint, ctx) {
|
|
104473
|
+
const allowedHosts = getAllowedHosts(ctx);
|
|
104474
|
+
if (allowedHosts.length === 0)
|
|
104475
|
+
return;
|
|
104476
|
+
if (!/^https?:\/\//i.test(endpoint.trim()))
|
|
104477
|
+
return;
|
|
104478
|
+
const hostname = extractHostname2(endpoint);
|
|
104479
|
+
if (!hostname)
|
|
104480
|
+
return;
|
|
104481
|
+
if (!isHostAllowed(hostname, allowedHosts)) {
|
|
104482
|
+
throw new ScopeViolationError(hostname, allowedHosts);
|
|
104483
|
+
}
|
|
104484
|
+
}
|
|
104469
104485
|
function extractHostsFromCommand(command) {
|
|
104470
104486
|
const hosts = new Set;
|
|
104471
104487
|
const urlPattern = /https?:\/\/[^\s"'`;|&)<>]+/gi;
|
|
@@ -105055,12 +105071,8 @@ const fs = require('fs');
|
|
|
105055
105071
|
...${JSON.stringify(CAMOUFOX_OPTIONS)},
|
|
105056
105072
|
headless: __headless,
|
|
105057
105073
|
window: __window,
|
|
105058
|
-
|
|
105059
|
-
|
|
105060
|
-
maxWidth: __window[0],
|
|
105061
|
-
minHeight: __window[1],
|
|
105062
|
-
maxHeight: __window[1],
|
|
105063
|
-
},
|
|
105074
|
+
// Floor only — exact-pinning a 720px height throws in browserforge.
|
|
105075
|
+
screen: { minWidth: __window[0], minHeight: __window[1] },
|
|
105064
105076
|
});
|
|
105065
105077
|
fs.writeFileSync('${SANDBOX_CAMOU_CACHE}', JSON.stringify(__camou));
|
|
105066
105078
|
}
|
|
@@ -106761,7 +106773,7 @@ IMPORTANT: Pass protectedEndpoints in authHints when you've discovered 401/403 e
|
|
|
106761
106773
|
if (credentials) {
|
|
106762
106774
|
ctx.session.credentialManager.addFromAuthCredentials(credentials);
|
|
106763
106775
|
}
|
|
106764
|
-
const { runAuthenticationAgent } = await import("./authentication-
|
|
106776
|
+
const { runAuthenticationAgent } = await import("./authentication-87zzmjdd.js");
|
|
106765
106777
|
const localBus = new AgentEventBus;
|
|
106766
106778
|
AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
|
|
106767
106779
|
const result = await runAuthenticationAgent({
|
|
@@ -107555,7 +107567,7 @@ async function generateThreatModelForEndpoint(ctx, input) {
|
|
|
107555
107567
|
return threatModelLimiter(async () => {
|
|
107556
107568
|
if (ctx.abortSignal?.aborted)
|
|
107557
107569
|
return null;
|
|
107558
|
-
const { CodeAgent } = await import("./agent-
|
|
107570
|
+
const { CodeAgent } = await import("./agent-48xj79bj.js");
|
|
107559
107571
|
const subagentId = newSessionId();
|
|
107560
107572
|
const subagentName = `Threat Model: ${input.routePath}`;
|
|
107561
107573
|
ctx.eventBus?.emit("subagent-spawn", {
|
|
@@ -108044,6 +108056,16 @@ import {
|
|
|
108044
108056
|
} from "node:fs";
|
|
108045
108057
|
import { join as join13 } from "node:path";
|
|
108046
108058
|
|
|
108059
|
+
// src/lib/attack-path/types.ts
|
|
108060
|
+
init_zod();
|
|
108061
|
+
var AttackPathSchema = exports_external.array(exports_external.object({
|
|
108062
|
+
applicationId: exports_external.string().optional(),
|
|
108063
|
+
applicationName: exports_external.string().optional(),
|
|
108064
|
+
host: exports_external.string().optional(),
|
|
108065
|
+
relationshipType: exports_external.string().optional(),
|
|
108066
|
+
notes: exports_external.string().optional()
|
|
108067
|
+
}));
|
|
108068
|
+
|
|
108047
108069
|
// src/lib/cwe/types.ts
|
|
108048
108070
|
init_zod();
|
|
108049
108071
|
var CweEntrySchema = exports_external.object({
|
|
@@ -108366,6 +108388,47 @@ var MAX_SEVERITY = {
|
|
|
108366
108388
|
eq4: { 0: 6, 1: 5, 2: 4 },
|
|
108367
108389
|
eq5: { 0: 1, 1: 1, 2: 1 }
|
|
108368
108390
|
};
|
|
108391
|
+
var MAX_COMPOSED = {
|
|
108392
|
+
eq1: {
|
|
108393
|
+
0: ["AV:N/PR:N/UI:N/"],
|
|
108394
|
+
1: ["AV:A/PR:N/UI:N/", "AV:N/PR:L/UI:N/", "AV:N/PR:N/UI:P/"],
|
|
108395
|
+
2: ["AV:P/PR:N/UI:N/", "AV:A/PR:L/UI:P/"]
|
|
108396
|
+
},
|
|
108397
|
+
eq2: {
|
|
108398
|
+
0: ["AC:L/AT:N/"],
|
|
108399
|
+
1: ["AC:H/AT:N/", "AC:L/AT:P/"]
|
|
108400
|
+
},
|
|
108401
|
+
eq3: {
|
|
108402
|
+
0: {
|
|
108403
|
+
"0": ["VC:H/VI:H/VA:H/CR:H/IR:H/AR:H/"],
|
|
108404
|
+
"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/"]
|
|
108405
|
+
},
|
|
108406
|
+
1: {
|
|
108407
|
+
"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/"],
|
|
108408
|
+
"1": [
|
|
108409
|
+
"VC:L/VI:H/VA:L/CR:H/IR:M/AR:H/",
|
|
108410
|
+
"VC:L/VI:H/VA:H/CR:H/IR:M/AR:M/",
|
|
108411
|
+
"VC:H/VI:L/VA:H/CR:M/IR:H/AR:M/",
|
|
108412
|
+
"VC:H/VI:L/VA:L/CR:M/IR:H/AR:H/",
|
|
108413
|
+
"VC:L/VI:L/VA:H/CR:H/IR:H/AR:M/"
|
|
108414
|
+
]
|
|
108415
|
+
},
|
|
108416
|
+
2: {
|
|
108417
|
+
"1": ["VC:L/VI:L/VA:L/CR:H/IR:H/AR:H/"]
|
|
108418
|
+
}
|
|
108419
|
+
},
|
|
108420
|
+
eq4: {
|
|
108421
|
+
0: ["SC:H/SI:S/SA:S/"],
|
|
108422
|
+
1: ["SC:H/SI:H/SA:H/"],
|
|
108423
|
+
2: ["SC:L/SI:L/SA:L/"]
|
|
108424
|
+
},
|
|
108425
|
+
eq5: {
|
|
108426
|
+
0: ["E:A/"],
|
|
108427
|
+
1: ["E:P/"],
|
|
108428
|
+
2: ["E:U/"]
|
|
108429
|
+
}
|
|
108430
|
+
};
|
|
108431
|
+
var NO_IMPACT_METRICS = ["VC", "VI", "VA", "SC", "SI", "SA"];
|
|
108369
108432
|
var STEP = 0.1;
|
|
108370
108433
|
var EPSILON = 10 ** -6;
|
|
108371
108434
|
|
|
@@ -108414,6 +108477,12 @@ var ENVIRONMENTAL_METRICS = [
|
|
|
108414
108477
|
"MSA"
|
|
108415
108478
|
];
|
|
108416
108479
|
var SUPPLEMENTAL_METRICS = ["S", "AU", "R", "V", "RE", "U"];
|
|
108480
|
+
var KNOWN_METRICS = new Set([
|
|
108481
|
+
...BASE_METRICS,
|
|
108482
|
+
...THREAT_METRICS,
|
|
108483
|
+
...ENVIRONMENTAL_METRICS,
|
|
108484
|
+
...SUPPLEMENTAL_METRICS
|
|
108485
|
+
]);
|
|
108417
108486
|
function buildVectorString(metrics) {
|
|
108418
108487
|
const parts = ["CVSS:4.0"];
|
|
108419
108488
|
for (const metric of BASE_METRICS) {
|
|
@@ -108442,39 +108511,49 @@ function buildVectorString(metrics) {
|
|
|
108442
108511
|
}
|
|
108443
108512
|
return parts.join("/");
|
|
108444
108513
|
}
|
|
108445
|
-
|
|
108446
|
-
|
|
108447
|
-
|
|
108448
|
-
|
|
108449
|
-
|
|
108450
|
-
|
|
108451
|
-
|
|
108452
|
-
|
|
108514
|
+
var WORST_CASE_DEFAULTS = {
|
|
108515
|
+
E: "A",
|
|
108516
|
+
CR: "H",
|
|
108517
|
+
IR: "H",
|
|
108518
|
+
AR: "H"
|
|
108519
|
+
};
|
|
108520
|
+
function getEffectiveValue(metrics, metric) {
|
|
108521
|
+
const record3 = metrics;
|
|
108522
|
+
const selected = record3[metric] ?? "X";
|
|
108523
|
+
const worstCase = WORST_CASE_DEFAULTS[metric];
|
|
108524
|
+
if (worstCase !== undefined && selected === "X") {
|
|
108525
|
+
return worstCase;
|
|
108526
|
+
}
|
|
108527
|
+
const modified = record3[`M${metric}`];
|
|
108528
|
+
if (modified !== undefined && modified !== "X") {
|
|
108529
|
+
return modified;
|
|
108530
|
+
}
|
|
108531
|
+
return selected;
|
|
108453
108532
|
}
|
|
108454
108533
|
function computeEQ1(metrics) {
|
|
108455
|
-
const av = getEffectiveValue(metrics, "AV"
|
|
108456
|
-
const pr = getEffectiveValue(metrics, "PR"
|
|
108457
|
-
const ui = getEffectiveValue(metrics, "UI"
|
|
108534
|
+
const av = getEffectiveValue(metrics, "AV");
|
|
108535
|
+
const pr = getEffectiveValue(metrics, "PR");
|
|
108536
|
+
const ui = getEffectiveValue(metrics, "UI");
|
|
108458
108537
|
if (av === "N" && pr === "N" && ui === "N") {
|
|
108459
108538
|
return 0;
|
|
108460
108539
|
}
|
|
108461
|
-
if (
|
|
108540
|
+
if ((av === "N" || pr === "N" || ui === "N") && av !== "P") {
|
|
108462
108541
|
return 1;
|
|
108463
108542
|
}
|
|
108464
108543
|
return 2;
|
|
108465
108544
|
}
|
|
108466
108545
|
function computeEQ2(metrics) {
|
|
108467
|
-
const ac = getEffectiveValue(metrics, "AC"
|
|
108468
|
-
const at = getEffectiveValue(metrics, "AT"
|
|
108546
|
+
const ac = getEffectiveValue(metrics, "AC");
|
|
108547
|
+
const at = getEffectiveValue(metrics, "AT");
|
|
108469
108548
|
if (ac === "L" && at === "N") {
|
|
108470
108549
|
return 0;
|
|
108471
108550
|
}
|
|
108472
108551
|
return 1;
|
|
108473
108552
|
}
|
|
108474
108553
|
function computeEQ3(metrics) {
|
|
108475
|
-
const vc = getEffectiveValue(metrics, "VC"
|
|
108476
|
-
const vi = getEffectiveValue(metrics, "VI"
|
|
108477
|
-
const va = getEffectiveValue(metrics, "VA"
|
|
108554
|
+
const vc = getEffectiveValue(metrics, "VC");
|
|
108555
|
+
const vi = getEffectiveValue(metrics, "VI");
|
|
108556
|
+
const va = getEffectiveValue(metrics, "VA");
|
|
108478
108557
|
if (vc === "H" && vi === "H") {
|
|
108479
108558
|
return 0;
|
|
108480
108559
|
}
|
|
@@ -108484,11 +108563,11 @@ function computeEQ3(metrics) {
|
|
|
108484
108563
|
return 2;
|
|
108485
108564
|
}
|
|
108486
108565
|
function computeEQ4(metrics) {
|
|
108487
|
-
const msi = metrics
|
|
108488
|
-
const msa = metrics
|
|
108489
|
-
const sc = getEffectiveValue(metrics, "SC"
|
|
108490
|
-
const si =
|
|
108491
|
-
const sa =
|
|
108566
|
+
const msi = getEffectiveValue(metrics, "MSI");
|
|
108567
|
+
const msa = getEffectiveValue(metrics, "MSA");
|
|
108568
|
+
const sc = getEffectiveValue(metrics, "SC");
|
|
108569
|
+
const si = getEffectiveValue(metrics, "SI");
|
|
108570
|
+
const sa = getEffectiveValue(metrics, "SA");
|
|
108492
108571
|
if (msi === "S" || msa === "S") {
|
|
108493
108572
|
return 0;
|
|
108494
108573
|
}
|
|
@@ -108498,8 +108577,8 @@ function computeEQ4(metrics) {
|
|
|
108498
108577
|
return 2;
|
|
108499
108578
|
}
|
|
108500
108579
|
function computeEQ5(metrics) {
|
|
108501
|
-
const e = metrics
|
|
108502
|
-
if (e === "A"
|
|
108580
|
+
const e = getEffectiveValue(metrics, "E");
|
|
108581
|
+
if (e === "A") {
|
|
108503
108582
|
return 0;
|
|
108504
108583
|
}
|
|
108505
108584
|
if (e === "P") {
|
|
@@ -108508,12 +108587,12 @@ function computeEQ5(metrics) {
|
|
|
108508
108587
|
return 2;
|
|
108509
108588
|
}
|
|
108510
108589
|
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"
|
|
108590
|
+
const cr = getEffectiveValue(metrics, "CR");
|
|
108591
|
+
const ir = getEffectiveValue(metrics, "IR");
|
|
108592
|
+
const ar = getEffectiveValue(metrics, "AR");
|
|
108593
|
+
const vc = getEffectiveValue(metrics, "VC");
|
|
108594
|
+
const vi = getEffectiveValue(metrics, "VI");
|
|
108595
|
+
const va = getEffectiveValue(metrics, "VA");
|
|
108517
108596
|
if (cr === "H" && vc === "H" || ir === "H" && vi === "H" || ar === "H" && va === "H") {
|
|
108518
108597
|
return 0;
|
|
108519
108598
|
}
|
|
@@ -108529,116 +108608,130 @@ function computeMacroVector(metrics) {
|
|
|
108529
108608
|
return `${eq1}${eq2}${eq3}${eq4}${eq5}${eq6}`;
|
|
108530
108609
|
}
|
|
108531
108610
|
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";
|
|
108611
|
+
return NO_IMPACT_METRICS.every((metric) => getEffectiveValue(metrics, metric) === "N");
|
|
108539
108612
|
}
|
|
108540
|
-
function
|
|
108541
|
-
|
|
108542
|
-
|
|
108543
|
-
|
|
108544
|
-
|
|
108545
|
-
|
|
108546
|
-
|
|
108547
|
-
|
|
108548
|
-
|
|
108549
|
-
|
|
108550
|
-
|
|
108613
|
+
function parseMacroVector(macroVector) {
|
|
108614
|
+
return {
|
|
108615
|
+
eq1: Number(macroVector[0]),
|
|
108616
|
+
eq2: Number(macroVector[1]),
|
|
108617
|
+
eq3: Number(macroVector[2]),
|
|
108618
|
+
eq4: Number(macroVector[3]),
|
|
108619
|
+
eq5: Number(macroVector[4]),
|
|
108620
|
+
eq6: Number(macroVector[5])
|
|
108621
|
+
};
|
|
108622
|
+
}
|
|
108623
|
+
function lowerMacroVectorScore(eq, step) {
|
|
108624
|
+
const stepped = { ...eq, ...step };
|
|
108625
|
+
return MACROVECTOR_LOOKUP[`${stepped.eq1}${stepped.eq2}${stepped.eq3}${stepped.eq4}${stepped.eq5}${stepped.eq6}`];
|
|
108626
|
+
}
|
|
108627
|
+
function lowerEq3Eq6Score(eq) {
|
|
108628
|
+
if (eq.eq3 === 0 && eq.eq6 === 0) {
|
|
108629
|
+
const viaEq6 = lowerMacroVectorScore(eq, { eq6: eq.eq6 + 1 });
|
|
108630
|
+
const viaEq3 = lowerMacroVectorScore(eq, { eq3: eq.eq3 + 1 });
|
|
108631
|
+
if (viaEq6 === undefined || viaEq3 === undefined) {
|
|
108632
|
+
return;
|
|
108633
|
+
}
|
|
108634
|
+
return Math.max(viaEq6, viaEq3);
|
|
108635
|
+
}
|
|
108636
|
+
if (eq.eq3 === 1 && eq.eq6 === 0) {
|
|
108637
|
+
return lowerMacroVectorScore(eq, { eq6: eq.eq6 + 1 });
|
|
108638
|
+
}
|
|
108639
|
+
if (eq.eq3 < 2) {
|
|
108640
|
+
return lowerMacroVectorScore(eq, { eq3: eq.eq3 + 1 });
|
|
108551
108641
|
}
|
|
108552
|
-
|
|
108553
|
-
|
|
108642
|
+
return lowerMacroVectorScore(eq, { eq3: eq.eq3 + 1, eq6: eq.eq6 + 1 });
|
|
108643
|
+
}
|
|
108644
|
+
function composeMaxVectors(eq) {
|
|
108645
|
+
const eq3Maxima = MAX_COMPOSED.eq3[eq.eq3]?.[eq.eq6];
|
|
108646
|
+
if (eq3Maxima === undefined) {
|
|
108647
|
+
throw new Error(`No max severity vector for eq3=${eq.eq3}, eq6=${eq.eq6}`);
|
|
108554
108648
|
}
|
|
108555
|
-
|
|
108556
|
-
|
|
108649
|
+
const vectors = [];
|
|
108650
|
+
for (const eq1Max of MAX_COMPOSED.eq1[eq.eq1]) {
|
|
108651
|
+
for (const eq2Max of MAX_COMPOSED.eq2[eq.eq2]) {
|
|
108652
|
+
for (const eq3Max of eq3Maxima) {
|
|
108653
|
+
for (const eq4Max of MAX_COMPOSED.eq4[eq.eq4]) {
|
|
108654
|
+
for (const eq5Max of MAX_COMPOSED.eq5[eq.eq5]) {
|
|
108655
|
+
vectors.push(eq1Max + eq2Max + eq3Max + eq4Max + eq5Max);
|
|
108656
|
+
}
|
|
108657
|
+
}
|
|
108658
|
+
}
|
|
108659
|
+
}
|
|
108557
108660
|
}
|
|
108558
|
-
return
|
|
108661
|
+
return vectors;
|
|
108559
108662
|
}
|
|
108560
|
-
function
|
|
108561
|
-
const
|
|
108562
|
-
|
|
108563
|
-
|
|
108564
|
-
|
|
108663
|
+
function extractMaxVectorValue(metric, maxVector) {
|
|
108664
|
+
const start = maxVector.indexOf(`${metric}:`);
|
|
108665
|
+
if (start < 0) {
|
|
108666
|
+
throw new Error(`Metric ${metric} missing from max vector ${maxVector}`);
|
|
108667
|
+
}
|
|
108668
|
+
const rest = maxVector.slice(start + metric.length + 1);
|
|
108669
|
+
const end = rest.indexOf("/");
|
|
108670
|
+
return end > 0 ? rest.slice(0, end) : rest;
|
|
108565
108671
|
}
|
|
108566
|
-
function
|
|
108567
|
-
const
|
|
108568
|
-
const
|
|
108569
|
-
|
|
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
|
-
|
|
108599
|
-
|
|
108600
|
-
|
|
108601
|
-
|
|
108602
|
-
|
|
108603
|
-
|
|
108604
|
-
|
|
108605
|
-
|
|
108606
|
-
|
|
108607
|
-
|
|
108608
|
-
|
|
108609
|
-
|
|
108610
|
-
|
|
108611
|
-
|
|
108612
|
-
|
|
108613
|
-
|
|
108614
|
-
|
|
108615
|
-
|
|
108616
|
-
|
|
108617
|
-
|
|
108618
|
-
|
|
108619
|
-
|
|
108620
|
-
|
|
108621
|
-
|
|
108622
|
-
|
|
108623
|
-
|
|
108624
|
-
|
|
108625
|
-
|
|
108626
|
-
|
|
108627
|
-
|
|
108628
|
-
|
|
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;
|
|
108672
|
+
function severityDistances(metrics, maxVector) {
|
|
108673
|
+
const distances = {};
|
|
108674
|
+
for (const [metric, levels] of Object.entries(METRIC_LEVELS)) {
|
|
108675
|
+
const value = getEffectiveValue(metrics, metric);
|
|
108676
|
+
const maxValue = extractMaxVectorValue(metric, maxVector);
|
|
108677
|
+
const level = levels[value];
|
|
108678
|
+
const maxLevel = levels[maxValue];
|
|
108679
|
+
if (level === undefined) {
|
|
108680
|
+
throw new Error(`Unknown value ${metric}:${value}`);
|
|
108681
|
+
}
|
|
108682
|
+
if (maxLevel === undefined) {
|
|
108683
|
+
throw new Error(`Unknown value ${metric}:${maxValue} in ${maxVector}`);
|
|
108684
|
+
}
|
|
108685
|
+
distances[metric] = level - maxLevel;
|
|
108686
|
+
}
|
|
108687
|
+
return distances;
|
|
108688
|
+
}
|
|
108689
|
+
function interpolateScore(metrics, macroVector, macroScore) {
|
|
108690
|
+
const eq = parseMacroVector(macroVector);
|
|
108691
|
+
let distances;
|
|
108692
|
+
for (const maxVector of composeMaxVectors(eq)) {
|
|
108693
|
+
distances = severityDistances(metrics, maxVector);
|
|
108694
|
+
if (Object.values(distances).every((distance) => distance >= 0)) {
|
|
108695
|
+
break;
|
|
108696
|
+
}
|
|
108697
|
+
}
|
|
108698
|
+
if (distances === undefined) {
|
|
108699
|
+
throw new Error(`No max vectors composed for MacroVector ${macroVector}`);
|
|
108700
|
+
}
|
|
108701
|
+
const severityDistance = {
|
|
108702
|
+
eq1: distances.AV + distances.PR + distances.UI,
|
|
108703
|
+
eq2: distances.AC + distances.AT,
|
|
108704
|
+
eq3eq6: distances.VC + distances.VI + distances.VA + distances.CR + distances.IR + distances.AR,
|
|
108705
|
+
eq4: distances.SC + distances.SI + distances.SA
|
|
108706
|
+
};
|
|
108707
|
+
const lowerScore = {
|
|
108708
|
+
eq1: lowerMacroVectorScore(eq, { eq1: eq.eq1 + 1 }),
|
|
108709
|
+
eq2: lowerMacroVectorScore(eq, { eq2: eq.eq2 + 1 }),
|
|
108710
|
+
eq3eq6: lowerEq3Eq6Score(eq),
|
|
108711
|
+
eq4: lowerMacroVectorScore(eq, { eq4: eq.eq4 + 1 })
|
|
108712
|
+
};
|
|
108713
|
+
const macroVectorDepth = {
|
|
108714
|
+
eq1: MAX_SEVERITY.eq1[eq.eq1] * STEP,
|
|
108715
|
+
eq2: MAX_SEVERITY.eq2[eq.eq2] * STEP,
|
|
108716
|
+
eq3eq6: MAX_SEVERITY.eq3eq6[eq.eq3][eq.eq6] * STEP,
|
|
108717
|
+
eq4: MAX_SEVERITY.eq4[eq.eq4] * STEP
|
|
108718
|
+
};
|
|
108719
|
+
let existingLowerCount = 0;
|
|
108720
|
+
let proportionalDistance = 0;
|
|
108721
|
+
for (const key of ["eq1", "eq2", "eq3eq6", "eq4"]) {
|
|
108722
|
+
const lower = lowerScore[key];
|
|
108723
|
+
if (lower === undefined) {
|
|
108724
|
+
continue;
|
|
108725
|
+
}
|
|
108726
|
+
existingLowerCount++;
|
|
108727
|
+
proportionalDistance += (macroScore - lower) * (severityDistance[key] / macroVectorDepth[key]);
|
|
108728
|
+
}
|
|
108729
|
+
if (lowerMacroVectorScore(eq, { eq5: eq.eq5 + 1 }) !== undefined) {
|
|
108730
|
+
existingLowerCount++;
|
|
108731
|
+
}
|
|
108732
|
+
const meanDistance = existingLowerCount === 0 ? 0 : proportionalDistance / existingLowerCount;
|
|
108733
|
+
const score = Math.max(0, Math.min(10, macroScore - meanDistance));
|
|
108734
|
+
return Math.round((score + EPSILON) * 10) / 10;
|
|
108642
108735
|
}
|
|
108643
108736
|
function calculateCVSS4Score(metrics) {
|
|
108644
108737
|
if (hasNoImpact(metrics)) {
|
|
@@ -109480,7 +109573,7 @@ init_lazyLogger();
|
|
|
109480
109573
|
var log6 = scopedLogger(() => createLogger("FindingJudge"));
|
|
109481
109574
|
async function judgeFinding(input, ctx) {
|
|
109482
109575
|
try {
|
|
109483
|
-
const { FindingJudgeAgent } = await import("./agent-
|
|
109576
|
+
const { FindingJudgeAgent } = await import("./agent-ve8pkr6q.js");
|
|
109484
109577
|
const agent = new FindingJudgeAgent({
|
|
109485
109578
|
finding: input,
|
|
109486
109579
|
model: ctx.model,
|
|
@@ -109581,7 +109674,8 @@ var documentVulnerabilityInputSchema = exports_external.object({
|
|
|
109581
109674
|
pocName: exports_external.string().describe("Short descriptive name for the POC"),
|
|
109582
109675
|
pocType: exports_external.enum(["bash", "python", "javascript"]).describe("Script language"),
|
|
109583
109676
|
pocContent: exports_external.string().describe("The full POC script content"),
|
|
109584
|
-
pocDescription: exports_external.string().describe("What this POC demonstrates")
|
|
109677
|
+
pocDescription: exports_external.string().describe("What this POC demonstrates"),
|
|
109678
|
+
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
109679
|
});
|
|
109586
109680
|
function formatMateriality(input) {
|
|
109587
109681
|
return [
|
|
@@ -109651,11 +109745,24 @@ CRITICAL RULES — READ BEFORE CALLING:
|
|
|
109651
109745
|
- POC must exit 0 on success (vulnerability confirmed), non-zero on failure
|
|
109652
109746
|
- POC must print clear evidence of exploitation to stdout
|
|
109653
109747
|
- 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
|
|
109748
|
+
- 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
109749
|
- If the tool returns a POC failure or judge rejection, revise your approach and call again
|
|
109655
109750
|
- Do NOT use this for: positive observations, informational notes, testing limitations, or anything that is not an exploitable security vulnerability
|
|
109656
109751
|
- If you could not exploit a vulnerability, do NOT call this tool — mention it in your final response summary instead`,
|
|
109657
109752
|
inputSchema: documentVulnerabilityInputSchema,
|
|
109658
109753
|
execute: async (input) => {
|
|
109754
|
+
try {
|
|
109755
|
+
assertFindingEndpointInScope(input.endpoint, ctx);
|
|
109756
|
+
} catch (error) {
|
|
109757
|
+
if (error instanceof ScopeViolationError) {
|
|
109758
|
+
return {
|
|
109759
|
+
success: false,
|
|
109760
|
+
error: error.message,
|
|
109761
|
+
message: `Finding endpoint rejected — out of scope: ${error.message}`
|
|
109762
|
+
};
|
|
109763
|
+
}
|
|
109764
|
+
throw error;
|
|
109765
|
+
}
|
|
109659
109766
|
try {
|
|
109660
109767
|
const materializedEvidence = formatMateriality(input);
|
|
109661
109768
|
if (ctx.findingsRegistry) {
|
|
@@ -109870,7 +109977,8 @@ CRITICAL RULES — READ BEFORE CALLING:
|
|
|
109870
109977
|
vulnerabilityClass: input.vulnerabilityClass
|
|
109871
109978
|
},
|
|
109872
109979
|
severity,
|
|
109873
|
-
...evidenceFiles.length > 0 && { evidenceFiles }
|
|
109980
|
+
...evidenceFiles.length > 0 && { evidenceFiles },
|
|
109981
|
+
...input.attackPath && input.attackPath.length > 0 && { attackPath: input.attackPath }
|
|
109874
109982
|
};
|
|
109875
109983
|
if (isVulnerability && ctx.findingsRegistry) {
|
|
109876
109984
|
const check = await ctx.findingsRegistry.register(finding);
|
|
@@ -115366,9 +115474,10 @@ class PersistentShell {
|
|
|
115366
115474
|
${commandOutput}`;
|
|
115367
115475
|
}
|
|
115368
115476
|
const effectiveExit = cmd.forcedExitCode != null ? cmd.forcedExitCode : Number.isNaN(naturalExitCode) ? 1 : naturalExitCode;
|
|
115369
|
-
const
|
|
115477
|
+
const diskStderr = readTempfileCapped(cmd.errPath);
|
|
115370
115478
|
unlinkSafe(cmd.outPath);
|
|
115371
115479
|
unlinkSafe(cmd.errPath);
|
|
115480
|
+
const effectiveStderr = (diskStderr || cmd.stderr || "") + (cmd.forcedStderrSuffix ?? "");
|
|
115372
115481
|
const resolve4 = cmd.resolve;
|
|
115373
115482
|
this.current = null;
|
|
115374
115483
|
this.pendingCancel = null;
|
|
@@ -116106,7 +116215,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
|
|
|
116106
116215
|
});
|
|
116107
116216
|
if (cwd) {
|
|
116108
116217
|
try {
|
|
116109
|
-
const { WhiteboxAttackSurfaceAgent } = await import("./index-
|
|
116218
|
+
const { WhiteboxAttackSurfaceAgent } = await import("./index-gng8ebqf.js");
|
|
116110
116219
|
const localBus = new AgentEventBus;
|
|
116111
116220
|
AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
|
|
116112
116221
|
const agent = new WhiteboxAttackSurfaceAgent({
|
|
@@ -116161,7 +116270,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
|
|
|
116161
116270
|
}
|
|
116162
116271
|
}
|
|
116163
116272
|
try {
|
|
116164
|
-
const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-
|
|
116273
|
+
const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-x0e1wqjx.js");
|
|
116165
116274
|
const localBus = new AgentEventBus;
|
|
116166
116275
|
AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
|
|
116167
116276
|
const agent = new BlackboxAttackSurfaceAgent({
|
|
@@ -116239,7 +116348,7 @@ Omit \`cwd\` for blackbox mode (live target probing only).`,
|
|
|
116239
116348
|
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
116240
116349
|
}),
|
|
116241
116350
|
execute: async ({ target, cwd }) => {
|
|
116242
|
-
const { runPentestWorkflow: workflow } = await import("./pentest-
|
|
116351
|
+
const { runPentestWorkflow: workflow } = await import("./pentest-dp9w88pw.js");
|
|
116243
116352
|
if (!ctx.model) {
|
|
116244
116353
|
return {
|
|
116245
116354
|
success: false,
|
|
@@ -116299,6 +116408,134 @@ function summarizeFindingsBySeverity(findings) {
|
|
|
116299
116408
|
return counts;
|
|
116300
116409
|
}
|
|
116301
116410
|
|
|
116411
|
+
// src/core/agents/offSecAgent/tools/smsListMessages.ts
|
|
116412
|
+
init_dist();
|
|
116413
|
+
init_zod();
|
|
116414
|
+
var SMS_LIST_MESSAGES_TOOL_NAME = "sms_list_messages";
|
|
116415
|
+
var SMS_TOOL_NAMES = [SMS_LIST_MESSAGES_TOOL_NAME];
|
|
116416
|
+
function phoneFromAuthCredentials(session) {
|
|
116417
|
+
const creds = session.config?.authCredentials;
|
|
116418
|
+
const list2 = creds ? Array.isArray(creds) ? creds : [creds] : [];
|
|
116419
|
+
for (const cred of list2) {
|
|
116420
|
+
const phone = cred.additionalFields?.phoneNumber;
|
|
116421
|
+
if (phone)
|
|
116422
|
+
return phone;
|
|
116423
|
+
}
|
|
116424
|
+
}
|
|
116425
|
+
function sessionHasSmsPasswordless(session) {
|
|
116426
|
+
const refs = session.credentialManager?.listReferences() ?? [];
|
|
116427
|
+
if (refs.some((ref) => ref.additionalFieldKeys?.includes("phoneNumber"))) {
|
|
116428
|
+
return true;
|
|
116429
|
+
}
|
|
116430
|
+
return Boolean(phoneFromAuthCredentials(session));
|
|
116431
|
+
}
|
|
116432
|
+
function requireAgentApi() {
|
|
116433
|
+
const base = process.env.AGENT_API_URL;
|
|
116434
|
+
const token = process.env.AGENT_API_TOKEN;
|
|
116435
|
+
if (!base || !token) {
|
|
116436
|
+
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.");
|
|
116437
|
+
}
|
|
116438
|
+
return { base: base.replace(/\/+$/, ""), token };
|
|
116439
|
+
}
|
|
116440
|
+
function resolvePhoneNumber(ctx, input) {
|
|
116441
|
+
if (input.phoneNumber)
|
|
116442
|
+
return input.phoneNumber;
|
|
116443
|
+
const cm = ctx.credentialManager ?? ctx.session.credentialManager;
|
|
116444
|
+
if (input.credentialId) {
|
|
116445
|
+
const stored = cm?.resolve(input.credentialId);
|
|
116446
|
+
const phone = stored?.additionalFields?.phoneNumber;
|
|
116447
|
+
if (!phone) {
|
|
116448
|
+
throw new Error(`Credential ${input.credentialId} has no phoneNumber additional field`);
|
|
116449
|
+
}
|
|
116450
|
+
return phone;
|
|
116451
|
+
}
|
|
116452
|
+
const refs = cm?.listReferences() ?? [];
|
|
116453
|
+
const smsRef = refs.find((ref) => ref.additionalFieldKeys?.includes("phoneNumber"));
|
|
116454
|
+
if (smsRef) {
|
|
116455
|
+
const stored = cm?.resolve(smsRef.id);
|
|
116456
|
+
const phone = stored?.additionalFields?.phoneNumber;
|
|
116457
|
+
if (phone)
|
|
116458
|
+
return phone;
|
|
116459
|
+
}
|
|
116460
|
+
const fromAuth = phoneFromAuthCredentials(ctx.session);
|
|
116461
|
+
if (fromAuth)
|
|
116462
|
+
return fromAuth;
|
|
116463
|
+
throw new Error("No sms-passwordless credential with a phoneNumber field is available");
|
|
116464
|
+
}
|
|
116465
|
+
async function agentFetch(path, init) {
|
|
116466
|
+
const { token, ...rest } = init;
|
|
116467
|
+
return fetch(path, {
|
|
116468
|
+
...rest,
|
|
116469
|
+
headers: {
|
|
116470
|
+
Authorization: `Bearer ${token}`,
|
|
116471
|
+
...rest.headers ?? {}
|
|
116472
|
+
}
|
|
116473
|
+
});
|
|
116474
|
+
}
|
|
116475
|
+
function smsListMessages(ctx) {
|
|
116476
|
+
return tool({
|
|
116477
|
+
description: `List inbound SMS on a Mobile OTP (sms-passwordless) receiving number.
|
|
116478
|
+
|
|
116479
|
+
This is a single read — it does not wait. After the target sends a code, sleep with execute_command (e.g. sleep 5) then call this tool. If the list is empty, sleep and list again, or stop and report what you observed. Do not hang in a wait loop.
|
|
116480
|
+
|
|
116481
|
+
Pass sinceMs as Date.now() from the send-code click so earlier messages are ignored. Set claim=true to consume the newest unconsumed message (exclusive; other runs cannot reuse that OTP). Fill the OTP with browser_fill from the returned code/body — do not report phone_verification as a barrier for this flow.
|
|
116482
|
+
|
|
116483
|
+
Requires a Console sandbox (AGENT_API_URL). Concurrent lists on the same shared number are exclusive; a 429 means another run holds the number.`,
|
|
116484
|
+
inputSchema: exports_external.object({
|
|
116485
|
+
credentialId: exports_external.string().optional().describe("Credential ID whose additionalFields.phoneNumber is the receiving number. Omit to use the session's sms-passwordless credential."),
|
|
116486
|
+
phoneNumber: exports_external.string().optional().describe("Explicit E.164 receiving number. Prefer credentialId so the number is resolved from the stored credential."),
|
|
116487
|
+
sinceMs: exports_external.number().describe("Epoch milliseconds of the send-code click. Messages received before this timestamp are ignored."),
|
|
116488
|
+
claim: exports_external.boolean().optional().describe("If true, consume the newest unconsumed message so other runs cannot reuse the OTP. Defaults to false (list only)."),
|
|
116489
|
+
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
116490
|
+
}),
|
|
116491
|
+
execute: async ({ credentialId, phoneNumber, sinceMs, claim }) => {
|
|
116492
|
+
const { base, token } = requireAgentApi();
|
|
116493
|
+
const toPhoneNumber = resolvePhoneNumber(ctx, {
|
|
116494
|
+
credentialId,
|
|
116495
|
+
phoneNumber
|
|
116496
|
+
});
|
|
116497
|
+
const since = new Date(sinceMs).toISOString();
|
|
116498
|
+
const url = new URL(`${base}/agent/sms/messages`);
|
|
116499
|
+
url.searchParams.set("toPhoneNumber", toPhoneNumber);
|
|
116500
|
+
url.searchParams.set("since", since);
|
|
116501
|
+
if (claim)
|
|
116502
|
+
url.searchParams.set("claim", "1");
|
|
116503
|
+
const res = await agentFetch(url.toString(), {
|
|
116504
|
+
method: "GET",
|
|
116505
|
+
token,
|
|
116506
|
+
signal: ctx.abortSignal
|
|
116507
|
+
});
|
|
116508
|
+
if (res.status === 429) {
|
|
116509
|
+
return {
|
|
116510
|
+
success: false,
|
|
116511
|
+
error: "Another agent run holds the exclusive lease on this phone number. Wait and retry, or use a different Mobile OTP number."
|
|
116512
|
+
};
|
|
116513
|
+
}
|
|
116514
|
+
if (res.status === 403) {
|
|
116515
|
+
return {
|
|
116516
|
+
success: false,
|
|
116517
|
+
error: "This phone number is not configured as a Mobile OTP credential in this workspace."
|
|
116518
|
+
};
|
|
116519
|
+
}
|
|
116520
|
+
if (res.status === 409) {
|
|
116521
|
+
return {
|
|
116522
|
+
success: false,
|
|
116523
|
+
error: "That SMS was already claimed. List without claim, or wait for a newer message."
|
|
116524
|
+
};
|
|
116525
|
+
}
|
|
116526
|
+
if (!res.ok) {
|
|
116527
|
+
throw new Error(`SMS list API error ${res.status} ${res.statusText}`);
|
|
116528
|
+
}
|
|
116529
|
+
const data = await res.json();
|
|
116530
|
+
return {
|
|
116531
|
+
success: true,
|
|
116532
|
+
messages: data.messages,
|
|
116533
|
+
claimed: data.claimed
|
|
116534
|
+
};
|
|
116535
|
+
}
|
|
116536
|
+
});
|
|
116537
|
+
}
|
|
116538
|
+
|
|
116302
116539
|
// src/core/utils/concurrency.ts
|
|
116303
116540
|
var import_api = __toESM(require_src(), 1);
|
|
116304
116541
|
async function runWithBoundedConcurrency(items, concurrency, fn, abortSignal) {
|
|
@@ -117817,7 +118054,7 @@ Returns an array of results with the text output from each agent.`,
|
|
|
117817
118054
|
});
|
|
117818
118055
|
}
|
|
117819
118056
|
async function runSingleCodingAgent(ctx, codebasePath, objective, agentIndex, name) {
|
|
117820
|
-
const { CodeAgent } = await import("./agent-
|
|
118057
|
+
const { CodeAgent } = await import("./agent-48xj79bj.js");
|
|
117821
118058
|
const childSessionId = newSessionId();
|
|
117822
118059
|
const subagentId = childSessionId;
|
|
117823
118060
|
ctx.eventBus?.emit("subagent-spawn", {
|
|
@@ -118298,13 +118535,17 @@ init_dist();
|
|
|
118298
118535
|
init_zod();
|
|
118299
118536
|
init_id();
|
|
118300
118537
|
var WORKER_DRAIN_GRACE_MS = 30000;
|
|
118538
|
+
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
118539
|
function spawnPentestAgent(ctx) {
|
|
118540
|
+
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
118541
|
return tool({
|
|
118303
118542
|
description: `Spawn a single focused pentest sub-agent (worker) to test ONE objective at a time.
|
|
118304
118543
|
|
|
118305
118544
|
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
118545
|
|
|
118307
|
-
CRITICAL — \`target\` must be
|
|
118546
|
+
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.
|
|
118547
|
+
|
|
118548
|
+
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
118549
|
|
|
118309
118550
|
Each spawn produces an independent TargetedPentestAgent that:
|
|
118310
118551
|
1. Tests the assigned objective(s) deeply (execute_command, http_request, browser tools)
|
|
@@ -118322,7 +118563,7 @@ False-positive discipline: workers should not call document_vulnerability for pu
|
|
|
118322
118563
|
Returns the worker's summary, objective results, and finding count — but NOT the findings themselves (those land in the shared registry).`,
|
|
118323
118564
|
inputSchema: exports_external.object({
|
|
118324
118565
|
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(
|
|
118566
|
+
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
118567
|
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
118568
|
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
118569
|
toolCallDescription: exports_external.string().describe("Concise, human-readable description of what this spawn is doing (shown in the UI).")
|
|
@@ -118334,7 +118575,21 @@ Returns the worker's summary, objective results, and finding count — but NOT t
|
|
|
118334
118575
|
message: "spawn_pentest_agent requires a model in the tool context."
|
|
118335
118576
|
};
|
|
118336
118577
|
}
|
|
118337
|
-
|
|
118578
|
+
if (typeof target !== "string" || parseTargetUrl(target) === null) {
|
|
118579
|
+
return {
|
|
118580
|
+
success: false,
|
|
118581
|
+
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.`
|
|
118582
|
+
};
|
|
118583
|
+
}
|
|
118584
|
+
try {
|
|
118585
|
+
assertUrlInScope(target, ctx);
|
|
118586
|
+
} catch (error) {
|
|
118587
|
+
if (error instanceof ScopeViolationError) {
|
|
118588
|
+
return { success: false, message: error.message };
|
|
118589
|
+
}
|
|
118590
|
+
throw error;
|
|
118591
|
+
}
|
|
118592
|
+
const { TargetedPentestAgent } = await import("./agent-7q3c9cjt.js");
|
|
118338
118593
|
const findingsRegistry = ctx.findingsRegistry ?? FindingsRegistry.fromDirectory(ctx.session.findingsPath, {
|
|
118339
118594
|
model: ctx.model,
|
|
118340
118595
|
authConfig: ctx.authConfig,
|
|
@@ -118365,12 +118620,15 @@ Returns the worker's summary, objective results, and finding count — but NOT t
|
|
|
118365
118620
|
agent = new TargetedPentestAgent({
|
|
118366
118621
|
target,
|
|
118367
118622
|
grpc: workerInheritsGrpc(target, ctx.grpc, ctx.target) ? ctx.grpc : undefined,
|
|
118623
|
+
systemScope: ctx.systemScope,
|
|
118368
118624
|
objectives,
|
|
118369
118625
|
context: enrichedContext,
|
|
118370
118626
|
model: ctx.model,
|
|
118371
118627
|
session: ctx.session,
|
|
118372
118628
|
authConfig: ctx.authConfig,
|
|
118373
118629
|
abortSignal: ctx.abortSignal,
|
|
118630
|
+
onStepFinish: ctx.onStepFinish,
|
|
118631
|
+
onCacheMetrics: ctx.onCacheMetrics,
|
|
118374
118632
|
findingsRegistry,
|
|
118375
118633
|
eventBus: childBus,
|
|
118376
118634
|
subagentId,
|
|
@@ -118429,7 +118687,7 @@ function workerInheritsGrpc(target, grpc, orchestratorTarget) {
|
|
|
118429
118687
|
function buildSharedBrowserSessionContext(existingContext) {
|
|
118430
118688
|
const note = `## Shared Browser Session
|
|
118431
118689
|
You are driving the orchestrator's live Playwright browser (NOT a private copy):
|
|
118432
|
-
- You
|
|
118690
|
+
- You inherit authentication only for origins where the orchestrator established it. Verify protected access on your assigned origin first. ${ORIGIN_AUTH_FAILURE_GUIDANCE}
|
|
118433
118691
|
- 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
118692
|
- 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
118693
|
if (!existingContext || existingContext.trim().length === 0) {
|
|
@@ -118468,7 +118726,7 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
118468
118726
|
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
118469
118727
|
}),
|
|
118470
118728
|
execute: async ({ targets }) => {
|
|
118471
|
-
const { runPentestSwarm, DEFAULT_CONCURRENCY: DEFAULT_CONCURRENCY2 } = await import("./pentest-
|
|
118729
|
+
const { runPentestSwarm, DEFAULT_CONCURRENCY: DEFAULT_CONCURRENCY2 } = await import("./pentest-dp9w88pw.js");
|
|
118472
118730
|
if (!ctx.model) {
|
|
118473
118731
|
return {
|
|
118474
118732
|
success: false,
|
|
@@ -118490,6 +118748,8 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
118490
118748
|
abortSignal: ctx.abortSignal,
|
|
118491
118749
|
findingsRegistry,
|
|
118492
118750
|
eventBus: ctx.eventBus,
|
|
118751
|
+
onStepFinish: ctx.onStepFinish,
|
|
118752
|
+
onCacheMetrics: ctx.onCacheMetrics,
|
|
118493
118753
|
concurrency: DEFAULT_CONCURRENCY2,
|
|
118494
118754
|
enableThinking: ctx.enableThinking,
|
|
118495
118755
|
thinkingEffort: ctx.thinkingEffort,
|
|
@@ -119104,6 +119364,29 @@ async function handleSearchResponse(response) {
|
|
|
119104
119364
|
// src/core/api/apiClient.ts
|
|
119105
119365
|
init_auth();
|
|
119106
119366
|
init_config();
|
|
119367
|
+
|
|
119368
|
+
// src/core/api/clientIdentity.ts
|
|
119369
|
+
init_installation();
|
|
119370
|
+
var CLIENT_HEADERS = {
|
|
119371
|
+
client: "X-Pensar-Client",
|
|
119372
|
+
version: "X-Pensar-Client-Version",
|
|
119373
|
+
command: "X-Pensar-Command"
|
|
119374
|
+
};
|
|
119375
|
+
var CLIENT_NAME = "cli";
|
|
119376
|
+
var currentCommand;
|
|
119377
|
+
function getCurrentCommand() {
|
|
119378
|
+
return currentCommand;
|
|
119379
|
+
}
|
|
119380
|
+
function clientIdentityHeaders() {
|
|
119381
|
+
const command = getCurrentCommand();
|
|
119382
|
+
return {
|
|
119383
|
+
[CLIENT_HEADERS.client]: CLIENT_NAME,
|
|
119384
|
+
[CLIENT_HEADERS.version]: getCurrentVersion(),
|
|
119385
|
+
...command ? { [CLIENT_HEADERS.command]: command } : {}
|
|
119386
|
+
};
|
|
119387
|
+
}
|
|
119388
|
+
|
|
119389
|
+
// src/core/api/apiClient.ts
|
|
119107
119390
|
init_constants();
|
|
119108
119391
|
async function getAuthHeaders() {
|
|
119109
119392
|
const cfg = await config.get();
|
|
@@ -119117,7 +119400,8 @@ async function getAuthHeaders() {
|
|
|
119117
119400
|
}
|
|
119118
119401
|
const headers = {
|
|
119119
119402
|
"Content-Type": "application/json",
|
|
119120
|
-
Authorization: `Bearer ${validToken.token}
|
|
119403
|
+
Authorization: `Bearer ${validToken.token}`,
|
|
119404
|
+
...clientIdentityHeaders()
|
|
119121
119405
|
};
|
|
119122
119406
|
if (cfg.workspaceId) {
|
|
119123
119407
|
headers["X-Workspace-Id"] = cfg.workspaceId;
|
|
@@ -119151,6 +119435,12 @@ async function apiRequest(method, path, body) {
|
|
|
119151
119435
|
}
|
|
119152
119436
|
|
|
119153
119437
|
// src/core/api/apps.ts
|
|
119438
|
+
var ENDPOINT_TRANSPORTS = [
|
|
119439
|
+
"http",
|
|
119440
|
+
"grpc",
|
|
119441
|
+
"grpc_web",
|
|
119442
|
+
"connect"
|
|
119443
|
+
];
|
|
119154
119444
|
async function listApps(opts) {
|
|
119155
119445
|
const params = new URLSearchParams;
|
|
119156
119446
|
if (opts?.limit !== undefined)
|
|
@@ -119263,7 +119553,7 @@ var ENDPOINT_TYPES = [
|
|
|
119263
119553
|
"file-storage",
|
|
119264
119554
|
"asset"
|
|
119265
119555
|
];
|
|
119266
|
-
var
|
|
119556
|
+
var ENDPOINT_TRANSPORTS2 = [
|
|
119267
119557
|
"http",
|
|
119268
119558
|
"grpc",
|
|
119269
119559
|
"grpc_web",
|
|
@@ -119309,7 +119599,7 @@ var createWorkspaceEndpointInputSchema = exports_external.object({
|
|
|
119309
119599
|
endpoint: exports_external.string().min(1).describe("Endpoint path, URL, or route"),
|
|
119310
119600
|
description: exports_external.string().describe("Endpoint description"),
|
|
119311
119601
|
type: exports_external.enum(ENDPOINT_TYPES).optional(),
|
|
119312
|
-
transport: exports_external.enum(
|
|
119602
|
+
transport: exports_external.enum(ENDPOINT_TRANSPORTS2).nullish().transform((value) => value ?? undefined).optional().describe("Wire transport; defaults to http when omitted"),
|
|
119313
119603
|
location: exports_external.string().optional().describe("Source file path"),
|
|
119314
119604
|
startLineNumber: exports_external.number().int().min(0).optional(),
|
|
119315
119605
|
endLineNumber: exports_external.number().int().min(0).optional(),
|
|
@@ -119328,7 +119618,7 @@ var updateWorkspaceEndpointInputSchema = exports_external.object({
|
|
|
119328
119618
|
endpoint: exports_external.string().min(1).nullish().transform((value) => value ?? undefined).optional(),
|
|
119329
119619
|
description: exports_external.string().nullish().transform((value) => value ?? undefined).optional(),
|
|
119330
119620
|
type: exports_external.enum(ENDPOINT_TYPES).nullable().optional(),
|
|
119331
|
-
transport: exports_external.enum(
|
|
119621
|
+
transport: exports_external.enum(ENDPOINT_TRANSPORTS2).nullish().transform((value) => value ?? undefined).optional().describe("Corrected wire transport"),
|
|
119332
119622
|
location: exports_external.string().nullable().optional(),
|
|
119333
119623
|
startLineNumber: exports_external.number().int().min(0).nullable().optional(),
|
|
119334
119624
|
endLineNumber: exports_external.number().int().min(0).nullable().optional(),
|
|
@@ -119456,10 +119746,6 @@ Use only when the user explicitly asks to change or repair an existing workspace
|
|
|
119456
119746
|
});
|
|
119457
119747
|
}
|
|
119458
119748
|
|
|
119459
|
-
// src/core/agents/offSecAgent/tools/workspaceDomains.ts
|
|
119460
|
-
init_dist();
|
|
119461
|
-
init_zod();
|
|
119462
|
-
|
|
119463
119749
|
// src/core/api/domains.ts
|
|
119464
119750
|
async function listDomains() {
|
|
119465
119751
|
return apiRequest("GET", "/domains");
|
|
@@ -119469,6 +119755,8 @@ async function createDomain(data) {
|
|
|
119469
119755
|
}
|
|
119470
119756
|
|
|
119471
119757
|
// src/core/agents/offSecAgent/tools/workspaceDomains.ts
|
|
119758
|
+
init_dist();
|
|
119759
|
+
init_zod();
|
|
119472
119760
|
var toolCallDescription2 = exports_external.string().describe("A concise description of the workspace operation");
|
|
119473
119761
|
var listWorkspaceDomainsInputSchema = exports_external.object({
|
|
119474
119762
|
toolCallDescription: toolCallDescription2
|
|
@@ -124352,6 +124640,7 @@ function createAllTools(ctx) {
|
|
|
124352
124640
|
email_list_messages: emailListMessages(ctx),
|
|
124353
124641
|
email_search_messages: emailSearchMessages(ctx),
|
|
124354
124642
|
email_get_message: emailGetMessage(ctx),
|
|
124643
|
+
sms_list_messages: smsListMessages(ctx),
|
|
124355
124644
|
web_search: webSearch(ctx),
|
|
124356
124645
|
get_page: getPage(ctx),
|
|
124357
124646
|
...ctx.skillsRegistry ? { read_skill: readSkill(ctx) } : {},
|
|
@@ -124439,6 +124728,7 @@ var ALL_TOOL_NAMES = [
|
|
|
124439
124728
|
"email_get_attachments",
|
|
124440
124729
|
"email_mark_read",
|
|
124441
124730
|
"send_email",
|
|
124731
|
+
"sms_list_messages",
|
|
124442
124732
|
"web_search",
|
|
124443
124733
|
"get_page",
|
|
124444
124734
|
"checkpoint_state",
|
|
@@ -124510,6 +124800,7 @@ var PLAN_MODE_TOOL_NAMES = [
|
|
|
124510
124800
|
"email_get_message",
|
|
124511
124801
|
"email_search_messages",
|
|
124512
124802
|
"email_get_attachments",
|
|
124803
|
+
"sms_list_messages",
|
|
124513
124804
|
"web_search",
|
|
124514
124805
|
"get_page",
|
|
124515
124806
|
"write_plan",
|
|
@@ -124521,6 +124812,7 @@ var PLAN_MODE_TOOL_NAMES = [
|
|
|
124521
124812
|
var SKILL_TOOL_NAMES = ["read_skill"];
|
|
124522
124813
|
|
|
124523
124814
|
// src/core/agents/offSecAgent/trace.ts
|
|
124815
|
+
init_observability();
|
|
124524
124816
|
import { createHash as createHash2 } from "node:crypto";
|
|
124525
124817
|
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync13 } from "node:fs";
|
|
124526
124818
|
import { dirname as dirname8 } from "node:path";
|
|
@@ -124707,13 +124999,15 @@ class StepTraceWriter {
|
|
|
124707
124999
|
this.appendRecord(record3);
|
|
124708
125000
|
}
|
|
124709
125001
|
appendRecord(record3) {
|
|
125002
|
+
const correlation = getActiveTraceCorrelation();
|
|
125003
|
+
const enriched = correlation ? { ...record3, correlation } : record3;
|
|
124710
125004
|
try {
|
|
124711
|
-
appendFileSync3(this.tracePath, `${JSON.stringify(
|
|
125005
|
+
appendFileSync3(this.tracePath, `${JSON.stringify(enriched)}
|
|
124712
125006
|
`);
|
|
124713
125007
|
} catch {}
|
|
124714
125008
|
try {
|
|
124715
125009
|
this.eventBus?.emit("trace-record", {
|
|
124716
|
-
record:
|
|
125010
|
+
record: enriched,
|
|
124717
125011
|
subagentId: this.agentId ?? undefined
|
|
124718
125012
|
});
|
|
124719
125013
|
} catch {}
|
|
@@ -124723,8 +125017,8 @@ class StepTraceWriter {
|
|
|
124723
125017
|
// src/core/agents/offSecAgent/offensiveSecurityAgent.ts
|
|
124724
125018
|
init_dist();
|
|
124725
125019
|
init_ai();
|
|
124726
|
-
|
|
124727
|
-
import {
|
|
125020
|
+
var import_api2 = __toESM(require_src(), 1);
|
|
125021
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync14 } from "node:fs";
|
|
124728
125022
|
import { join as join27 } from "node:path";
|
|
124729
125023
|
init_id();
|
|
124730
125024
|
init_structured();
|
|
@@ -125006,9 +125300,464 @@ var OperatorSettingsObject = exports_external.object({
|
|
|
125006
125300
|
// src/core/agents/offSecAgent/offensiveSecurityAgent.ts
|
|
125007
125301
|
init_session();
|
|
125008
125302
|
init_lazyLogger();
|
|
125009
|
-
|
|
125303
|
+
|
|
125304
|
+
// src/core/agents/offSecAgent/interruptedStepFinalization.ts
|
|
125305
|
+
import { existsSync as existsSync18, readFileSync as readFileSync8 } from "node:fs";
|
|
125306
|
+
|
|
125307
|
+
// src/core/agents/offSecAgent/interruptedStepMessages.ts
|
|
125308
|
+
function buildSyntheticToolResults(input) {
|
|
125309
|
+
const output = {
|
|
125310
|
+
type: "error-text",
|
|
125311
|
+
value: `Tool execution aborted: ${input.reason}`
|
|
125312
|
+
};
|
|
125313
|
+
const parts = [];
|
|
125314
|
+
for (const [toolCallId, toolName] of input.inFlightTools) {
|
|
125315
|
+
const result = toolName === input.responseToolName && input.responseSubmitted ? { type: "text", value: "Response submitted." } : output;
|
|
125316
|
+
parts.push({
|
|
125317
|
+
type: "tool-result",
|
|
125318
|
+
toolCallId,
|
|
125319
|
+
toolName,
|
|
125320
|
+
output: result
|
|
125321
|
+
});
|
|
125322
|
+
}
|
|
125323
|
+
return parts;
|
|
125324
|
+
}
|
|
125325
|
+
function baseContainsToolCalls(msg, toolCallIds) {
|
|
125326
|
+
if (!Array.isArray(msg.content))
|
|
125327
|
+
return false;
|
|
125328
|
+
const contentToolIds = new Set(msg.content.filter((p) => p.type === "tool-call" && p.toolCallId).map((p) => p.toolCallId));
|
|
125329
|
+
return [...toolCallIds].every((id) => contentToolIds.has(id));
|
|
125330
|
+
}
|
|
125331
|
+
function buildInterruptedStepMessages(input) {
|
|
125332
|
+
const { base, inFlightTools, completedResults, syntheticParts } = input;
|
|
125333
|
+
const allToolCallIds = new Set([
|
|
125334
|
+
...inFlightTools.keys(),
|
|
125335
|
+
...completedResults.map((r) => r.toolCallId)
|
|
125336
|
+
]);
|
|
125337
|
+
const lastMsg = base[base.length - 1];
|
|
125338
|
+
const needsStepReconstruction = !lastMsg || lastMsg.role !== "assistant" || !baseContainsToolCalls(lastMsg, allToolCallIds);
|
|
125339
|
+
const appended = [];
|
|
125340
|
+
if (needsStepReconstruction) {
|
|
125341
|
+
const stepTools = [
|
|
125342
|
+
...inFlightTools,
|
|
125343
|
+
...completedResults.map((r) => [
|
|
125344
|
+
r.toolCallId,
|
|
125345
|
+
r.toolName
|
|
125346
|
+
])
|
|
125347
|
+
];
|
|
125348
|
+
const reconstructInput = (toolCallId) => {
|
|
125349
|
+
const raw = input.streamedArgText?.get(toolCallId);
|
|
125350
|
+
if (!raw)
|
|
125351
|
+
return {};
|
|
125352
|
+
try {
|
|
125353
|
+
return JSON.parse(raw);
|
|
125354
|
+
} catch {
|
|
125355
|
+
return { _partial: raw };
|
|
125356
|
+
}
|
|
125357
|
+
};
|
|
125358
|
+
appended.push({
|
|
125359
|
+
role: "assistant",
|
|
125360
|
+
content: stepTools.map(([toolCallId, toolName]) => ({
|
|
125361
|
+
type: "tool-call",
|
|
125362
|
+
toolCallId,
|
|
125363
|
+
toolName,
|
|
125364
|
+
input: reconstructInput(toolCallId)
|
|
125365
|
+
}))
|
|
125366
|
+
});
|
|
125367
|
+
}
|
|
125368
|
+
appended.push({
|
|
125369
|
+
role: "tool",
|
|
125370
|
+
content: [...completedResults, ...syntheticParts]
|
|
125371
|
+
});
|
|
125372
|
+
return { appended, needsStepReconstruction };
|
|
125373
|
+
}
|
|
125374
|
+
|
|
125375
|
+
// src/core/agents/offSecAgent/interruptedStepFinalization.ts
|
|
125376
|
+
function createInterruptedStepFinalizer(deps) {
|
|
125377
|
+
const debug = deps.debugLog;
|
|
125378
|
+
const readBaseFromDisk = deps.readBaseFromDisk ?? (() => {
|
|
125379
|
+
const path = deps.writer.messagesPath;
|
|
125380
|
+
if (!path || !existsSync18(path))
|
|
125381
|
+
return null;
|
|
125382
|
+
try {
|
|
125383
|
+
return JSON.parse(readFileSync8(path, "utf-8"));
|
|
125384
|
+
} catch {
|
|
125385
|
+
return null;
|
|
125386
|
+
}
|
|
125387
|
+
});
|
|
125388
|
+
return async (input) => {
|
|
125389
|
+
const { snapshot, reason } = input;
|
|
125390
|
+
const { inFlightTools, completedResults, streamedArgText } = snapshot;
|
|
125391
|
+
const syntheticParts = buildSyntheticToolResults({
|
|
125392
|
+
inFlightTools,
|
|
125393
|
+
reason,
|
|
125394
|
+
responseToolName: deps.responseToolName,
|
|
125395
|
+
responseSubmitted: deps.responseToolFired()
|
|
125396
|
+
});
|
|
125397
|
+
let emissionError;
|
|
125398
|
+
let hasEmissionError = false;
|
|
125399
|
+
if (debug) {
|
|
125400
|
+
const responseInFlight = [...inFlightTools.entries()].filter(([, n7]) => n7 === deps.responseToolName);
|
|
125401
|
+
if (responseInFlight.length > 0) {
|
|
125402
|
+
debug(`[response-debug] emitSyntheticToolResults closing ${responseInFlight.length} response call(s) ` + `ids=${responseInFlight.map(([id]) => id).join(",")} reason="${reason}" ` + `responseToolFired=${deps.responseToolFired()}`);
|
|
125403
|
+
}
|
|
125404
|
+
}
|
|
125405
|
+
for (const part of syntheticParts) {
|
|
125406
|
+
try {
|
|
125407
|
+
deps.eventBus.emit("tool-result", {
|
|
125408
|
+
toolCallId: part.toolCallId,
|
|
125409
|
+
toolName: part.toolName,
|
|
125410
|
+
result: part.output,
|
|
125411
|
+
sessionId: deps.sessionId,
|
|
125412
|
+
subagentId: deps.subagentId,
|
|
125413
|
+
partId: input.partIdFor?.(part.toolCallId),
|
|
125414
|
+
messageId: input.messageId
|
|
125415
|
+
});
|
|
125416
|
+
} catch (error) {
|
|
125417
|
+
if (!hasEmissionError) {
|
|
125418
|
+
emissionError = error;
|
|
125419
|
+
hasEmissionError = true;
|
|
125420
|
+
}
|
|
125421
|
+
}
|
|
125422
|
+
}
|
|
125423
|
+
if (!deps.writer.messagesPath) {
|
|
125424
|
+
if (hasEmissionError)
|
|
125425
|
+
throw emissionError;
|
|
125426
|
+
return;
|
|
125427
|
+
}
|
|
125428
|
+
deps.writer.cancelTimer();
|
|
125429
|
+
await deps.writer.waitForPendingWrites();
|
|
125430
|
+
let base = deps.writer.latest ?? [];
|
|
125431
|
+
if (base.length === 0) {
|
|
125432
|
+
base = readBaseFromDisk() ?? [];
|
|
125433
|
+
}
|
|
125434
|
+
const { appended, needsStepReconstruction } = buildInterruptedStepMessages({
|
|
125435
|
+
base,
|
|
125436
|
+
inFlightTools,
|
|
125437
|
+
completedResults,
|
|
125438
|
+
syntheticParts,
|
|
125439
|
+
streamedArgText
|
|
125440
|
+
});
|
|
125441
|
+
if (needsStepReconstruction && debug) {
|
|
125442
|
+
const responseReconstructed = [
|
|
125443
|
+
...inFlightTools,
|
|
125444
|
+
...completedResults.map((r) => [r.toolCallId, r.toolName])
|
|
125445
|
+
].filter(([, n7]) => n7 === deps.responseToolName).map(([id]) => id);
|
|
125446
|
+
if (responseReconstructed.length > 0) {
|
|
125447
|
+
debug(`[response-debug] step-reconstruction for response call(s) ` + `ids=${responseReconstructed.join(",")} ` + `preservedArgChars=${responseReconstructed.map((id) => streamedArgText?.get(id)?.length ?? 0).join(",")}`);
|
|
125448
|
+
}
|
|
125449
|
+
}
|
|
125450
|
+
const next = [...base, ...appended];
|
|
125451
|
+
deps.writer.setLatest(next);
|
|
125452
|
+
try {
|
|
125453
|
+
await deps.writer.enqueueWrite(next);
|
|
125454
|
+
deps.writer.markSyntheticsPersisted();
|
|
125455
|
+
} catch {}
|
|
125456
|
+
if (hasEmissionError)
|
|
125457
|
+
throw emissionError;
|
|
125458
|
+
};
|
|
125459
|
+
}
|
|
125460
|
+
|
|
125461
|
+
// src/core/agents/offSecAgent/messagePersistence.ts
|
|
125462
|
+
import { writeFile as writeFile7 } from "node:fs/promises";
|
|
125463
|
+
var PERSIST_INTERVAL_MS = 15000;
|
|
125464
|
+
|
|
125465
|
+
class AgentMessageWriter {
|
|
125466
|
+
intervalMs;
|
|
125467
|
+
writeImpl;
|
|
125468
|
+
path;
|
|
125469
|
+
pending = null;
|
|
125470
|
+
tail = Promise.resolve();
|
|
125471
|
+
persistTimer = null;
|
|
125472
|
+
syntheticsWritten = false;
|
|
125473
|
+
constructor(options) {
|
|
125474
|
+
this.path = options.messagesPath;
|
|
125475
|
+
this.intervalMs = options.intervalMs ?? PERSIST_INTERVAL_MS;
|
|
125476
|
+
this.writeImpl = options.writeImpl ?? ((p, contents) => writeFile7(p, contents));
|
|
125477
|
+
}
|
|
125478
|
+
get messagesPath() {
|
|
125479
|
+
return this.path;
|
|
125480
|
+
}
|
|
125481
|
+
get latest() {
|
|
125482
|
+
return this.pending;
|
|
125483
|
+
}
|
|
125484
|
+
setLatest(messages) {
|
|
125485
|
+
this.pending = messages;
|
|
125486
|
+
}
|
|
125487
|
+
get syntheticsPersisted() {
|
|
125488
|
+
return this.syntheticsWritten;
|
|
125489
|
+
}
|
|
125490
|
+
markSyntheticsPersisted() {
|
|
125491
|
+
this.syntheticsWritten = true;
|
|
125492
|
+
}
|
|
125493
|
+
schedulePersist() {
|
|
125494
|
+
if (this.persistTimer)
|
|
125495
|
+
return;
|
|
125496
|
+
this.persistTimer = setTimeout(() => {
|
|
125497
|
+
this.persistTimer = null;
|
|
125498
|
+
const toWrite = this.pending;
|
|
125499
|
+
if (!toWrite)
|
|
125500
|
+
return;
|
|
125501
|
+
this.enqueueWrite(toWrite).then(() => {
|
|
125502
|
+
if (this.pending === toWrite)
|
|
125503
|
+
this.pending = null;
|
|
125504
|
+
}).catch(() => {});
|
|
125505
|
+
}, this.intervalMs);
|
|
125506
|
+
}
|
|
125507
|
+
cancelTimer() {
|
|
125508
|
+
if (this.persistTimer) {
|
|
125509
|
+
clearTimeout(this.persistTimer);
|
|
125510
|
+
this.persistTimer = null;
|
|
125511
|
+
}
|
|
125512
|
+
}
|
|
125513
|
+
async enqueueWrite(messages) {
|
|
125514
|
+
const path = this.path;
|
|
125515
|
+
if (!path)
|
|
125516
|
+
return;
|
|
125517
|
+
const contents = JSON.stringify(messages);
|
|
125518
|
+
const write2 = this.tail.then(() => this.writeImpl(path, contents));
|
|
125519
|
+
this.tail = write2.catch(() => {});
|
|
125520
|
+
await write2;
|
|
125521
|
+
}
|
|
125522
|
+
async waitForPendingWrites() {
|
|
125523
|
+
let pending;
|
|
125524
|
+
do {
|
|
125525
|
+
pending = this.tail;
|
|
125526
|
+
await pending;
|
|
125527
|
+
} while (pending !== this.tail);
|
|
125528
|
+
}
|
|
125529
|
+
}
|
|
125530
|
+
|
|
125531
|
+
// src/core/agents/offSecAgent/streamDiagnostics.ts
|
|
125532
|
+
init_structured();
|
|
125533
|
+
init_lazyLogger();
|
|
125534
|
+
var STREAM_STALL_DEBUG = process.env.STREAM_STALL_DEBUG === "1" || process.env.STREAM_STALL_DEBUG === "true";
|
|
125535
|
+
var STREAM_STALL_TICK_MS = 15000;
|
|
125536
|
+
var STREAM_STALL_WARN_MS = 20000;
|
|
125537
|
+
var STREAM_GAP_RECOVERED_MS = 1e4;
|
|
125010
125538
|
var RESPONSE_DEBUG = process.env.RESPONSE_DEBUG === "1" || process.env.RESPONSE_DEBUG === "true";
|
|
125011
125539
|
var rlog = scopedLogger(() => createLogger("response-debug"));
|
|
125540
|
+
function responseArgBytes(input) {
|
|
125541
|
+
if (input == null)
|
|
125542
|
+
return 0;
|
|
125543
|
+
if (typeof input === "string")
|
|
125544
|
+
return input.length;
|
|
125545
|
+
try {
|
|
125546
|
+
return JSON.stringify(input).length;
|
|
125547
|
+
} catch {
|
|
125548
|
+
return -1;
|
|
125549
|
+
}
|
|
125550
|
+
}
|
|
125551
|
+
|
|
125552
|
+
class StreamDiagnostics {
|
|
125553
|
+
opts;
|
|
125554
|
+
stallEnabled;
|
|
125555
|
+
responseDebugEnabled;
|
|
125556
|
+
warn;
|
|
125557
|
+
responseArgChars = new Map;
|
|
125558
|
+
responseSawTerminal = new Map;
|
|
125559
|
+
lastChunkAt = Date.now();
|
|
125560
|
+
lastChunkType = "none";
|
|
125561
|
+
stallStepIndex = -1;
|
|
125562
|
+
stallTimer;
|
|
125563
|
+
constructor(options) {
|
|
125564
|
+
this.opts = options;
|
|
125565
|
+
this.stallEnabled = options.stallEnabled ?? STREAM_STALL_DEBUG;
|
|
125566
|
+
this.responseDebugEnabled = options.responseDebugEnabled ?? RESPONSE_DEBUG;
|
|
125567
|
+
this.warn = options.warn ?? ((message) => rlog.warn(message));
|
|
125568
|
+
}
|
|
125569
|
+
start() {
|
|
125570
|
+
if (!this.stallEnabled || this.stallTimer)
|
|
125571
|
+
return;
|
|
125572
|
+
const label = this.opts.sessionId;
|
|
125573
|
+
const sid = this.opts.subagentId;
|
|
125574
|
+
this.stallTimer = setInterval(() => {
|
|
125575
|
+
const gap = Date.now() - this.lastChunkAt;
|
|
125576
|
+
if (gap > STREAM_STALL_WARN_MS) {
|
|
125577
|
+
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()}`);
|
|
125578
|
+
}
|
|
125579
|
+
}, STREAM_STALL_TICK_MS);
|
|
125580
|
+
}
|
|
125581
|
+
observeChunk(chunk) {
|
|
125582
|
+
if (this.stallEnabled) {
|
|
125583
|
+
const now = Date.now();
|
|
125584
|
+
const gap = now - this.lastChunkAt;
|
|
125585
|
+
this.lastChunkAt = now;
|
|
125586
|
+
this.lastChunkType = chunk.type;
|
|
125587
|
+
if (chunk.type === "start-step")
|
|
125588
|
+
this.stallStepIndex++;
|
|
125589
|
+
if (gap > STREAM_GAP_RECOVERED_MS) {
|
|
125590
|
+
this.warn(`[stream-gap] recovered after ${Math.round(gap / 1000)}s ` + `session=${this.opts.sessionId} chunkType=${chunk.type}`);
|
|
125591
|
+
}
|
|
125592
|
+
}
|
|
125593
|
+
if (this.responseDebugEnabled) {
|
|
125594
|
+
this.traceResponseTool(chunk);
|
|
125595
|
+
}
|
|
125596
|
+
}
|
|
125597
|
+
logSurfacedToolError(info) {
|
|
125598
|
+
if (!this.responseDebugEnabled)
|
|
125599
|
+
return;
|
|
125600
|
+
if (info.toolName !== this.opts.responseToolName)
|
|
125601
|
+
return;
|
|
125602
|
+
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)}`);
|
|
125603
|
+
}
|
|
125604
|
+
logClosingInFlightTool(info) {
|
|
125605
|
+
if (!this.responseDebugEnabled)
|
|
125606
|
+
return;
|
|
125607
|
+
if (info.toolName !== this.opts.responseToolName)
|
|
125608
|
+
return;
|
|
125609
|
+
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()}`);
|
|
125610
|
+
}
|
|
125611
|
+
stop() {
|
|
125612
|
+
if (this.stallTimer)
|
|
125613
|
+
clearInterval(this.stallTimer);
|
|
125614
|
+
this.stallTimer = undefined;
|
|
125615
|
+
}
|
|
125616
|
+
traceResponseTool(chunk) {
|
|
125617
|
+
const idForChunk = chunk.toolCallId ?? chunk.id;
|
|
125618
|
+
const nameForChunk = chunk.toolName ?? (idForChunk ? this.opts.inFlightTools().get(idForChunk) : undefined);
|
|
125619
|
+
if (nameForChunk !== this.opts.responseToolName || !idForChunk) {
|
|
125620
|
+
if (chunk.type === "finish-step") {
|
|
125621
|
+
const responseInFlight = [...this.opts.inFlightTools().entries()].filter(([, n7]) => n7 === this.opts.responseToolName).map(([id]) => id).join(",");
|
|
125622
|
+
if (responseInFlight) {
|
|
125623
|
+
this.warn(`[response-debug] finish-step finishReason=${chunk.finishReason} ` + `responseInFlight=${responseInFlight} ` + `responseToolFired=${this.opts.responseToolFired()}`);
|
|
125624
|
+
}
|
|
125625
|
+
}
|
|
125626
|
+
return;
|
|
125627
|
+
}
|
|
125628
|
+
switch (chunk.type) {
|
|
125629
|
+
case "tool-input-start":
|
|
125630
|
+
this.responseArgChars.set(idForChunk, 0);
|
|
125631
|
+
this.warn(`[response-debug] tool-input-start id=${idForChunk} session=${this.opts.subagentId ?? this.opts.sessionId}`);
|
|
125632
|
+
break;
|
|
125633
|
+
case "tool-input-delta":
|
|
125634
|
+
this.responseArgChars.set(idForChunk, (this.responseArgChars.get(idForChunk) ?? 0) + (chunk.delta?.length ?? 0));
|
|
125635
|
+
break;
|
|
125636
|
+
case "tool-input-end":
|
|
125637
|
+
this.warn(`[response-debug] tool-input-end id=${idForChunk} argChars=${this.responseArgChars.get(idForChunk) ?? 0}`);
|
|
125638
|
+
break;
|
|
125639
|
+
case "tool-call": {
|
|
125640
|
+
this.responseSawTerminal.set(idForChunk, "tool-call");
|
|
125641
|
+
const inputBytes = responseArgBytes(chunk.input ?? chunk.args);
|
|
125642
|
+
this.warn(`[response-debug] tool-call id=${idForChunk} streamedArgChars=${this.responseArgChars.get(idForChunk) ?? 0} parsedInputBytes=${inputBytes} invalid=${chunk.invalid === true}`);
|
|
125643
|
+
break;
|
|
125644
|
+
}
|
|
125645
|
+
case "tool-error": {
|
|
125646
|
+
this.responseSawTerminal.set(idForChunk, "tool-error");
|
|
125647
|
+
const errMsg = chunk.error instanceof Error ? chunk.error.message : typeof chunk.error === "string" ? chunk.error : JSON.stringify(chunk.error)?.slice(0, 300);
|
|
125648
|
+
this.warn(`[response-debug] tool-error id=${idForChunk} streamedArgChars=${this.responseArgChars.get(idForChunk) ?? 0} stillInFlight=${this.opts.inFlightTools().has(idForChunk)} error=${errMsg}`);
|
|
125649
|
+
break;
|
|
125650
|
+
}
|
|
125651
|
+
case "tool-result":
|
|
125652
|
+
this.responseSawTerminal.set(idForChunk, "tool-result");
|
|
125653
|
+
this.warn(`[response-debug] tool-result id=${idForChunk} streamedArgChars=${this.responseArgChars.get(idForChunk) ?? 0}`);
|
|
125654
|
+
break;
|
|
125655
|
+
}
|
|
125656
|
+
}
|
|
125657
|
+
}
|
|
125658
|
+
|
|
125659
|
+
// src/core/agents/offSecAgent/toolLifecycle.ts
|
|
125660
|
+
class ToolLifecycleTracker {
|
|
125661
|
+
inFlight = new Map;
|
|
125662
|
+
completed = [];
|
|
125663
|
+
streamedArgs = new Map;
|
|
125664
|
+
errors = new Map;
|
|
125665
|
+
observePart(chunk) {
|
|
125666
|
+
switch (chunk.type) {
|
|
125667
|
+
case "tool-input-start":
|
|
125668
|
+
this.inFlight.set(chunk.id, chunk.toolName);
|
|
125669
|
+
this.streamedArgs.set(chunk.id, "");
|
|
125670
|
+
break;
|
|
125671
|
+
case "tool-input-delta":
|
|
125672
|
+
this.streamedArgs.set(chunk.id, (this.streamedArgs.get(chunk.id) ?? "") + (chunk.delta ?? ""));
|
|
125673
|
+
break;
|
|
125674
|
+
case "tool-call":
|
|
125675
|
+
this.inFlight.set(chunk.toolCallId, chunk.toolName);
|
|
125676
|
+
break;
|
|
125677
|
+
case "tool-error": {
|
|
125678
|
+
const toolCallId = chunk.toolCallId;
|
|
125679
|
+
this.inFlight.delete(toolCallId);
|
|
125680
|
+
const errMsg = chunk.error instanceof Error ? chunk.error.message : typeof chunk.error === "string" ? chunk.error : (() => {
|
|
125681
|
+
try {
|
|
125682
|
+
return JSON.stringify(chunk.error);
|
|
125683
|
+
} catch {
|
|
125684
|
+
return String(chunk.error);
|
|
125685
|
+
}
|
|
125686
|
+
})();
|
|
125687
|
+
const partialArgs = chunk.input !== undefined && chunk.input !== null && responseArgBytes(chunk.input) > 2 ? chunk.input : this.streamedArgs.get(toolCallId) ?? "";
|
|
125688
|
+
this.errors.set(toolCallId, {
|
|
125689
|
+
message: errMsg,
|
|
125690
|
+
input: partialArgs,
|
|
125691
|
+
toolName: chunk.toolName
|
|
125692
|
+
});
|
|
125693
|
+
break;
|
|
125694
|
+
}
|
|
125695
|
+
case "tool-result":
|
|
125696
|
+
this.inFlight.delete(chunk.toolCallId);
|
|
125697
|
+
this.completed.push({
|
|
125698
|
+
type: "tool-result",
|
|
125699
|
+
toolCallId: chunk.toolCallId,
|
|
125700
|
+
toolName: chunk.toolName,
|
|
125701
|
+
output: chunk.result ?? chunk.output
|
|
125702
|
+
});
|
|
125703
|
+
break;
|
|
125704
|
+
}
|
|
125705
|
+
}
|
|
125706
|
+
onStepPersisted() {
|
|
125707
|
+
this.completed.length = 0;
|
|
125708
|
+
}
|
|
125709
|
+
flushToolErrorsToResults() {
|
|
125710
|
+
const flushed = [];
|
|
125711
|
+
for (const [toolCallId, info] of this.errors) {
|
|
125712
|
+
this.completed.push({
|
|
125713
|
+
type: "tool-result",
|
|
125714
|
+
toolCallId,
|
|
125715
|
+
toolName: info.toolName,
|
|
125716
|
+
output: {
|
|
125717
|
+
type: "error-text",
|
|
125718
|
+
value: `Tool call failed: ${info.message}`
|
|
125719
|
+
}
|
|
125720
|
+
});
|
|
125721
|
+
flushed.push([toolCallId, info]);
|
|
125722
|
+
}
|
|
125723
|
+
this.errors.clear();
|
|
125724
|
+
return flushed;
|
|
125725
|
+
}
|
|
125726
|
+
clearToolErrors() {
|
|
125727
|
+
this.errors.clear();
|
|
125728
|
+
}
|
|
125729
|
+
clearInFlight() {
|
|
125730
|
+
this.inFlight.clear();
|
|
125731
|
+
}
|
|
125732
|
+
hasUnpersistedState() {
|
|
125733
|
+
return this.inFlight.size > 0 || this.completed.length > 0;
|
|
125734
|
+
}
|
|
125735
|
+
get inFlightTools() {
|
|
125736
|
+
return this.inFlight;
|
|
125737
|
+
}
|
|
125738
|
+
get toolErrors() {
|
|
125739
|
+
return this.errors;
|
|
125740
|
+
}
|
|
125741
|
+
get completedResults() {
|
|
125742
|
+
return this.completed;
|
|
125743
|
+
}
|
|
125744
|
+
get streamedArgText() {
|
|
125745
|
+
return this.streamedArgs;
|
|
125746
|
+
}
|
|
125747
|
+
snapshot() {
|
|
125748
|
+
return {
|
|
125749
|
+
inFlightTools: new Map(this.inFlight),
|
|
125750
|
+
completedResults: this.completed.map((r) => ({ ...r })),
|
|
125751
|
+
streamedArgText: new Map(this.streamedArgs),
|
|
125752
|
+
toolErrors: new Map(this.errors)
|
|
125753
|
+
};
|
|
125754
|
+
}
|
|
125755
|
+
}
|
|
125756
|
+
|
|
125757
|
+
// src/core/agents/offSecAgent/offensiveSecurityAgent.ts
|
|
125758
|
+
var log13 = scopedLogger(() => createLogger("approval-gate"));
|
|
125759
|
+
var RESPONSE_DEBUG2 = process.env.RESPONSE_DEBUG === "1" || process.env.RESPONSE_DEBUG === "true";
|
|
125760
|
+
var rlog2 = scopedLogger(() => createLogger("response-debug"));
|
|
125012
125761
|
var WORKSPACE_TOOL_NAME_SET = new Set(WORKSPACE_TOOL_NAMES);
|
|
125013
125762
|
var WORKSPACE_WRITE_TOOL_NAME_SET = new Set(WORKSPACE_WRITE_TOOL_NAMES);
|
|
125014
125763
|
var WORKSPACE_TARGET_RE = /\b(?:console|workspace)\b/i;
|
|
@@ -125058,21 +125807,6 @@ function filterWorkspaceToolsForRun(activeTools, prompt, hasInteractiveApprovalG
|
|
|
125058
125807
|
return true;
|
|
125059
125808
|
});
|
|
125060
125809
|
}
|
|
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
125810
|
|
|
125077
125811
|
class OffensiveSecurityAgent {
|
|
125078
125812
|
_streamResult = null;
|
|
@@ -125091,18 +125825,19 @@ class OffensiveSecurityAgent {
|
|
|
125091
125825
|
drained = Promise.resolve();
|
|
125092
125826
|
subagentId;
|
|
125093
125827
|
subagentName;
|
|
125828
|
+
agentMode;
|
|
125094
125829
|
currentMessageId = null;
|
|
125095
125830
|
persistentShell;
|
|
125096
125831
|
browserSession;
|
|
125097
125832
|
ownsBrowserSession;
|
|
125098
125833
|
browserDisconnected = false;
|
|
125834
|
+
shellDisposed = false;
|
|
125099
125835
|
abortSignal;
|
|
125100
125836
|
userPrompt;
|
|
125101
125837
|
_session;
|
|
125102
|
-
|
|
125838
|
+
writer;
|
|
125839
|
+
finalizeInterruptedStep;
|
|
125103
125840
|
messagesPath = null;
|
|
125104
|
-
cancelPersistTimer = null;
|
|
125105
|
-
syntheticsPersisted = false;
|
|
125106
125841
|
static async create(input) {
|
|
125107
125842
|
let session = input.session;
|
|
125108
125843
|
if (!session) {
|
|
@@ -125127,6 +125862,7 @@ class OffensiveSecurityAgent {
|
|
|
125127
125862
|
this._session = input.session;
|
|
125128
125863
|
this.subagentId = input.subagentId;
|
|
125129
125864
|
this.subagentName = input.subagentName;
|
|
125865
|
+
this.agentMode = input.mode ?? "default";
|
|
125130
125866
|
this.abortSignal = input.abortSignal;
|
|
125131
125867
|
this.userPrompt = input.prompt;
|
|
125132
125868
|
this.eventBus = input.eventBus ?? new AgentEventBus;
|
|
@@ -125175,10 +125911,13 @@ class OffensiveSecurityAgent {
|
|
|
125175
125911
|
agentCwd,
|
|
125176
125912
|
target: input.target,
|
|
125177
125913
|
grpc: input.grpc,
|
|
125914
|
+
systemScope: input.systemScope,
|
|
125178
125915
|
abortSignal: input.abortSignal,
|
|
125179
125916
|
model: input.model,
|
|
125180
125917
|
authConfig: input.authConfig,
|
|
125181
125918
|
eventBus: this.eventBus,
|
|
125919
|
+
onStepFinish: input.forwardUsageCallbacksToSpawnedAgents ? input.onStepFinish : undefined,
|
|
125920
|
+
onCacheMetrics: input.forwardUsageCallbacksToSpawnedAgents ? input.onCacheMetrics : undefined,
|
|
125182
125921
|
sandbox: input.sandbox,
|
|
125183
125922
|
findingsRegistry: input.findingsRegistry,
|
|
125184
125923
|
attackSurfaceRegistry: input.attackSurfaceRegistry,
|
|
@@ -125210,8 +125949,8 @@ class OffensiveSecurityAgent {
|
|
|
125210
125949
|
...tools,
|
|
125211
125950
|
[RESPONSE_TOOL_NAME]: createResponseTool(input.responseSchema, (result) => {
|
|
125212
125951
|
this._responseToolFired = true;
|
|
125213
|
-
if (
|
|
125214
|
-
|
|
125952
|
+
if (RESPONSE_DEBUG2) {
|
|
125953
|
+
rlog2.warn(`[response-debug] response tool EXECUTED (captured) session=${this.busSessionId} ` + `resultBytes=${responseArgBytes(result)} — happy path`);
|
|
125215
125954
|
}
|
|
125216
125955
|
const customResolve = input.resolveResult;
|
|
125217
125956
|
if (customResolve) {
|
|
@@ -125259,7 +125998,11 @@ class OffensiveSecurityAgent {
|
|
|
125259
125998
|
const hasEmail = (input.session.config?.emailIntegration?.inboxes?.length ?? 0) > 0;
|
|
125260
125999
|
const hasSmtp = !!input.session.config?.smtpConfig;
|
|
125261
126000
|
const emailToolSet = new Set(EMAIL_TOOL_NAMES);
|
|
126001
|
+
const smsToolSet = new Set(SMS_TOOL_NAMES);
|
|
126002
|
+
const hasSms = sessionHasSmsPasswordless(input.session);
|
|
125262
126003
|
let activeTools = input.activeTools.filter((t) => {
|
|
126004
|
+
if (smsToolSet.has(t))
|
|
126005
|
+
return hasSms;
|
|
125263
126006
|
if (!emailToolSet.has(t))
|
|
125264
126007
|
return true;
|
|
125265
126008
|
if (t === SEND_EMAIL_TOOL_NAME)
|
|
@@ -125274,6 +126017,8 @@ class OffensiveSecurityAgent {
|
|
|
125274
126017
|
activeTools = Object.keys(tools).filter((t) => {
|
|
125275
126018
|
if (excluded.has(t))
|
|
125276
126019
|
return false;
|
|
126020
|
+
if (smsToolSet.has(t))
|
|
126021
|
+
return hasSms;
|
|
125277
126022
|
if (!emailToolSet.has(t))
|
|
125278
126023
|
return true;
|
|
125279
126024
|
if (t === SEND_EMAIL_TOOL_NAME)
|
|
@@ -125282,11 +126027,10 @@ class OffensiveSecurityAgent {
|
|
|
125282
126027
|
});
|
|
125283
126028
|
}
|
|
125284
126029
|
activeTools = filterWorkspaceToolsForRun(activeTools, input.prompt, input.approvalGate !== undefined);
|
|
125285
|
-
if (!
|
|
126030
|
+
if (!existsSync19(messagesDir)) {
|
|
125286
126031
|
mkdirSync14(messagesDir, { recursive: true });
|
|
125287
126032
|
}
|
|
125288
126033
|
this.messagesPath = join27(messagesDir, "messages.json");
|
|
125289
|
-
const messagesPath = this.messagesPath;
|
|
125290
126034
|
const initialMessagesRef = {
|
|
125291
126035
|
current: input.messages ? [...input.messages] : [
|
|
125292
126036
|
{
|
|
@@ -125295,26 +126039,17 @@ class OffensiveSecurityAgent {
|
|
|
125295
126039
|
}
|
|
125296
126040
|
]
|
|
125297
126041
|
};
|
|
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
|
-
};
|
|
126042
|
+
this.writer = new AgentMessageWriter({ messagesPath: this.messagesPath });
|
|
126043
|
+
this.finalizeInterruptedStep = createInterruptedStepFinalizer({
|
|
126044
|
+
eventBus: this.eventBus,
|
|
126045
|
+
sessionId: this.busSessionId,
|
|
126046
|
+
subagentId: this.subagentId,
|
|
126047
|
+
writer: this.writer,
|
|
126048
|
+
responseToolName: RESPONSE_TOOL_NAME,
|
|
126049
|
+
responseToolFired: () => this._responseToolFired,
|
|
126050
|
+
...RESPONSE_DEBUG2 ? { debugLog: (message) => rlog2.warn(message) } : {}
|
|
126051
|
+
});
|
|
126052
|
+
const schedulePersist = () => this.writer.schedulePersist();
|
|
125318
126053
|
const baseSystemPrompt = input.system ?? detectOSAndEnhancePrompt(buildBaseSystemPrompt({
|
|
125319
126054
|
sandboxMode: agentCwd === input.session.rootPath
|
|
125320
126055
|
}));
|
|
@@ -125339,10 +126074,10 @@ class OffensiveSecurityAgent {
|
|
|
125339
126074
|
sessionPath: messagesDir,
|
|
125340
126075
|
sessionId: this.busSessionId,
|
|
125341
126076
|
onStepFinish: async (event) => {
|
|
125342
|
-
this.
|
|
126077
|
+
this.writer.setLatest([
|
|
125343
126078
|
...initialMessagesRef.current,
|
|
125344
126079
|
...event.response.messages
|
|
125345
|
-
];
|
|
126080
|
+
]);
|
|
125346
126081
|
schedulePersist();
|
|
125347
126082
|
traceWriter.recordStep(event.response.messages, {
|
|
125348
126083
|
inputTokens: event.usage.inputTokens ?? 0,
|
|
@@ -125364,16 +126099,14 @@ class OffensiveSecurityAgent {
|
|
|
125364
126099
|
traceWriter.markSummarized();
|
|
125365
126100
|
},
|
|
125366
126101
|
onFinish: async (event) => {
|
|
125367
|
-
|
|
125368
|
-
|
|
125369
|
-
|
|
125370
|
-
}
|
|
125371
|
-
if (!this.syntheticsPersisted) {
|
|
125372
|
-
const finalMessages = this.latestMessages ?? [
|
|
126102
|
+
this.writer.cancelTimer();
|
|
126103
|
+
if (!this.writer.syntheticsPersisted) {
|
|
126104
|
+
const finalMessages = this.writer.latest ?? [
|
|
125373
126105
|
...initialMessagesRef.current,
|
|
125374
126106
|
...event.response.messages
|
|
125375
126107
|
];
|
|
125376
|
-
|
|
126108
|
+
this.writer.setLatest(finalMessages);
|
|
126109
|
+
await this.writer.enqueueWrite(finalMessages).catch(() => {});
|
|
125377
126110
|
}
|
|
125378
126111
|
await input.onFinish?.(event);
|
|
125379
126112
|
},
|
|
@@ -125425,205 +126158,34 @@ class OffensiveSecurityAgent {
|
|
|
125425
126158
|
return p;
|
|
125426
126159
|
}
|
|
125427
126160
|
};
|
|
125428
|
-
const
|
|
125429
|
-
const completedResults = [];
|
|
126161
|
+
const tracker = new ToolLifecycleTracker;
|
|
125430
126162
|
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
|
-
}
|
|
126163
|
+
const diagnostics = new StreamDiagnostics({
|
|
126164
|
+
sessionId: this._session.id,
|
|
126165
|
+
subagentId: sid,
|
|
126166
|
+
inFlightTools: () => tracker.inFlightTools,
|
|
126167
|
+
responseToolFired: () => this._responseToolFired,
|
|
126168
|
+
responseToolName: RESPONSE_TOOL_NAME
|
|
126169
|
+
});
|
|
126170
|
+
diagnostics.start();
|
|
125448
126171
|
try {
|
|
125449
126172
|
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
|
-
}
|
|
126173
|
+
diagnostics.observeChunk(chunk);
|
|
126174
|
+
this.applyStreamPart(chunk, { ids, tracker, diagnostics });
|
|
125590
126175
|
bus.emitStreamPart(chunk, ids);
|
|
125591
126176
|
}
|
|
125592
126177
|
} catch (err) {
|
|
125593
126178
|
streamError = err;
|
|
125594
126179
|
} 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 {}
|
|
126180
|
+
const finalizeError = await this.finalizeRun({
|
|
126181
|
+
tracker,
|
|
126182
|
+
diagnostics,
|
|
126183
|
+
ids,
|
|
126184
|
+
streamError
|
|
126185
|
+
});
|
|
126186
|
+
if (streamError === null && finalizeError !== null) {
|
|
126187
|
+
streamError = finalizeError;
|
|
125625
126188
|
}
|
|
125626
|
-
await this.disconnectOwnedBrowser();
|
|
125627
126189
|
}
|
|
125628
126190
|
if (streamError) {
|
|
125629
126191
|
throw streamError;
|
|
@@ -125639,22 +126201,32 @@ class OffensiveSecurityAgent {
|
|
|
125639
126201
|
}
|
|
125640
126202
|
return;
|
|
125641
126203
|
};
|
|
125642
|
-
const
|
|
125643
|
-
const
|
|
125644
|
-
|
|
125645
|
-
|
|
125646
|
-
|
|
126204
|
+
const isSubagent = Boolean(sid);
|
|
126205
|
+
const spanLabel = isSubagent ? this.subagentName ?? sid ?? "subagent" : this.agentMode;
|
|
126206
|
+
const runId = isSubagent ? undefined : newRunId();
|
|
126207
|
+
const runSpanAttributes = {
|
|
126208
|
+
"gen_ai.operation.name": "invoke_agent",
|
|
126209
|
+
"gen_ai.agent.name": spanLabel,
|
|
126210
|
+
"gen_ai.conversation.id": this.busSessionId,
|
|
126211
|
+
"pensar.session.id": this.busSessionId,
|
|
126212
|
+
...isSubagent ? {} : {
|
|
126213
|
+
"pensar.run.id": runId,
|
|
126214
|
+
"pensar.agent.mode": this.agentMode
|
|
125647
126215
|
}
|
|
125648
|
-
}
|
|
126216
|
+
};
|
|
126217
|
+
const runInSpan = () => getApexTracer().startActiveSpan(`invoke_agent ${spanLabel}`, { attributes: runSpanAttributes }, async (span) => {
|
|
125649
126218
|
try {
|
|
125650
126219
|
return await runConsume();
|
|
125651
126220
|
} catch (err) {
|
|
125652
126221
|
span.recordException(err);
|
|
126222
|
+
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
126223
|
+
span.setAttribute("error.type", err instanceof Error ? err.name : "Error");
|
|
125653
126224
|
throw err;
|
|
125654
126225
|
} finally {
|
|
125655
126226
|
span.end();
|
|
125656
126227
|
}
|
|
125657
|
-
})
|
|
126228
|
+
});
|
|
126229
|
+
const drain = !isSubagent ? runInSpan() : withSubagentSessionBaggage(sid, runInSpan);
|
|
125658
126230
|
let rejectDrain;
|
|
125659
126231
|
this._drainRejection = new Promise((_2, reject) => {
|
|
125660
126232
|
rejectDrain = reject;
|
|
@@ -125678,6 +126250,141 @@ class OffensiveSecurityAgent {
|
|
|
125678
126250
|
await this.disconnectOwnedBrowser();
|
|
125679
126251
|
return result;
|
|
125680
126252
|
}
|
|
126253
|
+
applyStreamPart(chunk, ctx) {
|
|
126254
|
+
const { ids, tracker, diagnostics } = ctx;
|
|
126255
|
+
const sid = this.subagentId;
|
|
126256
|
+
const bus = this.eventBus;
|
|
126257
|
+
switch (chunk.type) {
|
|
126258
|
+
case "start-step":
|
|
126259
|
+
ids.messageId = newMessageId();
|
|
126260
|
+
this.currentMessageId = ids.messageId;
|
|
126261
|
+
ids.textPartId = undefined;
|
|
126262
|
+
break;
|
|
126263
|
+
case "text-start":
|
|
126264
|
+
ids.textPartId = newPartId();
|
|
126265
|
+
break;
|
|
126266
|
+
case "text-end":
|
|
126267
|
+
ids.textPartId = undefined;
|
|
126268
|
+
break;
|
|
126269
|
+
case "finish-step": {
|
|
126270
|
+
tracker.onStepPersisted();
|
|
126271
|
+
const finishReason = chunk.finishReason;
|
|
126272
|
+
const truncated = finishReason === "length";
|
|
126273
|
+
for (const [toolCallId, info] of tracker.toolErrors) {
|
|
126274
|
+
diagnostics.logSurfacedToolError({
|
|
126275
|
+
toolCallId,
|
|
126276
|
+
toolName: info.toolName,
|
|
126277
|
+
message: info.message,
|
|
126278
|
+
streamedArgChars: (tracker.streamedArgText.get(toolCallId) ?? "").length,
|
|
126279
|
+
finishReason,
|
|
126280
|
+
truncated
|
|
126281
|
+
});
|
|
126282
|
+
bus.emit("tool-result", {
|
|
126283
|
+
toolCallId,
|
|
126284
|
+
toolName: info.toolName,
|
|
126285
|
+
result: {
|
|
126286
|
+
type: "error-text",
|
|
126287
|
+
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}`
|
|
126288
|
+
},
|
|
126289
|
+
sessionId: this.busSessionId,
|
|
126290
|
+
subagentId: sid,
|
|
126291
|
+
partId: ids.toolPartId?.(toolCallId),
|
|
126292
|
+
messageId: ids.messageId
|
|
126293
|
+
});
|
|
126294
|
+
}
|
|
126295
|
+
tracker.clearToolErrors();
|
|
126296
|
+
for (const [toolCallId, toolName] of tracker.inFlightTools) {
|
|
126297
|
+
diagnostics.logClosingInFlightTool({
|
|
126298
|
+
toolCallId,
|
|
126299
|
+
toolName,
|
|
126300
|
+
finishReason,
|
|
126301
|
+
truncated
|
|
126302
|
+
});
|
|
126303
|
+
const result = toolName === RESPONSE_TOOL_NAME && this._responseToolFired ? { type: "text", value: "Response submitted." } : {
|
|
126304
|
+
type: "error-text",
|
|
126305
|
+
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"
|
|
126306
|
+
};
|
|
126307
|
+
bus.emit("tool-result", {
|
|
126308
|
+
toolCallId,
|
|
126309
|
+
toolName,
|
|
126310
|
+
result,
|
|
126311
|
+
sessionId: this.busSessionId,
|
|
126312
|
+
subagentId: sid,
|
|
126313
|
+
partId: ids.toolPartId?.(toolCallId),
|
|
126314
|
+
messageId: ids.messageId
|
|
126315
|
+
});
|
|
126316
|
+
}
|
|
126317
|
+
tracker.clearInFlight();
|
|
126318
|
+
break;
|
|
126319
|
+
}
|
|
126320
|
+
default:
|
|
126321
|
+
tracker.observePart(chunk);
|
|
126322
|
+
}
|
|
126323
|
+
}
|
|
126324
|
+
async finalizeRun(input) {
|
|
126325
|
+
const { tracker, diagnostics, ids, streamError } = input;
|
|
126326
|
+
const sid = this.subagentId;
|
|
126327
|
+
const bus = this.eventBus;
|
|
126328
|
+
diagnostics.stop();
|
|
126329
|
+
let finalizationError;
|
|
126330
|
+
let hasFinalizationError = false;
|
|
126331
|
+
const recordFinalizationError = (error) => {
|
|
126332
|
+
if (hasFinalizationError)
|
|
126333
|
+
return;
|
|
126334
|
+
finalizationError = error;
|
|
126335
|
+
hasFinalizationError = true;
|
|
126336
|
+
};
|
|
126337
|
+
try {
|
|
126338
|
+
try {
|
|
126339
|
+
this.disposeOwnedShell();
|
|
126340
|
+
} catch (error) {
|
|
126341
|
+
recordFinalizationError(error);
|
|
126342
|
+
}
|
|
126343
|
+
for (const [toolCallId, info] of tracker.flushToolErrorsToResults()) {
|
|
126344
|
+
const result = {
|
|
126345
|
+
type: "error-text",
|
|
126346
|
+
value: `Tool call failed: ${info.message}`
|
|
126347
|
+
};
|
|
126348
|
+
try {
|
|
126349
|
+
bus.emit("tool-result", {
|
|
126350
|
+
toolCallId,
|
|
126351
|
+
toolName: info.toolName,
|
|
126352
|
+
result,
|
|
126353
|
+
sessionId: this.busSessionId,
|
|
126354
|
+
subagentId: sid,
|
|
126355
|
+
partId: ids.toolPartId?.(toolCallId),
|
|
126356
|
+
messageId: ids.messageId
|
|
126357
|
+
});
|
|
126358
|
+
} catch (error) {
|
|
126359
|
+
recordFinalizationError(error);
|
|
126360
|
+
}
|
|
126361
|
+
}
|
|
126362
|
+
if (tracker.hasUnpersistedState()) {
|
|
126363
|
+
const reason = this.abortSignal?.aborted ? "Agent aborted by user" : streamError instanceof Error && streamError.message ? streamError.message : "Stream terminated unexpectedly";
|
|
126364
|
+
try {
|
|
126365
|
+
await this.finalizeInterruptedStep({
|
|
126366
|
+
snapshot: tracker.snapshot(),
|
|
126367
|
+
reason,
|
|
126368
|
+
partIdFor: ids.toolPartId,
|
|
126369
|
+
messageId: ids.messageId
|
|
126370
|
+
});
|
|
126371
|
+
} catch (error) {
|
|
126372
|
+
recordFinalizationError(error);
|
|
126373
|
+
}
|
|
126374
|
+
}
|
|
126375
|
+
} catch (error) {
|
|
126376
|
+
recordFinalizationError(error);
|
|
126377
|
+
} finally {
|
|
126378
|
+
await this.disconnectOwnedBrowser();
|
|
126379
|
+
}
|
|
126380
|
+
return hasFinalizationError ? finalizationError : null;
|
|
126381
|
+
}
|
|
126382
|
+
disposeOwnedShell() {
|
|
126383
|
+
if (this.shellDisposed)
|
|
126384
|
+
return;
|
|
126385
|
+
this.shellDisposed = true;
|
|
126386
|
+
this.persistentShell?.dispose();
|
|
126387
|
+
}
|
|
125681
126388
|
async disconnectOwnedBrowser() {
|
|
125682
126389
|
if (this.browserDisconnected)
|
|
125683
126390
|
return;
|
|
@@ -125693,102 +126400,6 @@ class OffensiveSecurityAgent {
|
|
|
125693
126400
|
get response() {
|
|
125694
126401
|
return this.streamResult.response;
|
|
125695
126402
|
}
|
|
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
126403
|
}
|
|
125793
126404
|
var AGENT_PAUSE_TOOLS = new Set([ASK_USER_QUESTIONS_TOOL_NAME]);
|
|
125794
126405
|
function wrapToolsWithApprovalGate(tools, gate, exemptToolNames) {
|
|
@@ -125828,4 +126439,4 @@ function wrapToolsWithApprovalGate(tools, gate, exemptToolNames) {
|
|
|
125828
126439
|
return wrapped;
|
|
125829
126440
|
}
|
|
125830
126441
|
|
|
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 };
|
|
126442
|
+
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 };
|