@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.
Files changed (68) hide show
  1. package/build/agent-20hb6mg7.js +20 -0
  2. package/build/{agent-5ejt5vpz.js → agent-71sn1cjn.js} +9 -8
  3. package/build/{agent-nhs1w5w0.js → agent-xnrz4bhp.js} +11 -10
  4. package/build/{apps-17wvz1d7.js → apps-ghf7kp1s.js} +72 -31
  5. package/build/{auth-z3h9859n.js → auth-p1nrv7re.js} +25 -20
  6. package/build/authentication-m1vj2f0s.js +20 -0
  7. package/build/blackboxAgent-hjfzgk93.js +20 -0
  8. package/build/blackboxPentest-9snp9gvp.js +70 -0
  9. package/build/{cli-0n4r54hq.js → cli-08fcc6d8.js} +1 -1
  10. package/build/{cli-gq40s5b3.js → cli-14j00zfh.js} +5 -3
  11. package/build/{cli-vnynf0js.js → cli-3bmqdcfh.js} +10 -4
  12. package/build/{cli-mavved45.js → cli-3ew5fs3f.js} +46 -25
  13. package/build/{cli-xshasbwe.js → cli-4mgj070h.js} +30 -4
  14. package/build/{cli-repbyhkk.js → cli-4vwnsyep.js} +1141 -525
  15. package/build/cli-53rm0rrz.js +15 -0
  16. package/build/cli-68260ckj.js +12136 -0
  17. package/build/cli-7q3ae3ft.js +6 -0
  18. package/build/{cli-5k33webc.js → cli-7sqb16dd.js} +45 -43
  19. package/build/{cli-9rhzhgx2.js → cli-8pk8znhw.js} +1 -1
  20. package/build/cli-9pbk8m32.js +32 -0
  21. package/build/{cli-72cvcqhg.js → cli-9ya3yktn.js} +1 -1
  22. package/build/{cli-vq52kp7j.js → cli-a8n64cef.js} +23 -5
  23. package/build/{cli-qqt4gj1w.js → cli-a9vq54sx.js} +5 -3
  24. package/build/{cli-swpbx60z.js → cli-avmhkjtv.js} +1 -1481
  25. package/build/{cli-tkc598ey.js → cli-f47dgye3.js} +411 -280
  26. package/build/{cli-k8kc47pq.js → cli-fw7sp0fp.js} +3 -3
  27. package/build/{cli-32z0017y.js → cli-g3cb8pj5.js} +2 -2
  28. package/build/{cli-tznv8pf1.js → cli-gbch9xmy.js} +1 -1
  29. package/build/cli-knd276ed.js +1485 -0
  30. package/build/{cli-2cbwdk78.js → cli-t7rhyqx5.js} +1 -1
  31. package/build/{cli-b1adytsy.js → cli-yge44bmk.js} +28 -5
  32. package/build/cli.js +641 -95
  33. package/build/{config-f1mj4nhd.js → config-cqw98n5y.js} +18 -15
  34. package/build/{doctor-ekneewa3.js → doctor-vzh1wmfa.js} +8 -7
  35. package/build/{fastStrike-8zka43xs.js → fastStrike-f441e9nr.js} +13 -10
  36. package/build/{fixes-b89s5haw.js → fixes-xxz52cf2.js} +25 -20
  37. package/build/getMachineId-bsd-xj3bn2fv.js +36 -0
  38. package/build/getMachineId-darwin-07jzjcx6.js +36 -0
  39. package/build/getMachineId-linux-ahngynxd.js +29 -0
  40. package/build/getMachineId-unsupported-vy43b44z.js +19 -0
  41. package/build/getMachineId-win-8x66cynz.js +38 -0
  42. package/build/{index-ghwf5z3v.js → index-23jj0234.js} +3 -3
  43. package/build/{index-6d22pyxt.js → index-3gavwzay.js} +1756 -1213
  44. package/build/{index-4ad3sdwk.js → index-4v5jc2td.js} +4 -4
  45. package/build/{index-mtq7kmxz.js → index-5wh7gq37.js} +4 -2
  46. package/build/{index-sf16jm0m.js → index-e7kq5rrd.js} +9 -7
  47. package/build/{index-rbzhk712.js → index-fxx38nc9.js} +11 -10
  48. package/build/{index-hqjdg6fg.js → index-j3dc7dks.js} +17 -9
  49. package/build/{index-y5w6n3tb.js → index-yc1dnj3n.js} +2 -2
  50. package/build/{issues-xx5bs4md.js → issues-zdag9ayw.js} +82 -26
  51. package/build/{logs-qtxe51w2.js → logs-f492cjgt.js} +25 -20
  52. package/build/{offesecAgent-b9e2xm6v.js → offesecAgent-pr0cmrqb.js} +10 -9
  53. package/build/pentest-1g3fzah5.js +30 -0
  54. package/build/{pentests-6ks3szc4.js → pentests-vstpzh9j.js} +26 -21
  55. package/build/{targetedPentest-s1ptvq8e.js → targetedPentest-wj3ae355.js} +11 -10
  56. package/build/{targets-sxygyj87.js → targets-806zxf1n.js} +27 -22
  57. package/build/threatModel-dc4jbhkf.js +29 -0
  58. package/build/{uninstall-tvsh81v8.js → uninstall-58ak2e2v.js} +6 -3
  59. package/build/{upload-7wdyyqmr.js → upload-kkktzh83.js} +8 -7
  60. package/build/{utils-7fwdkqk6.js → utils-1sawtwbj.js} +7 -6
  61. package/package.json +8 -2
  62. package/build/agent-mvpgvgks.js +0 -19
  63. package/build/authentication-3s97cpk4.js +0 -19
  64. package/build/blackboxAgent-gw0a1ca4.js +0 -19
  65. package/build/blackboxPentest-44333zss.js +0 -37
  66. package/build/main-mmjp338j.js +0 -324
  67. package/build/pentest-xtc1sjdw.js +0 -29
  68. package/build/threatModel-xsm6fwk5.js +0 -27
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  detectOSAndEnhancePrompt
3
- } from "./cli-tznv8pf1.js";
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-tkc598ey.js";
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-0n4r54hq.js";
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-swpbx60z.js";
72
+ } from "./cli-avmhkjtv.js";
70
73
  import {
71
74
  config,
72
75
  init_config
73
- } from "./cli-72cvcqhg.js";
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
- screen: {
105059
- minWidth: __window[0],
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-3s97cpk4.js");
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-mvpgvgks.js");
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
- function getEffectiveValue(metrics, baseMetric, modifiedMetric) {
108446
- if (modifiedMetric) {
108447
- const modValue = metrics[modifiedMetric];
108448
- if (modValue && modValue !== "X") {
108449
- return modValue;
108450
- }
108451
- }
108452
- return metrics[baseMetric] ?? "";
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", "MAV");
108456
- const pr = getEffectiveValue(metrics, "PR", "MPR");
108457
- const ui = getEffectiveValue(metrics, "UI", "MUI");
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 (!(av === "P" || pr === "H" || ui === "A")) {
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", "MAC");
108468
- const at = getEffectiveValue(metrics, "AT", "MAT");
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", "MVC");
108476
- const vi = getEffectiveValue(metrics, "VI", "MVI");
108477
- const va = getEffectiveValue(metrics, "VA", "MVA");
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.MSI || "X";
108488
- const msa = metrics.MSA || "X";
108489
- const sc = getEffectiveValue(metrics, "SC", "MSC");
108490
- const si = msi !== "X" ? msi : metrics.SI;
108491
- const sa = msa !== "X" ? msa : metrics.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.E || "A";
108502
- if (e === "A" || e === "X") {
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.CR || "H";
108512
- const ir = metrics.IR || "H";
108513
- const ar = metrics.AR || "H";
108514
- const vc = getEffectiveValue(metrics, "VC", "MVC");
108515
- const vi = getEffectiveValue(metrics, "VI", "MVI");
108516
- const va = getEffectiveValue(metrics, "VA", "MVA");
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
- const vc = getEffectiveValue(metrics, "VC", "MVC");
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 getMetricDistance(metrics, metric) {
108541
- const levels = METRIC_LEVELS[metric];
108542
- if (!levels)
108543
- return 0;
108544
- let value;
108545
- const modifiedMetric = `M${metric}`;
108546
- const metricsRecord = metrics;
108547
- if (metricsRecord[modifiedMetric] && metricsRecord[modifiedMetric] !== "X") {
108548
- value = metricsRecord[modifiedMetric] ?? "";
108549
- } else {
108550
- value = metricsRecord[metric] ?? "";
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
- if (metric === "E" && (!value || value === "X")) {
108553
- value = "A";
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
- if ((metric === "CR" || metric === "IR" || metric === "AR") && (!value || value === "X")) {
108556
- value = "H";
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 levels[value] || 0;
108663
+ return vectors;
108559
108664
  }
108560
- function getNextLowerScore(macroVector, position) {
108561
- const digits = macroVector.split("").map(Number);
108562
- digits[position]++;
108563
- const nextMacroVector = digits.join("");
108564
- return MACROVECTOR_LOOKUP[nextMacroVector] ?? null;
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 interpolateScore(metrics, macroVector, baseScore) {
108567
- const eq1 = parseInt(macroVector[0], 10);
108568
- const eq2 = parseInt(macroVector[1], 10);
108569
- const eq3 = parseInt(macroVector[2], 10);
108570
- const eq4 = parseInt(macroVector[3], 10);
108571
- const eq5 = parseInt(macroVector[4], 10);
108572
- const eq6 = parseInt(macroVector[5], 10);
108573
- let meanDistance = 0;
108574
- let eqCount = 0;
108575
- const eq1NextLower = getNextLowerScore(macroVector, 0);
108576
- if (eq1NextLower !== null) {
108577
- const msd = baseScore - eq1NextLower;
108578
- const maxDepth = MAX_SEVERITY.eq1[eq1] || 1;
108579
- const avDist = getMetricDistance(metrics, "AV");
108580
- const prDist = getMetricDistance(metrics, "PR");
108581
- const uiDist = getMetricDistance(metrics, "UI");
108582
- const severityDist = avDist + prDist + uiDist;
108583
- const normalizedDist = severityDist / (maxDepth * STEP);
108584
- meanDistance += msd * normalizedDist;
108585
- eqCount++;
108586
- }
108587
- const eq2NextLower = getNextLowerScore(macroVector, 1);
108588
- if (eq2NextLower !== null) {
108589
- const msd = baseScore - eq2NextLower;
108590
- const maxDepth = MAX_SEVERITY.eq2[eq2] || 1;
108591
- const acDist = getMetricDistance(metrics, "AC");
108592
- const atDist = getMetricDistance(metrics, "AT");
108593
- const severityDist = acDist + atDist;
108594
- const normalizedDist = severityDist / (maxDepth * STEP);
108595
- meanDistance += msd * normalizedDist;
108596
- eqCount++;
108597
- }
108598
- const eq3eq6MaxSeverity = MAX_SEVERITY.eq3eq6;
108599
- if (eq3eq6MaxSeverity[eq3] && eq3eq6MaxSeverity[eq3][eq6] !== undefined) {
108600
- const eq3NextLower = getNextLowerScore(macroVector, 2);
108601
- if (eq3NextLower !== null) {
108602
- const msd = baseScore - eq3NextLower;
108603
- const maxDepth = eq3eq6MaxSeverity[eq3][eq6] || 1;
108604
- const vcDist = getMetricDistance(metrics, "VC");
108605
- const viDist = getMetricDistance(metrics, "VI");
108606
- const vaDist = getMetricDistance(metrics, "VA");
108607
- const crDist = getMetricDistance(metrics, "CR");
108608
- const irDist = getMetricDistance(metrics, "IR");
108609
- const arDist = getMetricDistance(metrics, "AR");
108610
- const severityDist = vcDist + viDist + vaDist + crDist + irDist + arDist;
108611
- const normalizedDist = severityDist / (maxDepth * STEP);
108612
- meanDistance += msd * normalizedDist;
108613
- eqCount++;
108614
- }
108615
- }
108616
- const eq4NextLower = getNextLowerScore(macroVector, 3);
108617
- if (eq4NextLower !== null) {
108618
- const msd = baseScore - eq4NextLower;
108619
- const maxDepth = MAX_SEVERITY.eq4[eq4] || 1;
108620
- const scDist = getMetricDistance(metrics, "SC");
108621
- const siDist = getMetricDistance(metrics, "SI");
108622
- const saDist = getMetricDistance(metrics, "SA");
108623
- const severityDist = scDist + siDist + saDist;
108624
- const normalizedDist = severityDist / (maxDepth * STEP);
108625
- meanDistance += msd * normalizedDist;
108626
- eqCount++;
108627
- }
108628
- const eq5NextLower = getNextLowerScore(macroVector, 4);
108629
- if (eq5NextLower !== null) {
108630
- const msd = baseScore - eq5NextLower;
108631
- const maxDepth = MAX_SEVERITY.eq5[eq5] || 1;
108632
- const eDist = getMetricDistance(metrics, "E");
108633
- const normalizedDist = eDist / (maxDepth * STEP);
108634
- meanDistance += msd * normalizedDist;
108635
- eqCount++;
108636
- }
108637
- const avgDistance = eqCount > 0 ? meanDistance / eqCount : 0;
108638
- let finalScore = baseScore - avgDistance;
108639
- finalScore = Math.max(0, Math.min(10, finalScore));
108640
- finalScore = Math.round(finalScore * 10) / 10;
108641
- return finalScore;
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-5ejt5vpz.js");
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 effectiveStderr = cmd.forcedStderrSuffix ? (cmd.stderr || "") + cmd.forcedStderrSuffix : cmd.stderr || "";
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-rbzhk712.js");
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-gw0a1ca4.js");
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-xtc1sjdw.js");
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-mvpgvgks.js");
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 the FULL URL including the endpoint path the caller wants tested (e.g. https://example.com/api/users/{id}), not a bare domain. Forward through whatever URL the orchestrator itself received unless recon turned up a related sibling endpoint that genuinely belongs to a follow-up objective.
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("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'). Pass through whatever URL the orchestrator received as its own target that is already the domain + endpoint path the console / caller wants tested. Do NOT strip the path back to a bare domain, and do NOT invent a different endpoint; you are not doing endpoint discovery. If a single objective genuinely needs a sibling path (e.g. recon revealed a related admin endpoint on the same host), only then deviate, and keep the full URL."),
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
- const { TargetedPentestAgent } = await import("./agent-nhs1w5w0.js");
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 are already authenticated for any origin the orchestrator authenticated for. Do NOT re-authenticate unless a request returns 401/403.
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-xtc1sjdw.js");
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 ENDPOINT_TRANSPORTS = [
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(ENDPOINT_TRANSPORTS).nullish().transform((value) => value ?? undefined).optional().describe("Wire transport; defaults to http when omitted"),
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(ENDPOINT_TRANSPORTS).nullish().transform((value) => value ?? undefined).optional().describe("Corrected wire transport"),
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(record3)}
125007
+ appendFileSync3(this.tracePath, `${JSON.stringify(enriched)}
124712
125008
  `);
124713
125009
  } catch {}
124714
125010
  try {
124715
125011
  this.eventBus?.emit("trace-record", {
124716
- record: record3,
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
- import { existsSync as existsSync18, mkdirSync as mkdirSync14, readFileSync as readFileSync8 } from "node:fs";
124727
- import { writeFile as writeFile7 } from "node:fs/promises";
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
- var log13 = scopedLogger(() => createLogger("approval-gate"));
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
- latestMessages = null;
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 (RESPONSE_DEBUG) {
125214
- rlog.warn(`[response-debug] response tool EXECUTED (captured) session=${this.busSessionId} ` + `resultBytes=${responseArgBytes(result)} — happy path`);
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 (!existsSync18(messagesDir)) {
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
- const PERSIST_INTERVAL_MS = 15000;
125299
- let persistTimer = null;
125300
- const schedulePersist = () => {
125301
- if (persistTimer)
125302
- return;
125303
- persistTimer = setTimeout(() => {
125304
- persistTimer = null;
125305
- if (this.latestMessages) {
125306
- const toWrite = this.latestMessages;
125307
- this.latestMessages = null;
125308
- writeFile7(messagesPath, JSON.stringify(toWrite)).catch(() => {});
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.latestMessages = [
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
- if (persistTimer) {
125368
- clearTimeout(persistTimer);
125369
- persistTimer = null;
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
- await writeFile7(messagesPath, JSON.stringify(finalMessages)).catch(() => {});
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 inFlightTools = new Map;
125429
- const completedResults = [];
126163
+ const tracker = new ToolLifecycleTracker;
125430
126164
  let streamError = null;
125431
- const responseArgChars = new Map;
125432
- const responseSawTerminal = new Map;
125433
- const streamedArgText = new Map;
125434
- const toolErrors = new Map;
125435
- let lastChunkAt = Date.now();
125436
- let lastChunkType = "none";
125437
- let stallStepIndex = -1;
125438
- let stallTimer;
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
- if (STREAM_STALL_DEBUG) {
125451
- const now = Date.now();
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
- if (stallTimer)
125596
- clearInterval(stallTimer);
125597
- this.persistentShell?.dispose();
125598
- for (const [toolCallId, info] of toolErrors) {
125599
- const result2 = {
125600
- type: "error-text",
125601
- value: `Tool call failed: ${info.message}`
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 spanLabel = this.subagentName ?? sid;
125643
- const drain = !sid ? runConsume() : withSubagentSessionBaggage(sid, () => getApexTracer().startActiveSpan(`invoke_agent ${spanLabel}`, {
125644
- attributes: {
125645
- "gen_ai.operation.name": "invoke_agent",
125646
- "gen_ai.agent.name": spanLabel
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
- }, async (span) => {
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 };