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