pentesting 0.8.39 → 0.8.42

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 (3) hide show
  1. package/README.md +115 -18
  2. package/dist/index.js +1131 -17
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -32,8 +32,8 @@ import TextInput from "ink-text-input";
32
32
  import Spinner from "ink-spinner";
33
33
 
34
34
  // src/core/agent/autonomous-agent.ts
35
- import Anthropic from "@anthropic-ai/sdk";
36
- import { EventEmitter as EventEmitter4 } from "events";
35
+ import Anthropic3 from "@anthropic-ai/sdk";
36
+ import { EventEmitter as EventEmitter7 } from "events";
37
37
 
38
38
  // src/core/prompts/autonomous-prompt.ts
39
39
  var AUTONOMOUS_HACKING_PROMPT = `You are Pentesting, an elite autonomous penetration testing AI designed for CTF competitions and professional security assessments. You operate with minimal human intervention, making intelligent decisions, adapting to obstacles, and persistently pursuing objectives until complete system compromise.
@@ -220,6 +220,115 @@ Analyze your situation honestly:
220
220
  - Manual testing vs. automated?
221
221
 
222
222
  Based on this reflection, propose 3 completely different approaches to try next.`;
223
+ var STRATEGY_PLANNING_PROMPT = `You are the strategic coordinator for this penetration test. Before executing ANY action, validate the strategy.
224
+
225
+ ## STRATEGIC VALIDATION PROCESS
226
+
227
+ ### 1. INTENT VERIFICATION
228
+ \`\`\`
229
+ [INTENT CHECK]
230
+ - What is the user's objective?
231
+ - What phase are we in?
232
+ - What have we accomplished so far?
233
+ - What is the immediate goal?
234
+ \`\`\`
235
+
236
+ ### 2. PLAN FORMULATION
237
+ \`\`\`
238
+ [PLAN PROPOSAL]
239
+ Given the current state, I propose:
240
+ 1. [Primary approach] - Expected outcome: X
241
+ 2. [Backup approach] - If primary fails: Y
242
+ 3. [Alternative] - If we need to pivot: Z
243
+ \`\`\`
244
+
245
+ ### 3. PLAN VALIDATION (Self-Check)
246
+ \`\`\`
247
+ [VALIDATION]
248
+ \u25A1 Is this aligned with BFS (surface mapping first)?
249
+ \u25A1 Have I completed reconnaissance before deep testing?
250
+ \u25A1 Is this the highest ROI action right now?
251
+ \u25A1 Am I avoiding rabbit holes (SSL testing too early, etc.)?
252
+ \u25A1 Is the tool/command correct for this task?
253
+ \`\`\`
254
+
255
+ ### 4. AGENT COORDINATION
256
+ When switching agents or techniques:
257
+ \`\`\`
258
+ [HANDOFF]
259
+ From: [current agent/approach]
260
+ To: [next agent/approach]
261
+ Reason: [why this switch makes sense]
262
+ Context passed: [what the next agent needs to know]
263
+ \`\`\`
264
+
265
+ ### 5. DECISION LOG
266
+ After each significant decision:
267
+ \`\`\`
268
+ [DECISION]
269
+ Action: [what was done]
270
+ Result: [what happened]
271
+ Learning: [what we now know]
272
+ Next: [logical next step]
273
+ \`\`\`
274
+
275
+ ## ANTI-PATTERNS TO DETECT AND PREVENT
276
+
277
+ - \u274C SSL/TLS testing before full surface mapping
278
+ - \u274C Deep diving one endpoint before discovering others
279
+ - \u274C Brute force without any intelligence
280
+ - \u274C Repeating failed commands with minor changes
281
+ - \u274C Ignoring discovered information
282
+ - \u274C Skipping subdomain/directory enumeration
283
+
284
+ ## SUCCESS PATTERNS TO FOLLOW
285
+
286
+ - \u2705 Port scan \u2192 Web discovery (subdomain + directory) \u2192 Technology detection \u2192 CVE check
287
+ - \u2705 Find all endpoints first, then prioritize by value
288
+ - \u2705 Use discovered info (usernames, versions) in subsequent attacks
289
+ - \u2705 Pivot quickly when stuck (max 3 attempts per approach)
290
+ - \u2705 Document findings as we go`;
291
+ var AGENT_COLLABORATION_PROMPT = `When collaborating with other specialized agents:
292
+
293
+ ## AGENT ROLES
294
+ - **Recon Agent**: Surface discovery, OSINT, subdomain/directory enumeration
295
+ - **Exploit Agent**: Vulnerability exploitation, payload delivery
296
+ - **PrivEsc Agent**: Privilege escalation on compromised hosts
297
+ - **Web Agent**: Web application testing, injection attacks
298
+ - **Crypto Agent**: Cryptographic analysis, hash cracking
299
+
300
+ ## COLLABORATION PROTOCOL
301
+
302
+ ### 1. TASK DELEGATION
303
+ \`\`\`
304
+ [DELEGATE]
305
+ From: [current agent]
306
+ To: [specialized agent]
307
+ Task: [specific task]
308
+ Expected output: [what we need back]
309
+ \`\`\`
310
+
311
+ ### 2. RESULTS HANDOFF
312
+ \`\`\`
313
+ [HANDOFF]
314
+ Agent: [which agent completed]
315
+ Findings: [key discoveries]
316
+ Recommended next: [what should happen next]
317
+ \`\`\`
318
+
319
+ ### 3. CONFLICT RESOLUTION
320
+ When agents disagree on approach:
321
+ - Consider ROI of each approach
322
+ - Check if one requires prerequisites the other provides
323
+ - Default to BFS (broader coverage) over DFS (deep focus)
324
+ - Escalate to user only if truly ambiguous
325
+
326
+ ### 4. KNOWLEDGE SHARING
327
+ All agents maintain shared context:
328
+ - Discovered hosts and services
329
+ - Obtained credentials
330
+ - Failed approaches (don't repeat)
331
+ - Current attack surface map`;
223
332
 
224
333
  // src/core/tools/tool-definitions.ts
225
334
  var SYSTEM_TOOLS = [
@@ -4150,6 +4259,868 @@ function buildAgentSystemPrompt(basePrompt, agent) {
4150
4259
  ${agent.systemPrompt}`;
4151
4260
  }
4152
4261
 
4262
+ // src/core/agent/agent-orchestrator.ts
4263
+ import Anthropic from "@anthropic-ai/sdk";
4264
+ import { EventEmitter as EventEmitter4 } from "events";
4265
+ var ORCHESTRATOR_EVENT = {
4266
+ AGENT_START: "agent_start",
4267
+ AGENT_COMPLETE: "agent_complete",
4268
+ AGENT_ERROR: "agent_error",
4269
+ ALL_COMPLETE: "all_complete",
4270
+ FINDING: "finding"
4271
+ };
4272
+ var AgentOrchestrator = class extends EventEmitter4 {
4273
+ client;
4274
+ agents = /* @__PURE__ */ new Map();
4275
+ initialized = false;
4276
+ constructor(apiKey) {
4277
+ super();
4278
+ this.client = new Anthropic({
4279
+ apiKey: apiKey || LLM_API_KEY || process.env.PENTEST_API_KEY,
4280
+ baseURL: LLM_BASE_URL
4281
+ });
4282
+ }
4283
+ /**
4284
+ * Initialize with built-in agents
4285
+ */
4286
+ async initialize() {
4287
+ if (this.initialized) return;
4288
+ for (const agent of BUILTIN_AGENTS) {
4289
+ this.agents.set(agent.name, agent);
4290
+ }
4291
+ this.initialized = true;
4292
+ }
4293
+ /**
4294
+ * Launch multiple agents in parallel
4295
+ */
4296
+ async launchParallel(tasks) {
4297
+ await this.initialize();
4298
+ console.log(`\u{1F680} Launching ${tasks.length} agents in parallel...`);
4299
+ const startTime = Date.now();
4300
+ const promises = tasks.map((task) => this.executeAgent(task));
4301
+ const results = await Promise.allSettled(promises);
4302
+ const duration = Date.now() - startTime;
4303
+ console.log(`\u2705 All agents completed in ${(duration / 1e3).toFixed(1)}s`);
4304
+ const finalResults = results.map((result, index) => {
4305
+ if (result.status === "fulfilled") {
4306
+ return result.value;
4307
+ } else {
4308
+ return {
4309
+ agent: tasks[index].agent,
4310
+ success: false,
4311
+ output: "",
4312
+ findings: [],
4313
+ duration: 0,
4314
+ error: result.reason?.message || "Agent failed"
4315
+ };
4316
+ }
4317
+ });
4318
+ this.emit(ORCHESTRATOR_EVENT.ALL_COMPLETE, {
4319
+ results: finalResults,
4320
+ duration
4321
+ });
4322
+ return finalResults;
4323
+ }
4324
+ /**
4325
+ * Execute a single agent
4326
+ */
4327
+ async executeAgent(task) {
4328
+ const startTime = Date.now();
4329
+ this.emit(ORCHESTRATOR_EVENT.AGENT_START, { agent: task.agent, prompt: task.prompt });
4330
+ try {
4331
+ const agentDef = this.agents.get(task.agent);
4332
+ const systemPrompt = agentDef ? buildAgentSystemPrompt("You are a security expert. Report findings clearly.", agentDef) : `You are a security expert focused on ${task.agent}. Be thorough and report findings in JSON format.`;
4333
+ const response = await withRetry(
4334
+ () => this.client.messages.create({
4335
+ model: LLM_MODEL,
4336
+ max_tokens: LLM_MAX_TOKENS,
4337
+ system: systemPrompt,
4338
+ messages: [
4339
+ { role: "user", content: task.prompt }
4340
+ ]
4341
+ }),
4342
+ { maxRetries: 2 }
4343
+ );
4344
+ const output = response.content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
4345
+ const findings = this.parseFindings(output, task.agent);
4346
+ const duration = Date.now() - startTime;
4347
+ const result = {
4348
+ agent: task.agent,
4349
+ success: true,
4350
+ output,
4351
+ findings,
4352
+ duration
4353
+ };
4354
+ this.emit(ORCHESTRATOR_EVENT.AGENT_COMPLETE, result);
4355
+ for (const finding of findings) {
4356
+ this.emit(ORCHESTRATOR_EVENT.FINDING, finding);
4357
+ }
4358
+ return result;
4359
+ } catch (error) {
4360
+ const errorMsg = error instanceof Error ? error.message : String(error);
4361
+ this.emit(ORCHESTRATOR_EVENT.AGENT_ERROR, { agent: task.agent, error: errorMsg });
4362
+ return {
4363
+ agent: task.agent,
4364
+ success: false,
4365
+ output: "",
4366
+ findings: [],
4367
+ duration: Date.now() - startTime,
4368
+ error: errorMsg
4369
+ };
4370
+ }
4371
+ }
4372
+ /**
4373
+ * Parse findings from agent output
4374
+ */
4375
+ parseFindings(output, agentName) {
4376
+ const findings = [];
4377
+ const jsonMatch = output.match(/```json\n?([\s\S]*?)\n?```/);
4378
+ if (jsonMatch) {
4379
+ try {
4380
+ const parsed = JSON.parse(jsonMatch[1]);
4381
+ if (Array.isArray(parsed)) {
4382
+ return parsed.map((f) => this.normalizeFinding(f, agentName));
4383
+ } else if (parsed.findings) {
4384
+ return parsed.findings.map((f) => this.normalizeFinding(f, agentName));
4385
+ }
4386
+ } catch {
4387
+ }
4388
+ }
4389
+ const patterns = [
4390
+ { regex: /CVE-\d{4}-\d+/gi, type: "vulnerability", severity: "high" },
4391
+ { regex: /open port[s]?[:\s]+(\d+)/gi, type: "info", severity: "info" },
4392
+ { regex: /admin|root|password/gi, type: "credential", severity: "high" },
4393
+ { regex: /shell access|RCE|command injection/gi, type: "vulnerability", severity: "critical" },
4394
+ { regex: /SQL injection|XSS|SSRF/gi, type: "vulnerability", severity: "high" }
4395
+ ];
4396
+ for (const pattern of patterns) {
4397
+ const matches = output.match(pattern.regex);
4398
+ if (matches) {
4399
+ for (const match of [...new Set(matches)]) {
4400
+ findings.push({
4401
+ id: `finding_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`,
4402
+ type: pattern.type,
4403
+ title: match,
4404
+ description: `Found by ${agentName}: ${match}`,
4405
+ confidence: 60,
4406
+ severity: pattern.severity,
4407
+ evidence: [match],
4408
+ exploitability: "possible"
4409
+ });
4410
+ }
4411
+ }
4412
+ }
4413
+ return findings;
4414
+ }
4415
+ /**
4416
+ * Normalize a finding object
4417
+ */
4418
+ normalizeFinding(raw, agentName) {
4419
+ const f = raw;
4420
+ return {
4421
+ id: f.id || `finding_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`,
4422
+ type: f.type || "info",
4423
+ title: f.title || "Unknown finding",
4424
+ description: f.description || `Found by ${agentName}`,
4425
+ confidence: f.confidence || 50,
4426
+ severity: f.severity || "medium",
4427
+ evidence: f.evidence || [],
4428
+ exploitability: f.exploitability || "possible",
4429
+ nextSteps: f.nextSteps
4430
+ };
4431
+ }
4432
+ /**
4433
+ * Get available agent names
4434
+ */
4435
+ getAgentNames() {
4436
+ return Array.from(this.agents.keys());
4437
+ }
4438
+ };
4439
+ function consolidateFindings(results) {
4440
+ const allFindings = [];
4441
+ for (const result of results) {
4442
+ allFindings.push(...result.findings);
4443
+ }
4444
+ const findingMap = /* @__PURE__ */ new Map();
4445
+ for (const finding of allFindings) {
4446
+ const key = `${finding.type}:${finding.title}`;
4447
+ if (findingMap.has(key)) {
4448
+ const existing = findingMap.get(key);
4449
+ existing.confidence = Math.min(100, existing.confidence + 10);
4450
+ existing.evidence.push(...finding.evidence);
4451
+ } else {
4452
+ findingMap.set(key, { ...finding });
4453
+ }
4454
+ }
4455
+ return Array.from(findingMap.values()).sort((a, b) => b.confidence - a.confidence);
4456
+ }
4457
+ var orchestratorInstance = null;
4458
+ function getOrchestrator(apiKey) {
4459
+ if (!orchestratorInstance) {
4460
+ orchestratorInstance = new AgentOrchestrator(apiKey);
4461
+ }
4462
+ return orchestratorInstance;
4463
+ }
4464
+
4465
+ // src/core/agent/agent-memory.ts
4466
+ import { EventEmitter as EventEmitter5 } from "events";
4467
+ var MEMORY_EVENT = {
4468
+ ENTRY_ADDED: "entry_added",
4469
+ STATE_UPDATED: "state_updated",
4470
+ HANDOFF: "handoff",
4471
+ COMPACTION: "compaction"
4472
+ };
4473
+ var AgentMemory = class _AgentMemory extends EventEmitter5 {
4474
+ // Short-term memory (current session)
4475
+ shortTermMemory = [];
4476
+ // Long-term memory (persisted across sessions)
4477
+ longTermMemory = [];
4478
+ // Episodic memory (specific events/interactions)
4479
+ episodicMemory = /* @__PURE__ */ new Map();
4480
+ // Shared state across all agents
4481
+ sharedState;
4482
+ // Agent contexts
4483
+ agentContexts = /* @__PURE__ */ new Map();
4484
+ // Memory limits
4485
+ SHORT_TERM_LIMIT = 100;
4486
+ LONG_TERM_LIMIT = 1e3;
4487
+ COMPACTION_THRESHOLD = 80;
4488
+ // % of limit
4489
+ constructor(target = "") {
4490
+ super();
4491
+ this.sharedState = this.initializeState(target);
4492
+ }
4493
+ // ===== State Management =====
4494
+ initializeState(target) {
4495
+ return {
4496
+ target,
4497
+ discoveredHosts: [],
4498
+ discoveredServices: /* @__PURE__ */ new Map(),
4499
+ credentials: [],
4500
+ currentPhase: "recon",
4501
+ completedPhases: [],
4502
+ attackSurface: /* @__PURE__ */ new Map(),
4503
+ vulnerabilities: [],
4504
+ failedApproaches: []
4505
+ };
4506
+ }
4507
+ getSharedState() {
4508
+ return this.sharedState;
4509
+ }
4510
+ updateState(updates) {
4511
+ this.sharedState = { ...this.sharedState, ...updates };
4512
+ this.emit(MEMORY_EVENT.STATE_UPDATED, this.sharedState);
4513
+ }
4514
+ // ===== Memory Operations =====
4515
+ addMemory(entry) {
4516
+ const fullEntry = {
4517
+ ...entry,
4518
+ id: `mem_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`,
4519
+ timestamp: /* @__PURE__ */ new Date()
4520
+ };
4521
+ this.shortTermMemory.push(fullEntry);
4522
+ if (entry.importance >= 70) {
4523
+ this.longTermMemory.push(fullEntry);
4524
+ }
4525
+ if (!this.episodicMemory.has(entry.agent)) {
4526
+ this.episodicMemory.set(entry.agent, []);
4527
+ }
4528
+ this.episodicMemory.get(entry.agent).push(fullEntry);
4529
+ this.emit(MEMORY_EVENT.ENTRY_ADDED, fullEntry);
4530
+ this.checkCompaction();
4531
+ return fullEntry;
4532
+ }
4533
+ // ===== Memory Retrieval =====
4534
+ getRecentMemories(count = 10) {
4535
+ return this.shortTermMemory.slice(-count);
4536
+ }
4537
+ getMemoriesByAgent(agentName) {
4538
+ return this.episodicMemory.get(agentName) || [];
4539
+ }
4540
+ getMemoriesByType(type) {
4541
+ return [...this.shortTermMemory, ...this.longTermMemory].filter((m) => m.type === type);
4542
+ }
4543
+ getImportantMemories(threshold = 70) {
4544
+ return this.longTermMemory.filter((m) => m.importance >= threshold);
4545
+ }
4546
+ searchMemories(query) {
4547
+ const lowerQuery = query.toLowerCase();
4548
+ return [...this.shortTermMemory, ...this.longTermMemory].filter((m) => m.content.toLowerCase().includes(lowerQuery)).sort((a, b) => b.importance - a.importance);
4549
+ }
4550
+ // ===== Agent Context Management =====
4551
+ setAgentContext(context) {
4552
+ this.agentContexts.set(context.agentName, context);
4553
+ }
4554
+ getAgentContext(agentName) {
4555
+ return this.agentContexts.get(agentName);
4556
+ }
4557
+ getAllAgentContexts() {
4558
+ return Array.from(this.agentContexts.values());
4559
+ }
4560
+ // ===== Agent Handoff =====
4561
+ /**
4562
+ * Create a handoff package for transferring context between agents
4563
+ */
4564
+ createHandoff(fromAgent, toAgent, task, relevantContext) {
4565
+ const handoffId = `handoff_${Date.now()}`;
4566
+ const relevantMemories = this.shortTermMemory.filter(
4567
+ (m) => m.agent === fromAgent || relevantContext.some((c) => m.content.includes(c))
4568
+ ).slice(-20);
4569
+ const contextSummary = this.createContextSummary(fromAgent, task);
4570
+ this.addMemory({
4571
+ type: "handoff",
4572
+ agent: "orchestrator",
4573
+ content: `Handoff: ${fromAgent} \u2192 ${toAgent} for task: ${task}`,
4574
+ importance: 80,
4575
+ metadata: { fromAgent, toAgent, task, handoffId }
4576
+ });
4577
+ this.emit(MEMORY_EVENT.HANDOFF, { fromAgent, toAgent, task, handoffId });
4578
+ return {
4579
+ handoffId,
4580
+ context: contextSummary,
4581
+ sharedState: this.sharedState,
4582
+ relevantMemories
4583
+ };
4584
+ }
4585
+ /**
4586
+ * Create a summarized context for handoff
4587
+ */
4588
+ createContextSummary(agentName, task) {
4589
+ const agentMemories = this.getMemoriesByAgent(agentName).slice(-10);
4590
+ const findings = this.getMemoriesByType("finding").slice(-5);
4591
+ const errors = this.getMemoriesByType("error").slice(-3);
4592
+ return `
4593
+ ## Context Summary for: ${task}
4594
+
4595
+ ### Target
4596
+ - Primary: ${this.sharedState.target}
4597
+ - Phase: ${this.sharedState.currentPhase}
4598
+ - Hosts discovered: ${this.sharedState.discoveredHosts.length}
4599
+
4600
+ ### Recent Actions by ${agentName}
4601
+ ${agentMemories.map((m) => `- ${m.content.slice(0, 100)}`).join("\n")}
4602
+
4603
+ ### Key Findings
4604
+ ${findings.map((f) => `- [${f.agent}] ${f.content.slice(0, 100)}`).join("\n")}
4605
+
4606
+ ### Failed Approaches (avoid these)
4607
+ ${this.sharedState.failedApproaches.slice(-5).map((f) => `- ${f.approach}: ${f.reason}`).join("\n")}
4608
+
4609
+ ### Credentials Found
4610
+ ${this.sharedState.credentials.map((c) => `- ${c.username}:${c.password} (${c.source})`).join("\n") || "None"}
4611
+ `;
4612
+ }
4613
+ // ===== Attack Surface Tracking =====
4614
+ addToAttackSurface(category, items) {
4615
+ const existing = this.sharedState.attackSurface.get(category) || [];
4616
+ const newItems = items.filter((i) => !existing.includes(i));
4617
+ this.sharedState.attackSurface.set(category, [...existing, ...newItems]);
4618
+ if (newItems.length > 0) {
4619
+ this.addMemory({
4620
+ type: "discovery",
4621
+ agent: "orchestrator",
4622
+ content: `Attack surface expanded [${category}]: ${newItems.join(", ")}`,
4623
+ importance: 60
4624
+ });
4625
+ }
4626
+ }
4627
+ getAttackSurface() {
4628
+ return this.sharedState.attackSurface;
4629
+ }
4630
+ getAttackSurfaceSummary() {
4631
+ const summary = [];
4632
+ for (const [category, items] of this.sharedState.attackSurface) {
4633
+ summary.push(`${category}: ${items.length} items`);
4634
+ }
4635
+ return summary.join(", ");
4636
+ }
4637
+ // ===== Failed Approach Tracking =====
4638
+ recordFailedApproach(approach, reason) {
4639
+ this.sharedState.failedApproaches.push({
4640
+ approach,
4641
+ reason,
4642
+ timestamp: /* @__PURE__ */ new Date()
4643
+ });
4644
+ }
4645
+ hasFailedBefore(approach) {
4646
+ return this.sharedState.failedApproaches.some(
4647
+ (f) => f.approach.toLowerCase().includes(approach.toLowerCase())
4648
+ );
4649
+ }
4650
+ // ===== Memory Compaction =====
4651
+ checkCompaction() {
4652
+ if (this.shortTermMemory.length >= this.SHORT_TERM_LIMIT * (this.COMPACTION_THRESHOLD / 100)) {
4653
+ this.compactShortTermMemory();
4654
+ }
4655
+ if (this.longTermMemory.length >= this.LONG_TERM_LIMIT * (this.COMPACTION_THRESHOLD / 100)) {
4656
+ this.compactLongTermMemory();
4657
+ }
4658
+ }
4659
+ compactShortTermMemory() {
4660
+ const sorted = [...this.shortTermMemory].sort((a, b) => {
4661
+ const importanceDiff = b.importance - a.importance;
4662
+ if (importanceDiff !== 0) return importanceDiff;
4663
+ return b.timestamp.getTime() - a.timestamp.getTime();
4664
+ });
4665
+ this.shortTermMemory = sorted.slice(0, Math.floor(this.SHORT_TERM_LIMIT * 0.5));
4666
+ this.emit(MEMORY_EVENT.COMPACTION, { type: "short-term", remaining: this.shortTermMemory.length });
4667
+ }
4668
+ compactLongTermMemory() {
4669
+ this.longTermMemory = this.longTermMemory.sort((a, b) => b.importance - a.importance).slice(0, Math.floor(this.LONG_TERM_LIMIT * 0.7));
4670
+ this.emit(MEMORY_EVENT.COMPACTION, { type: "long-term", remaining: this.longTermMemory.length });
4671
+ }
4672
+ // ===== Serialization =====
4673
+ toJSON() {
4674
+ return {
4675
+ shortTermMemory: this.shortTermMemory,
4676
+ longTermMemory: this.longTermMemory,
4677
+ sharedState: {
4678
+ ...this.sharedState,
4679
+ discoveredServices: Object.fromEntries(this.sharedState.discoveredServices),
4680
+ attackSurface: Object.fromEntries(this.sharedState.attackSurface)
4681
+ },
4682
+ agentContexts: Object.fromEntries(this.agentContexts)
4683
+ };
4684
+ }
4685
+ static fromJSON(data) {
4686
+ const memory = new _AgentMemory();
4687
+ const parsed = data;
4688
+ memory.shortTermMemory = parsed.shortTermMemory || [];
4689
+ memory.longTermMemory = parsed.longTermMemory || [];
4690
+ if (parsed.sharedState) {
4691
+ memory.sharedState = {
4692
+ ...parsed.sharedState,
4693
+ discoveredServices: new Map(Object.entries(parsed.sharedState.discoveredServices || {})),
4694
+ attackSurface: new Map(Object.entries(parsed.sharedState.attackSurface || {}))
4695
+ };
4696
+ }
4697
+ if (parsed.agentContexts) {
4698
+ memory.agentContexts = new Map(Object.entries(parsed.agentContexts));
4699
+ }
4700
+ return memory;
4701
+ }
4702
+ };
4703
+ var memoryInstance = null;
4704
+ function getAgentMemory(target) {
4705
+ if (!memoryInstance) {
4706
+ memoryInstance = new AgentMemory(target);
4707
+ }
4708
+ return memoryInstance;
4709
+ }
4710
+
4711
+ // src/core/agent/supervisor-agent.ts
4712
+ import Anthropic2 from "@anthropic-ai/sdk";
4713
+ import { EventEmitter as EventEmitter6 } from "events";
4714
+ var SUPERVISOR_EVENT = {
4715
+ PLAN_CREATED: "plan_created",
4716
+ PHASE_STARTED: "phase_started",
4717
+ PHASE_COMPLETED: "phase_completed",
4718
+ TASK_DELEGATED: "task_delegated",
4719
+ TASK_COMPLETED: "task_completed",
4720
+ STRATEGY_ADJUSTED: "strategy_adjusted",
4721
+ DECISION_MADE: "decision_made"
4722
+ };
4723
+ var SupervisorAgent = class extends EventEmitter6 {
4724
+ client;
4725
+ orchestrator;
4726
+ memory;
4727
+ currentPlan = null;
4728
+ // Agent capability mapping
4729
+ agentCapabilities = /* @__PURE__ */ new Map([
4730
+ ["target-explorer", ["recon", "scanning", "enumeration", "osint", "subdomain", "directory"]],
4731
+ ["exploit-researcher", ["cve", "exploit", "vulnerability", "payload", "metasploit"]],
4732
+ ["privesc-master", ["privilege", "escalation", "root", "system", "linux", "windows"]],
4733
+ ["web-hacker", ["web", "sql", "xss", "injection", "http", "api", "form"]],
4734
+ ["crypto-solver", ["crypto", "hash", "password", "decrypt", "encode"]],
4735
+ ["forensics-analyst", ["forensics", "memory", "file", "log", "steganography"]],
4736
+ ["reverse-engineer", ["binary", "reverse", "debug", "exploit", "buffer"]],
4737
+ ["attack-architect", ["strategy", "plan", "attack", "chain", "prioritize"]],
4738
+ ["finding-reviewer", ["validate", "verify", "review", "confidence", "false positive"]]
4739
+ ]);
4740
+ constructor(apiKey) {
4741
+ super();
4742
+ this.client = new Anthropic2({
4743
+ apiKey: apiKey || LLM_API_KEY || process.env.PENTEST_API_KEY,
4744
+ baseURL: LLM_BASE_URL
4745
+ });
4746
+ this.orchestrator = getOrchestrator(apiKey);
4747
+ this.memory = getAgentMemory();
4748
+ }
4749
+ // ===== Task Planning =====
4750
+ /**
4751
+ * Create an execution plan for the given objective
4752
+ */
4753
+ async createPlan(objective, target) {
4754
+ const planPrompt = `
4755
+ ${STRATEGY_PLANNING_PROMPT}
4756
+
4757
+ Create an execution plan for:
4758
+ Objective: ${objective}
4759
+ Target: ${target}
4760
+
4761
+ Respond with a JSON plan:
4762
+ {
4763
+ "phases": [
4764
+ {
4765
+ "name": "Phase name",
4766
+ "description": "What this phase accomplishes",
4767
+ "agents": ["agent-name"],
4768
+ "tasks": [
4769
+ {
4770
+ "description": "Task description",
4771
+ "assignedAgent": "agent-name"
4772
+ }
4773
+ ]
4774
+ }
4775
+ ]
4776
+ }
4777
+
4778
+ Rules:
4779
+ 1. Start with reconnaissance (BFS - map attack surface first)
4780
+ 2. Discovery before exploitation
4781
+ 3. Use specialized agents for their strengths
4782
+ 4. Include validation steps
4783
+ 5. Plan for fallbacks
4784
+ `;
4785
+ try {
4786
+ const response = await this.client.messages.create({
4787
+ model: LLM_MODEL,
4788
+ max_tokens: 2048,
4789
+ messages: [{ role: "user", content: planPrompt }]
4790
+ });
4791
+ const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
4792
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
4793
+ if (jsonMatch) {
4794
+ const parsed = JSON.parse(jsonMatch[0]);
4795
+ this.currentPlan = this.buildPlan(objective, parsed);
4796
+ } else {
4797
+ this.currentPlan = this.createDefaultPlan(objective, target);
4798
+ }
4799
+ } catch {
4800
+ this.currentPlan = this.createDefaultPlan(objective, target);
4801
+ }
4802
+ this.emit(SUPERVISOR_EVENT.PLAN_CREATED, this.currentPlan);
4803
+ this.memory.addMemory({
4804
+ type: "decision",
4805
+ agent: "supervisor",
4806
+ content: `Plan created: ${this.currentPlan.phases.length} phases for ${objective}`,
4807
+ importance: 90
4808
+ });
4809
+ return this.currentPlan;
4810
+ }
4811
+ buildPlan(objective, parsed) {
4812
+ return {
4813
+ id: `plan_${Date.now()}`,
4814
+ objective,
4815
+ status: "planning",
4816
+ currentPhaseIndex: 0,
4817
+ phases: parsed.phases.map((phase, idx) => ({
4818
+ id: `phase_${idx}`,
4819
+ name: phase.name,
4820
+ description: phase.description,
4821
+ agents: phase.agents || [],
4822
+ status: "pending",
4823
+ findings: [],
4824
+ tasks: (phase.tasks || []).map((task, tidx) => ({
4825
+ id: `task_${idx}_${tidx}`,
4826
+ description: task.description,
4827
+ assignedAgent: task.assignedAgent || this.selectBestAgent(task.description),
4828
+ status: "pending"
4829
+ }))
4830
+ }))
4831
+ };
4832
+ }
4833
+ createDefaultPlan(objective, target) {
4834
+ return {
4835
+ id: `plan_${Date.now()}`,
4836
+ objective,
4837
+ status: "planning",
4838
+ currentPhaseIndex: 0,
4839
+ phases: [
4840
+ {
4841
+ id: "phase_0",
4842
+ name: "Reconnaissance",
4843
+ description: "Map attack surface - ports, subdomains, directories",
4844
+ agents: ["target-explorer"],
4845
+ status: "pending",
4846
+ findings: [],
4847
+ tasks: [
4848
+ { id: "task_0_0", description: `Port scan ${target}`, assignedAgent: "target-explorer", status: "pending" },
4849
+ { id: "task_0_1", description: `Subdomain enumeration for ${target}`, assignedAgent: "target-explorer", status: "pending" },
4850
+ { id: "task_0_2", description: `Directory bruteforce on web services`, assignedAgent: "web-hacker", status: "pending" }
4851
+ ]
4852
+ },
4853
+ {
4854
+ id: "phase_1",
4855
+ name: "Analysis",
4856
+ description: "Analyze findings and identify vulnerabilities",
4857
+ agents: ["attack-architect", "finding-reviewer"],
4858
+ status: "pending",
4859
+ findings: [],
4860
+ tasks: [
4861
+ { id: "task_1_0", description: "Analyze attack surface and prioritize targets", assignedAgent: "attack-architect", status: "pending" },
4862
+ { id: "task_1_1", description: "CVE research for discovered services", assignedAgent: "exploit-researcher", status: "pending" }
4863
+ ]
4864
+ },
4865
+ {
4866
+ id: "phase_2",
4867
+ name: "Exploitation",
4868
+ description: "Attempt exploitation of identified vulnerabilities",
4869
+ agents: ["exploit-researcher", "web-hacker"],
4870
+ status: "pending",
4871
+ findings: [],
4872
+ tasks: [
4873
+ { id: "task_2_0", description: "Exploit high-priority vulnerabilities", assignedAgent: "exploit-researcher", status: "pending" }
4874
+ ]
4875
+ }
4876
+ ]
4877
+ };
4878
+ }
4879
+ // ===== Agent Selection =====
4880
+ /**
4881
+ * Select the best agent for a given task
4882
+ */
4883
+ selectBestAgent(taskDescription) {
4884
+ const lowerTask = taskDescription.toLowerCase();
4885
+ let bestAgent = "target-explorer";
4886
+ let bestScore = 0;
4887
+ for (const [agent, capabilities] of this.agentCapabilities) {
4888
+ const score = capabilities.filter((cap) => lowerTask.includes(cap)).length;
4889
+ if (score > bestScore) {
4890
+ bestScore = score;
4891
+ bestAgent = agent;
4892
+ }
4893
+ }
4894
+ return bestAgent;
4895
+ }
4896
+ /**
4897
+ * Get agents for a specific phase
4898
+ */
4899
+ getAgentsForPhase(phaseName) {
4900
+ const phaseMapping = {
4901
+ "recon": ["target-explorer"],
4902
+ "reconnaissance": ["target-explorer"],
4903
+ "scan": ["target-explorer"],
4904
+ "enum": ["target-explorer", "web-hacker"],
4905
+ "enumeration": ["target-explorer", "web-hacker"],
4906
+ "analysis": ["attack-architect", "finding-reviewer"],
4907
+ "vuln": ["exploit-researcher", "web-hacker"],
4908
+ "vulnerability": ["exploit-researcher", "web-hacker"],
4909
+ "exploit": ["exploit-researcher", "web-hacker"],
4910
+ "exploitation": ["exploit-researcher", "web-hacker"],
4911
+ "privesc": ["privesc-master"],
4912
+ "privilege": ["privesc-master"],
4913
+ "post": ["privesc-master", "forensics-analyst"]
4914
+ };
4915
+ const lowerPhase = phaseName.toLowerCase();
4916
+ for (const [key, agents] of Object.entries(phaseMapping)) {
4917
+ if (lowerPhase.includes(key)) {
4918
+ return agents;
4919
+ }
4920
+ }
4921
+ return ["target-explorer"];
4922
+ }
4923
+ // ===== Task Execution =====
4924
+ /**
4925
+ * Execute the current plan
4926
+ */
4927
+ async executePlan() {
4928
+ if (!this.currentPlan) {
4929
+ throw new Error("No plan created. Call createPlan() first.");
4930
+ }
4931
+ this.currentPlan.status = "executing";
4932
+ const allFindings = [];
4933
+ for (let i = 0; i < this.currentPlan.phases.length; i++) {
4934
+ this.currentPlan.currentPhaseIndex = i;
4935
+ const phase = this.currentPlan.phases[i];
4936
+ this.emit(SUPERVISOR_EVENT.PHASE_STARTED, phase);
4937
+ phase.status = "in_progress";
4938
+ try {
4939
+ const phaseFindings = await this.executePhase(phase);
4940
+ phase.findings = phaseFindings;
4941
+ allFindings.push(...phaseFindings);
4942
+ phase.status = "completed";
4943
+ this.emit(SUPERVISOR_EVENT.PHASE_COMPLETED, phase);
4944
+ await this.evaluateProgress(phaseFindings);
4945
+ } catch (error) {
4946
+ phase.status = "failed";
4947
+ this.memory.recordFailedApproach(
4948
+ phase.name,
4949
+ error instanceof Error ? error.message : "Unknown error"
4950
+ );
4951
+ }
4952
+ }
4953
+ this.currentPlan.status = "completed";
4954
+ return consolidateFindings(allFindings.map((f) => ({
4955
+ agent: "supervisor",
4956
+ success: true,
4957
+ output: "",
4958
+ findings: [f],
4959
+ duration: 0
4960
+ })));
4961
+ }
4962
+ /**
4963
+ * Execute a single phase
4964
+ */
4965
+ async executePhase(phase) {
4966
+ const tasks = phase.tasks.map((task) => ({
4967
+ agent: task.assignedAgent,
4968
+ prompt: this.buildTaskPrompt(task, phase),
4969
+ priority: 1
4970
+ }));
4971
+ await this.orchestrator.initialize();
4972
+ const results = await this.orchestrator.launchParallel(tasks);
4973
+ for (let i = 0; i < phase.tasks.length; i++) {
4974
+ const task = phase.tasks[i];
4975
+ const result = results[i];
4976
+ task.status = result.success ? "completed" : "failed";
4977
+ task.result = result.output;
4978
+ task.error = result.error;
4979
+ this.emit(SUPERVISOR_EVENT.TASK_COMPLETED, { task, result });
4980
+ this.memory.addMemory({
4981
+ type: result.success ? "action" : "error",
4982
+ agent: task.assignedAgent,
4983
+ content: result.success ? `Completed: ${task.description}` : `Failed: ${task.description} - ${result.error}`,
4984
+ importance: result.success ? 60 : 70
4985
+ });
4986
+ }
4987
+ return consolidateFindings(results);
4988
+ }
4989
+ buildTaskPrompt(task, phase) {
4990
+ const handoff = this.memory.createHandoff(
4991
+ "supervisor",
4992
+ task.assignedAgent,
4993
+ task.description,
4994
+ [phase.name, task.description]
4995
+ );
4996
+ return `
4997
+ ${AGENT_COLLABORATION_PROMPT}
4998
+
4999
+ ## Your Task
5000
+ ${task.description}
5001
+
5002
+ ## Phase Context
5003
+ Phase: ${phase.name}
5004
+ Description: ${phase.description}
5005
+
5006
+ ## Shared Context
5007
+ ${handoff.context}
5008
+
5009
+ ## Instructions
5010
+ 1. Complete the task thoroughly
5011
+ 2. Report all findings in structured format
5012
+ 3. Suggest next steps based on discoveries
5013
+ 4. Be efficient - BFS over DFS
5014
+
5015
+ Provide your findings in JSON format when possible.
5016
+ `;
5017
+ }
5018
+ // ===== Strategy Evaluation =====
5019
+ /**
5020
+ * Evaluate progress and adjust strategy if needed
5021
+ */
5022
+ async evaluateProgress(findings) {
5023
+ const criticalFindings = findings.filter((f) => f.severity === "critical" || f.severity === "high");
5024
+ const failedApproaches = this.memory.getSharedState().failedApproaches;
5025
+ if (criticalFindings.length > 0) {
5026
+ this.memory.addMemory({
5027
+ type: "decision",
5028
+ agent: "supervisor",
5029
+ content: `Strategy adjustment: Found ${criticalFindings.length} critical/high findings. Prioritizing exploitation.`,
5030
+ importance: 85
5031
+ });
5032
+ this.emit(SUPERVISOR_EVENT.STRATEGY_ADJUSTED, {
5033
+ reason: "Critical findings discovered",
5034
+ adjustment: "Prioritize exploitation",
5035
+ findings: criticalFindings
5036
+ });
5037
+ }
5038
+ if (failedApproaches.length >= 3) {
5039
+ this.memory.addMemory({
5040
+ type: "decision",
5041
+ agent: "supervisor",
5042
+ content: `Strategy adjustment: ${failedApproaches.length} failed approaches. Recommending pivot.`,
5043
+ importance: 80
5044
+ });
5045
+ }
5046
+ }
5047
+ // ===== Decision Making =====
5048
+ /**
5049
+ * Make a decision about next action
5050
+ */
5051
+ async makeDecision(situation) {
5052
+ const decisionPrompt = `
5053
+ ${STRATEGY_PLANNING_PROMPT}
5054
+
5055
+ Current situation:
5056
+ ${situation}
5057
+
5058
+ Shared state:
5059
+ - Target: ${this.memory.getSharedState().target}
5060
+ - Phase: ${this.memory.getSharedState().currentPhase}
5061
+ - Attack surface: ${this.memory.getAttackSurfaceSummary()}
5062
+ - Failed approaches: ${this.memory.getSharedState().failedApproaches.map((f) => f.approach).join(", ")}
5063
+
5064
+ Make a decision:
5065
+ 1. What action should we take?
5066
+ 2. Which agent should handle it?
5067
+ 3. What's your reasoning?
5068
+ 4. What are alternatives if this fails?
5069
+
5070
+ Respond with JSON:
5071
+ {
5072
+ "action": "description of action",
5073
+ "agent": "agent-name",
5074
+ "reasoning": "why this is the best choice",
5075
+ "confidence": 0-100,
5076
+ "alternatives": ["alt1", "alt2"]
5077
+ }
5078
+ `;
5079
+ try {
5080
+ const response = await this.client.messages.create({
5081
+ model: LLM_MODEL,
5082
+ max_tokens: 1024,
5083
+ messages: [{ role: "user", content: decisionPrompt }]
5084
+ });
5085
+ const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
5086
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
5087
+ if (jsonMatch) {
5088
+ const decision = JSON.parse(jsonMatch[0]);
5089
+ this.emit(SUPERVISOR_EVENT.DECISION_MADE, decision);
5090
+ this.memory.addMemory({
5091
+ type: "decision",
5092
+ agent: "supervisor",
5093
+ content: `Decision: ${decision.action} (${decision.agent}, ${decision.confidence}% confidence)`,
5094
+ importance: 75
5095
+ });
5096
+ return decision;
5097
+ }
5098
+ } catch {
5099
+ }
5100
+ return {
5101
+ action: "Continue with reconnaissance",
5102
+ agent: "target-explorer",
5103
+ reasoning: "Default action when unsure",
5104
+ confidence: 50,
5105
+ alternatives: ["web-hacker", "exploit-researcher"]
5106
+ };
5107
+ }
5108
+ // ===== Getters =====
5109
+ getCurrentPlan() {
5110
+ return this.currentPlan;
5111
+ }
5112
+ getMemory() {
5113
+ return this.memory;
5114
+ }
5115
+ };
5116
+ var supervisorInstance = null;
5117
+ function getSupervisor(apiKey) {
5118
+ if (!supervisorInstance) {
5119
+ supervisorInstance = new SupervisorAgent(apiKey);
5120
+ }
5121
+ return supervisorInstance;
5122
+ }
5123
+
4153
5124
  // src/commands/index.ts
4154
5125
  var SCAN_COMMAND = {
4155
5126
  name: "scan",
@@ -4466,7 +5437,7 @@ var DEFAULT_PHASES = [
4466
5437
  { id: PHASE_ID.EXFIL, name: "Data Exfiltration", shortName: "Exfil", status: PHASE_STATUS.PENDING, attempts: 0 },
4467
5438
  { id: PHASE_ID.REPORT, name: "Reporting", shortName: "Report", status: PHASE_STATUS.PENDING, attempts: 0 }
4468
5439
  ];
4469
- var AutonomousHackingAgent = class extends EventEmitter4 {
5440
+ var AutonomousHackingAgent = class extends EventEmitter7 {
4470
5441
  client;
4471
5442
  state;
4472
5443
  config;
@@ -4481,6 +5452,9 @@ var AutonomousHackingAgent = class extends EventEmitter4 {
4481
5452
  mcpManager;
4482
5453
  contextManager;
4483
5454
  approvalManager;
5455
+ orchestrator;
5456
+ agentMemory;
5457
+ supervisor;
4484
5458
  // Token usage tracking
4485
5459
  tokenUsage = {
4486
5460
  input: 0,
@@ -4499,7 +5473,7 @@ var AutonomousHackingAgent = class extends EventEmitter4 {
4499
5473
  // Max attempts per phase
4500
5474
  constructor(apiKey, config) {
4501
5475
  super();
4502
- this.client = new Anthropic({
5476
+ this.client = new Anthropic3({
4503
5477
  apiKey: apiKey || LLM_API_KEY || process.env.PENTEST_API_KEY,
4504
5478
  baseURL: LLM_BASE_URL
4505
5479
  });
@@ -4509,6 +5483,9 @@ var AutonomousHackingAgent = class extends EventEmitter4 {
4509
5483
  this.mcpManager = getMCPManager();
4510
5484
  this.contextManager = new ContextManager(this.client);
4511
5485
  this.approvalManager = getApprovalManager({ yoloMode: config?.autoApprove });
5486
+ this.orchestrator = getOrchestrator(apiKey);
5487
+ this.agentMemory = getAgentMemory();
5488
+ this.supervisor = getSupervisor(apiKey);
4512
5489
  this.state = this.createInitialState();
4513
5490
  this.initSystems();
4514
5491
  }
@@ -4919,25 +5896,161 @@ What went wrong and what different approach should be tried?
4919
5896
  this.think(THOUGHT_TYPE.REFLECTION, reflection);
4920
5897
  return reflection;
4921
5898
  }
5899
+ // ===== Strategy Validation =====
5900
+ async validateStrategy(proposedAction) {
5901
+ this.think(THOUGHT_TYPE.PLANNING, "[strategy] Validating action strategy...");
5902
+ const validationPrompt = `
5903
+ ${STRATEGY_PLANNING_PROMPT}
5904
+
5905
+ Current situation:
5906
+ - Target: ${this.state.target.primary}
5907
+ - Current phase: ${this.getCurrentPhase().shortName}
5908
+ - Discovered services: ${this.state.target.services.map((s) => `${s.host}:${s.port} (${s.service})`).join(", ") || "none"}
5909
+ - Attack surface mapped: ${this.state.target.discovered.length} hosts, ${this.state.target.services.length} services
5910
+ - Subdomains found: ${this.state.target.discovered.filter((d) => d.includes(".")).length}
5911
+
5912
+ Proposed action: ${proposedAction}
5913
+
5914
+ Validate this action:
5915
+ 1. Is this aligned with BFS (surface mapping first)?
5916
+ 2. Have we completed reconnaissance before deep testing?
5917
+ 3. Is this the highest ROI action right now?
5918
+ 4. Should we adjust the approach?
5919
+
5920
+ Respond with JSON:
5921
+ {
5922
+ "valid": true/false,
5923
+ "adjustedAction": "if invalid, suggest better action",
5924
+ "reasoning": "brief explanation"
5925
+ }
5926
+ `;
5927
+ try {
5928
+ const response = await this.client.messages.create({
5929
+ model: LLM_MODEL,
5930
+ max_tokens: 1024,
5931
+ messages: [{ role: "user", content: validationPrompt }]
5932
+ });
5933
+ const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
5934
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
5935
+ if (jsonMatch) {
5936
+ const result = JSON.parse(jsonMatch[0]);
5937
+ if (!result.valid) {
5938
+ this.think(THOUGHT_TYPE.REFLECTION, `[strategy] Action adjusted: ${result.reasoning}`);
5939
+ }
5940
+ return result;
5941
+ }
5942
+ } catch {
5943
+ }
5944
+ return { valid: true, reasoning: "Validation skipped" };
5945
+ }
5946
+ // ===== Agent Collaboration =====
5947
+ /**
5948
+ * Delegate a task to a specialist agent and get results
5949
+ */
5950
+ async delegateToSpecialist(agentName, task, context) {
5951
+ this.think(THOUGHT_TYPE.PLANNING, `[delegate] Delegating to ${agentName}: ${task.slice(0, 50)}...`);
5952
+ await this.orchestrator.initialize();
5953
+ const agentTask = {
5954
+ agent: agentName,
5955
+ prompt: `${AGENT_COLLABORATION_PROMPT}
5956
+
5957
+ Context from main agent:
5958
+ ${context}
5959
+
5960
+ Your task:
5961
+ ${task}
5962
+
5963
+ Provide your analysis and findings. Include:
5964
+ 1. Key discoveries
5965
+ 2. Recommended next actions
5966
+ 3. Any concerns or issues found`,
5967
+ priority: 1
5968
+ };
5969
+ try {
5970
+ const results = await this.orchestrator.launchParallel([agentTask]);
5971
+ const result = results[0];
5972
+ if (result.success) {
5973
+ const consolidatedFindings = consolidateFindings(results);
5974
+ const findingsSummary = consolidatedFindings.map((f) => `- [${f.severity.toUpperCase()}] ${f.title} (${f.confidence}% confidence)`).join("\n");
5975
+ this.think(THOUGHT_TYPE.REFLECTION, `[delegate] ${agentName} completed: ${result.findings.length} findings`);
5976
+ return {
5977
+ success: true,
5978
+ findings: findingsSummary || result.output.slice(0, 500),
5979
+ recommendation: result.findings[0]?.nextSteps?.join(", ") || "Continue with main approach"
5980
+ };
5981
+ }
5982
+ return {
5983
+ success: false,
5984
+ findings: result.error || "Agent failed",
5985
+ recommendation: "Try alternative approach"
5986
+ };
5987
+ } catch (error) {
5988
+ return {
5989
+ success: false,
5990
+ findings: error instanceof Error ? error.message : "Unknown error",
5991
+ recommendation: "Fallback to main agent"
5992
+ };
5993
+ }
5994
+ }
5995
+ /**
5996
+ * Consult multiple agents for strategy validation
5997
+ */
5998
+ async consultAgents(question) {
5999
+ this.think(THOUGHT_TYPE.PLANNING, "[consult] Consulting specialist agents...");
6000
+ const tasks = [
6001
+ {
6002
+ agent: "attack-architect",
6003
+ prompt: `Strategic question: ${question}
6004
+
6005
+ Provide your expert opinion on the best approach.`,
6006
+ priority: 1
6007
+ },
6008
+ {
6009
+ agent: "finding-reviewer",
6010
+ prompt: `Review this approach: ${question}
6011
+
6012
+ Validate if this is the right strategy.`,
6013
+ priority: 1
6014
+ }
6015
+ ];
6016
+ await this.orchestrator.initialize();
6017
+ const results = await this.orchestrator.launchParallel(tasks);
6018
+ const opinions = results.filter((r) => r.success).map((r) => `**${r.agent}**: ${r.output.slice(0, 200)}...`).join("\n\n");
6019
+ this.think(THOUGHT_TYPE.REFLECTION, "[consult] Received opinions from specialists");
6020
+ return opinions || "No specialist opinions available";
6021
+ }
4922
6022
  // ===== Progress Detection =====
4923
6023
  recordProgress(type) {
4924
6024
  this.resetStuckCounter();
4925
6025
  this.state.lastProgressTime = /* @__PURE__ */ new Date();
6026
+ let message = "";
6027
+ let importance = 60;
4926
6028
  switch (type) {
4927
6029
  case "discovery":
4928
- this.think(THOUGHT_TYPE.BREAKTHROUGH, "[target] New target discovered!");
6030
+ message = "[target] New target discovered!";
6031
+ importance = 65;
4929
6032
  break;
4930
6033
  case "credential":
4931
- this.think(THOUGHT_TYPE.BREAKTHROUGH, "[cred] Credential obtained!");
6034
+ message = "[cred] Credential obtained!";
6035
+ importance = 85;
4932
6036
  break;
4933
6037
  case "access":
4934
- this.think(THOUGHT_TYPE.BREAKTHROUGH, "[access] Access obtained!");
6038
+ message = "[access] Access obtained!";
6039
+ importance = 90;
4935
6040
  break;
4936
6041
  case "exploit":
4937
- this.think(THOUGHT_TYPE.BREAKTHROUGH, "[exploit] Exploit successful!");
6042
+ message = "[exploit] Exploit successful!";
6043
+ importance = 95;
4938
6044
  this.state.successfulExploits++;
4939
6045
  break;
4940
6046
  }
6047
+ this.think(THOUGHT_TYPE.BREAKTHROUGH, message);
6048
+ this.agentMemory.addMemory({
6049
+ type: type === "exploit" ? "action" : type === "credential" ? "credential" : "discovery",
6050
+ agent: this.currentAgent?.name || "autonomous-agent",
6051
+ content: message,
6052
+ importance
6053
+ });
4941
6054
  }
4942
6055
  // ===== Finding Management =====
4943
6056
  addFinding(finding) {
@@ -5686,14 +6799,14 @@ Respond helpfully to the user's message. If they ask to perform security testing
5686
6799
  // src/core/session/session-manager.ts
5687
6800
  import * as fs4 from "fs/promises";
5688
6801
  import * as path4 from "path";
5689
- import { EventEmitter as EventEmitter5 } from "events";
6802
+ import { EventEmitter as EventEmitter8 } from "events";
5690
6803
  var SESSIONS_DIR = ".pentesting/sessions";
5691
6804
  function generateSessionId() {
5692
6805
  const timestamp = Date.now().toString(36);
5693
6806
  const random = Math.random().toString(36).substring(2, 8);
5694
6807
  return `session_${timestamp}_${random}`;
5695
6808
  }
5696
- var SessionManager = class extends EventEmitter5 {
6809
+ var SessionManager = class extends EventEmitter8 {
5697
6810
  sessionsDir;
5698
6811
  currentSession = null;
5699
6812
  constructor(baseDir) {
@@ -6012,7 +7125,7 @@ function getSlashCommandRegistry() {
6012
7125
  // src/core/context/context-manager.ts
6013
7126
  import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync, renameSync } from "fs";
6014
7127
  import { join as join4, dirname as dirname3 } from "path";
6015
- import { EventEmitter as EventEmitter6 } from "events";
7128
+ import { EventEmitter as EventEmitter9 } from "events";
6016
7129
  var CONTEXT_EVENT = {
6017
7130
  MESSAGE_ADDED: "message_added",
6018
7131
  CHECKPOINT_CREATED: "checkpoint_created",
@@ -6020,7 +7133,7 @@ var CONTEXT_EVENT = {
6020
7133
  CLEARED: "cleared",
6021
7134
  COMPACTED: "compacted"
6022
7135
  };
6023
- var ContextManager2 = class extends EventEmitter6 {
7136
+ var ContextManager2 = class extends EventEmitter9 {
6024
7137
  filePath;
6025
7138
  state;
6026
7139
  maxMessages;
@@ -6731,9 +7844,9 @@ import { homedir } from "os";
6731
7844
  import { join as join7 } from "path";
6732
7845
 
6733
7846
  // src/cli/utils/keyboard-listener.ts
6734
- import { EventEmitter as EventEmitter7 } from "events";
7847
+ import { EventEmitter as EventEmitter10 } from "events";
6735
7848
  import * as readline2 from "readline";
6736
- var KeyboardListener = class extends EventEmitter7 {
7849
+ var KeyboardListener = class extends EventEmitter10 {
6737
7850
  isListening = false;
6738
7851
  isPaused = false;
6739
7852
  stdin = process.stdin;
@@ -6958,7 +8071,7 @@ function getKeyboardListener() {
6958
8071
  }
6959
8072
 
6960
8073
  // src/utils/input-queue.ts
6961
- import { EventEmitter as EventEmitter8 } from "events";
8074
+ import { EventEmitter as EventEmitter11 } from "events";
6962
8075
  var INPUT_QUEUE_EVENT = {
6963
8076
  QUEUED: "queued",
6964
8077
  // Message added to queue
@@ -6971,7 +8084,7 @@ var INPUT_QUEUE_EVENT = {
6971
8084
  SHUTDOWN: "shutdown"
6972
8085
  // Queue shutdown
6973
8086
  };
6974
- var InputQueue = class extends EventEmitter8 {
8087
+ var InputQueue = class extends EventEmitter11 {
6975
8088
  queue = [];
6976
8089
  isShutdown = false;
6977
8090
  isPaused = false;
@@ -7442,7 +8555,8 @@ var App = ({ autoApprove = false, target }) => {
7442
8555
  inputQueue.enqueue(trimmed);
7443
8556
  setQueuedCount(inputQueue.length);
7444
8557
  setInput("");
7445
- addMessage(MESSAGE_TYPE.SYSTEM, ` \u{1F4E5} Queued (${inputQueue.length} pending): ${trimmed.slice(0, 50)}${trimmed.length > 50 ? "..." : ""}`);
8558
+ addMessage(MESSAGE_TYPE.USER, trimmed);
8559
+ addMessage(MESSAGE_TYPE.SYSTEM, ` \u{1F4E5} Queued (${inputQueue.length} pending)`);
7446
8560
  return;
7447
8561
  }
7448
8562
  setInput("");