pentesting 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/index.js +235 -182
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,6 +29,11 @@ export PENTEST_API_KEY=your_api_key
|
|
|
29
29
|
export PENTEST_BASE_URL=https://your-api-endpoint.com/v1
|
|
30
30
|
export PENTEST_MODEL=your-model-name
|
|
31
31
|
|
|
32
|
+
export PENTEST_API_KEY="key"
|
|
33
|
+
export PENTEST_BASE_URL="https://api.z.ai/api/anthropic"
|
|
34
|
+
export PENTEST_MODEL="glm-4.7"
|
|
35
|
+
|
|
36
|
+
|
|
32
37
|
# Run
|
|
33
38
|
pentesting
|
|
34
39
|
```
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import Spinner from "ink-spinner";
|
|
|
12
12
|
|
|
13
13
|
// src/core/agent/autonomous-agent.ts
|
|
14
14
|
import Anthropic from "@anthropic-ai/sdk";
|
|
15
|
-
import { EventEmitter as
|
|
15
|
+
import { EventEmitter as EventEmitter4 } from "events";
|
|
16
16
|
|
|
17
17
|
// src/core/prompts/autonomous-prompt.ts
|
|
18
18
|
var AUTONOMOUS_HACKING_PROMPT = `You are Hacker-Code, 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.
|
|
@@ -251,6 +251,8 @@ var AGENT_EVENT = {
|
|
|
251
251
|
TOOL_CALL: "tool_call",
|
|
252
252
|
TOOL_RESULT: "tool_result",
|
|
253
253
|
COMMAND_EXECUTE: "command_execute",
|
|
254
|
+
APPROVAL_NEEDED: "approval_needed",
|
|
255
|
+
TOKEN_USAGE: "token_usage",
|
|
254
256
|
// State changes
|
|
255
257
|
TARGET_SET: "target_set",
|
|
256
258
|
PHASE_CHANGE: "phase_change",
|
|
@@ -1374,7 +1376,7 @@ const { chromium } = require('playwright');
|
|
|
1374
1376
|
}
|
|
1375
1377
|
|
|
1376
1378
|
// src/config/constants.ts
|
|
1377
|
-
var APP_VERSION = "0.2.
|
|
1379
|
+
var APP_VERSION = "0.2.5";
|
|
1378
1380
|
var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
|
|
1379
1381
|
var LLM_API_KEY = process.env.PENTEST_API_KEY || process.env.ANTHROPIC_API_KEY || "";
|
|
1380
1382
|
var LLM_BASE_URL = process.env.PENTEST_BASE_URL || void 0;
|
|
@@ -1732,6 +1734,183 @@ function getMCPManager() {
|
|
|
1732
1734
|
return mcpManager;
|
|
1733
1735
|
}
|
|
1734
1736
|
|
|
1737
|
+
// src/core/approval/approval-manager.ts
|
|
1738
|
+
import { EventEmitter as EventEmitter3 } from "events";
|
|
1739
|
+
var APPROVAL_EVENT = {
|
|
1740
|
+
REQUEST: "approval_request",
|
|
1741
|
+
RESPONSE: "approval_response",
|
|
1742
|
+
TIMEOUT: "approval_timeout"
|
|
1743
|
+
};
|
|
1744
|
+
var CRITICAL_TOOLS = [
|
|
1745
|
+
"execute_command",
|
|
1746
|
+
"write_file",
|
|
1747
|
+
"delete_file",
|
|
1748
|
+
"modify_file",
|
|
1749
|
+
"send_request",
|
|
1750
|
+
"exploit_execute"
|
|
1751
|
+
];
|
|
1752
|
+
var HIGH_RISK_PATTERNS = [
|
|
1753
|
+
/rm\s+-rf/i,
|
|
1754
|
+
/mkfs/i,
|
|
1755
|
+
/dd\s+if=/i,
|
|
1756
|
+
/format/i,
|
|
1757
|
+
/shutdown/i,
|
|
1758
|
+
/reboot/i,
|
|
1759
|
+
/kill\s+-9/i,
|
|
1760
|
+
/pkill/i,
|
|
1761
|
+
/iptables/i,
|
|
1762
|
+
/ufw/i,
|
|
1763
|
+
/firewall/i,
|
|
1764
|
+
/passwd/i,
|
|
1765
|
+
/useradd/i,
|
|
1766
|
+
/userdel/i,
|
|
1767
|
+
/chmod\s+777/i,
|
|
1768
|
+
/chown/i,
|
|
1769
|
+
/sudo/i,
|
|
1770
|
+
/su\s+-/i,
|
|
1771
|
+
/nc\s+-e/i,
|
|
1772
|
+
/bash\s+-i/i,
|
|
1773
|
+
/reverse.*shell/i,
|
|
1774
|
+
/bind.*shell/i,
|
|
1775
|
+
/meterpreter/i,
|
|
1776
|
+
/mimikatz/i
|
|
1777
|
+
];
|
|
1778
|
+
function assessRisk(toolName, toolInput) {
|
|
1779
|
+
const inputStr = JSON.stringify(toolInput).toLowerCase();
|
|
1780
|
+
for (const pattern of HIGH_RISK_PATTERNS) {
|
|
1781
|
+
if (pattern.test(inputStr)) {
|
|
1782
|
+
return "critical";
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
if (CRITICAL_TOOLS.includes(toolName)) {
|
|
1786
|
+
return "high";
|
|
1787
|
+
}
|
|
1788
|
+
if (toolName.includes("script") || toolName.includes("exec")) {
|
|
1789
|
+
return "medium";
|
|
1790
|
+
}
|
|
1791
|
+
if (toolName.includes("scan") || toolName.includes("request")) {
|
|
1792
|
+
return "medium";
|
|
1793
|
+
}
|
|
1794
|
+
return "low";
|
|
1795
|
+
}
|
|
1796
|
+
function generateRequestId() {
|
|
1797
|
+
return `approval_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
1798
|
+
}
|
|
1799
|
+
var ApprovalManager = class extends EventEmitter3 {
|
|
1800
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
1801
|
+
autoApprovedTools = /* @__PURE__ */ new Set();
|
|
1802
|
+
autoDeniedTools = /* @__PURE__ */ new Set();
|
|
1803
|
+
yoloMode = false;
|
|
1804
|
+
defaultTimeout = 6e4;
|
|
1805
|
+
// 1 minute
|
|
1806
|
+
constructor(options) {
|
|
1807
|
+
super();
|
|
1808
|
+
this.yoloMode = options?.yoloMode ?? false;
|
|
1809
|
+
this.defaultTimeout = options?.timeout ?? 6e4;
|
|
1810
|
+
}
|
|
1811
|
+
/**
|
|
1812
|
+
* Enable/disable YOLO mode (auto-approve everything)
|
|
1813
|
+
*/
|
|
1814
|
+
setYoloMode(enabled) {
|
|
1815
|
+
this.yoloMode = enabled;
|
|
1816
|
+
this.emit("yolo_mode_changed", enabled);
|
|
1817
|
+
}
|
|
1818
|
+
/**
|
|
1819
|
+
* Check if approval is required for a tool call
|
|
1820
|
+
*/
|
|
1821
|
+
requiresApproval(toolName, toolInput) {
|
|
1822
|
+
if (this.yoloMode) return false;
|
|
1823
|
+
if (this.autoApprovedTools.has(toolName)) return false;
|
|
1824
|
+
if (this.autoDeniedTools.has(toolName)) return true;
|
|
1825
|
+
const risk = assessRisk(toolName, toolInput);
|
|
1826
|
+
if (risk === "low") return false;
|
|
1827
|
+
return true;
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* Request approval for a tool call
|
|
1831
|
+
*/
|
|
1832
|
+
async requestApproval(toolName, toolInput, reason) {
|
|
1833
|
+
if (this.autoDeniedTools.has(toolName)) {
|
|
1834
|
+
return "deny";
|
|
1835
|
+
}
|
|
1836
|
+
if (this.autoApprovedTools.has(toolName)) {
|
|
1837
|
+
return "approve";
|
|
1838
|
+
}
|
|
1839
|
+
const risk = assessRisk(toolName, toolInput);
|
|
1840
|
+
const request = {
|
|
1841
|
+
id: generateRequestId(),
|
|
1842
|
+
toolName,
|
|
1843
|
+
toolInput,
|
|
1844
|
+
reason: reason || `Tool "${toolName}" requires approval (${risk} risk)`,
|
|
1845
|
+
riskLevel: risk,
|
|
1846
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1847
|
+
};
|
|
1848
|
+
this.pendingRequests.set(request.id, request);
|
|
1849
|
+
this.emit(APPROVAL_EVENT.REQUEST, request);
|
|
1850
|
+
return new Promise((resolve) => {
|
|
1851
|
+
const timeout = setTimeout(() => {
|
|
1852
|
+
this.pendingRequests.delete(request.id);
|
|
1853
|
+
this.emit(APPROVAL_EVENT.TIMEOUT, request.id);
|
|
1854
|
+
resolve("deny");
|
|
1855
|
+
}, this.defaultTimeout);
|
|
1856
|
+
const responseHandler = (response) => {
|
|
1857
|
+
if (response.requestId === request.id) {
|
|
1858
|
+
clearTimeout(timeout);
|
|
1859
|
+
this.pendingRequests.delete(request.id);
|
|
1860
|
+
this.removeListener(APPROVAL_EVENT.RESPONSE, responseHandler);
|
|
1861
|
+
if (response.decision === "approve_always") {
|
|
1862
|
+
this.autoApprovedTools.add(toolName);
|
|
1863
|
+
resolve("approve");
|
|
1864
|
+
} else if (response.decision === "deny_always") {
|
|
1865
|
+
this.autoDeniedTools.add(toolName);
|
|
1866
|
+
resolve("deny");
|
|
1867
|
+
} else {
|
|
1868
|
+
resolve(response.decision);
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
};
|
|
1872
|
+
this.on(APPROVAL_EVENT.RESPONSE, responseHandler);
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1875
|
+
/**
|
|
1876
|
+
* Respond to an approval request (called by UI)
|
|
1877
|
+
*/
|
|
1878
|
+
respond(requestId, decision) {
|
|
1879
|
+
const response = {
|
|
1880
|
+
requestId,
|
|
1881
|
+
decision,
|
|
1882
|
+
respondedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1883
|
+
};
|
|
1884
|
+
this.emit(APPROVAL_EVENT.RESPONSE, response);
|
|
1885
|
+
}
|
|
1886
|
+
/**
|
|
1887
|
+
* Get pending requests
|
|
1888
|
+
*/
|
|
1889
|
+
getPendingRequests() {
|
|
1890
|
+
return Array.from(this.pendingRequests.values());
|
|
1891
|
+
}
|
|
1892
|
+
/**
|
|
1893
|
+
* Get auto-approved tools
|
|
1894
|
+
*/
|
|
1895
|
+
getAutoApprovedTools() {
|
|
1896
|
+
return Array.from(this.autoApprovedTools);
|
|
1897
|
+
}
|
|
1898
|
+
/**
|
|
1899
|
+
* Reset all auto decisions
|
|
1900
|
+
*/
|
|
1901
|
+
resetAutoDecisions() {
|
|
1902
|
+
this.autoApprovedTools.clear();
|
|
1903
|
+
this.autoDeniedTools.clear();
|
|
1904
|
+
}
|
|
1905
|
+
};
|
|
1906
|
+
var approvalManager = null;
|
|
1907
|
+
function getApprovalManager(options) {
|
|
1908
|
+
if (!approvalManager) {
|
|
1909
|
+
approvalManager = new ApprovalManager(options);
|
|
1910
|
+
}
|
|
1911
|
+
return approvalManager;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1735
1914
|
// src/core/tools/web-search.ts
|
|
1736
1915
|
import { spawn as spawn4 } from "child_process";
|
|
1737
1916
|
async function searchDuckDuckGo(query, options = {}) {
|
|
@@ -2959,7 +3138,7 @@ var DEFAULT_PHASES = [
|
|
|
2959
3138
|
{ id: PHASE_ID.EXFIL, name: "Data Exfiltration", shortName: "Exfil", status: PHASE_STATUS.PENDING, attempts: 0 },
|
|
2960
3139
|
{ id: PHASE_ID.REPORT, name: "Reporting", shortName: "Report", status: PHASE_STATUS.PENDING, attempts: 0 }
|
|
2961
3140
|
];
|
|
2962
|
-
var AutonomousHackingAgent = class extends
|
|
3141
|
+
var AutonomousHackingAgent = class extends EventEmitter4 {
|
|
2963
3142
|
client;
|
|
2964
3143
|
state;
|
|
2965
3144
|
config;
|
|
@@ -2970,6 +3149,13 @@ var AutonomousHackingAgent = class extends EventEmitter3 {
|
|
|
2970
3149
|
hookExecutor;
|
|
2971
3150
|
mcpManager;
|
|
2972
3151
|
contextManager;
|
|
3152
|
+
approvalManager;
|
|
3153
|
+
// Token usage tracking
|
|
3154
|
+
tokenUsage = {
|
|
3155
|
+
input: 0,
|
|
3156
|
+
output: 0,
|
|
3157
|
+
total: 0
|
|
3158
|
+
};
|
|
2973
3159
|
// Rabbit hole detection settings
|
|
2974
3160
|
STUCK_THRESHOLD = 5;
|
|
2975
3161
|
// Same action repeat count
|
|
@@ -2988,6 +3174,7 @@ var AutonomousHackingAgent = class extends EventEmitter3 {
|
|
|
2988
3174
|
this.hookExecutor = getHookExecutor();
|
|
2989
3175
|
this.mcpManager = getMCPManager();
|
|
2990
3176
|
this.contextManager = new ContextManager(this.client);
|
|
3177
|
+
this.approvalManager = getApprovalManager({ yoloMode: config?.autoApprove });
|
|
2991
3178
|
this.state = this.createInitialState();
|
|
2992
3179
|
this.initSystems();
|
|
2993
3180
|
}
|
|
@@ -3399,6 +3586,12 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
|
|
|
3399
3586
|
}
|
|
3400
3587
|
}
|
|
3401
3588
|
);
|
|
3589
|
+
if (response.usage) {
|
|
3590
|
+
this.tokenUsage.input += response.usage.input_tokens;
|
|
3591
|
+
this.tokenUsage.output += response.usage.output_tokens;
|
|
3592
|
+
this.tokenUsage.total = this.tokenUsage.input + this.tokenUsage.output;
|
|
3593
|
+
this.emit(AGENT_EVENT.TOKEN_USAGE, this.tokenUsage);
|
|
3594
|
+
}
|
|
3402
3595
|
return this.processResponse(response);
|
|
3403
3596
|
}
|
|
3404
3597
|
buildContextPrompt() {
|
|
@@ -3457,6 +3650,29 @@ Use report_finding tool for important discoveries.
|
|
|
3457
3650
|
this.think(THOUGHT_TYPE.STUCK, `Tool blocked by hook: ${hookCheck.output}`);
|
|
3458
3651
|
continue;
|
|
3459
3652
|
}
|
|
3653
|
+
if (this.approvalManager.requiresApproval(toolName, toolInput)) {
|
|
3654
|
+
const risk = assessRisk(toolName, toolInput);
|
|
3655
|
+
this.emit(AGENT_EVENT.APPROVAL_NEEDED, {
|
|
3656
|
+
id: block.id,
|
|
3657
|
+
toolName,
|
|
3658
|
+
toolInput,
|
|
3659
|
+
riskLevel: risk
|
|
3660
|
+
});
|
|
3661
|
+
const decision = await this.approvalManager.requestApproval(
|
|
3662
|
+
toolName,
|
|
3663
|
+
toolInput,
|
|
3664
|
+
`Executing ${toolName} (${risk} risk)`
|
|
3665
|
+
);
|
|
3666
|
+
if (decision === "deny") {
|
|
3667
|
+
this.think(THOUGHT_TYPE.STUCK, `Tool denied by user: ${toolName}`);
|
|
3668
|
+
this.emit(AGENT_EVENT.TOOL_RESULT, {
|
|
3669
|
+
id: block.id,
|
|
3670
|
+
name: toolName,
|
|
3671
|
+
result: { success: false, output: "Denied by user" }
|
|
3672
|
+
});
|
|
3673
|
+
continue;
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3460
3676
|
const result = await executeToolCall(toolName, toolInput);
|
|
3461
3677
|
await this.hookExecutor.runPostToolUse(toolName, result.output || "");
|
|
3462
3678
|
const resultType = result.success ? "result" : "result";
|
|
@@ -3833,14 +4049,14 @@ Respond helpfully to the user's message. If they ask to perform security testing
|
|
|
3833
4049
|
// src/core/session/session-manager.ts
|
|
3834
4050
|
import * as fs3 from "fs/promises";
|
|
3835
4051
|
import * as path3 from "path";
|
|
3836
|
-
import { EventEmitter as
|
|
4052
|
+
import { EventEmitter as EventEmitter5 } from "events";
|
|
3837
4053
|
var SESSIONS_DIR = ".pentesting/sessions";
|
|
3838
4054
|
function generateSessionId() {
|
|
3839
4055
|
const timestamp = Date.now().toString(36);
|
|
3840
4056
|
const random = Math.random().toString(36).substring(2, 8);
|
|
3841
4057
|
return `session_${timestamp}_${random}`;
|
|
3842
4058
|
}
|
|
3843
|
-
var SessionManager = class extends
|
|
4059
|
+
var SessionManager = class extends EventEmitter5 {
|
|
3844
4060
|
sessionsDir;
|
|
3845
4061
|
currentSession = null;
|
|
3846
4062
|
constructor(baseDir) {
|
|
@@ -4015,183 +4231,6 @@ function getSessionManager() {
|
|
|
4015
4231
|
return sessionManager;
|
|
4016
4232
|
}
|
|
4017
4233
|
|
|
4018
|
-
// src/core/approval/approval-manager.ts
|
|
4019
|
-
import { EventEmitter as EventEmitter5 } from "events";
|
|
4020
|
-
var APPROVAL_EVENT = {
|
|
4021
|
-
REQUEST: "approval_request",
|
|
4022
|
-
RESPONSE: "approval_response",
|
|
4023
|
-
TIMEOUT: "approval_timeout"
|
|
4024
|
-
};
|
|
4025
|
-
var CRITICAL_TOOLS = [
|
|
4026
|
-
"execute_command",
|
|
4027
|
-
"write_file",
|
|
4028
|
-
"delete_file",
|
|
4029
|
-
"modify_file",
|
|
4030
|
-
"send_request",
|
|
4031
|
-
"exploit_execute"
|
|
4032
|
-
];
|
|
4033
|
-
var HIGH_RISK_PATTERNS = [
|
|
4034
|
-
/rm\s+-rf/i,
|
|
4035
|
-
/mkfs/i,
|
|
4036
|
-
/dd\s+if=/i,
|
|
4037
|
-
/format/i,
|
|
4038
|
-
/shutdown/i,
|
|
4039
|
-
/reboot/i,
|
|
4040
|
-
/kill\s+-9/i,
|
|
4041
|
-
/pkill/i,
|
|
4042
|
-
/iptables/i,
|
|
4043
|
-
/ufw/i,
|
|
4044
|
-
/firewall/i,
|
|
4045
|
-
/passwd/i,
|
|
4046
|
-
/useradd/i,
|
|
4047
|
-
/userdel/i,
|
|
4048
|
-
/chmod\s+777/i,
|
|
4049
|
-
/chown/i,
|
|
4050
|
-
/sudo/i,
|
|
4051
|
-
/su\s+-/i,
|
|
4052
|
-
/nc\s+-e/i,
|
|
4053
|
-
/bash\s+-i/i,
|
|
4054
|
-
/reverse.*shell/i,
|
|
4055
|
-
/bind.*shell/i,
|
|
4056
|
-
/meterpreter/i,
|
|
4057
|
-
/mimikatz/i
|
|
4058
|
-
];
|
|
4059
|
-
function assessRisk(toolName, toolInput) {
|
|
4060
|
-
const inputStr = JSON.stringify(toolInput).toLowerCase();
|
|
4061
|
-
for (const pattern of HIGH_RISK_PATTERNS) {
|
|
4062
|
-
if (pattern.test(inputStr)) {
|
|
4063
|
-
return "critical";
|
|
4064
|
-
}
|
|
4065
|
-
}
|
|
4066
|
-
if (CRITICAL_TOOLS.includes(toolName)) {
|
|
4067
|
-
return "high";
|
|
4068
|
-
}
|
|
4069
|
-
if (toolName.includes("script") || toolName.includes("exec")) {
|
|
4070
|
-
return "medium";
|
|
4071
|
-
}
|
|
4072
|
-
if (toolName.includes("scan") || toolName.includes("request")) {
|
|
4073
|
-
return "medium";
|
|
4074
|
-
}
|
|
4075
|
-
return "low";
|
|
4076
|
-
}
|
|
4077
|
-
function generateRequestId() {
|
|
4078
|
-
return `approval_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
4079
|
-
}
|
|
4080
|
-
var ApprovalManager = class extends EventEmitter5 {
|
|
4081
|
-
pendingRequests = /* @__PURE__ */ new Map();
|
|
4082
|
-
autoApprovedTools = /* @__PURE__ */ new Set();
|
|
4083
|
-
autoDeniedTools = /* @__PURE__ */ new Set();
|
|
4084
|
-
yoloMode = false;
|
|
4085
|
-
defaultTimeout = 6e4;
|
|
4086
|
-
// 1 minute
|
|
4087
|
-
constructor(options) {
|
|
4088
|
-
super();
|
|
4089
|
-
this.yoloMode = options?.yoloMode ?? false;
|
|
4090
|
-
this.defaultTimeout = options?.timeout ?? 6e4;
|
|
4091
|
-
}
|
|
4092
|
-
/**
|
|
4093
|
-
* Enable/disable YOLO mode (auto-approve everything)
|
|
4094
|
-
*/
|
|
4095
|
-
setYoloMode(enabled) {
|
|
4096
|
-
this.yoloMode = enabled;
|
|
4097
|
-
this.emit("yolo_mode_changed", enabled);
|
|
4098
|
-
}
|
|
4099
|
-
/**
|
|
4100
|
-
* Check if approval is required for a tool call
|
|
4101
|
-
*/
|
|
4102
|
-
requiresApproval(toolName, toolInput) {
|
|
4103
|
-
if (this.yoloMode) return false;
|
|
4104
|
-
if (this.autoApprovedTools.has(toolName)) return false;
|
|
4105
|
-
if (this.autoDeniedTools.has(toolName)) return true;
|
|
4106
|
-
const risk = assessRisk(toolName, toolInput);
|
|
4107
|
-
if (risk === "low") return false;
|
|
4108
|
-
return true;
|
|
4109
|
-
}
|
|
4110
|
-
/**
|
|
4111
|
-
* Request approval for a tool call
|
|
4112
|
-
*/
|
|
4113
|
-
async requestApproval(toolName, toolInput, reason) {
|
|
4114
|
-
if (this.autoDeniedTools.has(toolName)) {
|
|
4115
|
-
return "deny";
|
|
4116
|
-
}
|
|
4117
|
-
if (this.autoApprovedTools.has(toolName)) {
|
|
4118
|
-
return "approve";
|
|
4119
|
-
}
|
|
4120
|
-
const risk = assessRisk(toolName, toolInput);
|
|
4121
|
-
const request = {
|
|
4122
|
-
id: generateRequestId(),
|
|
4123
|
-
toolName,
|
|
4124
|
-
toolInput,
|
|
4125
|
-
reason: reason || `Tool "${toolName}" requires approval (${risk} risk)`,
|
|
4126
|
-
riskLevel: risk,
|
|
4127
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4128
|
-
};
|
|
4129
|
-
this.pendingRequests.set(request.id, request);
|
|
4130
|
-
this.emit(APPROVAL_EVENT.REQUEST, request);
|
|
4131
|
-
return new Promise((resolve) => {
|
|
4132
|
-
const timeout = setTimeout(() => {
|
|
4133
|
-
this.pendingRequests.delete(request.id);
|
|
4134
|
-
this.emit(APPROVAL_EVENT.TIMEOUT, request.id);
|
|
4135
|
-
resolve("deny");
|
|
4136
|
-
}, this.defaultTimeout);
|
|
4137
|
-
const responseHandler = (response) => {
|
|
4138
|
-
if (response.requestId === request.id) {
|
|
4139
|
-
clearTimeout(timeout);
|
|
4140
|
-
this.pendingRequests.delete(request.id);
|
|
4141
|
-
this.removeListener(APPROVAL_EVENT.RESPONSE, responseHandler);
|
|
4142
|
-
if (response.decision === "approve_always") {
|
|
4143
|
-
this.autoApprovedTools.add(toolName);
|
|
4144
|
-
resolve("approve");
|
|
4145
|
-
} else if (response.decision === "deny_always") {
|
|
4146
|
-
this.autoDeniedTools.add(toolName);
|
|
4147
|
-
resolve("deny");
|
|
4148
|
-
} else {
|
|
4149
|
-
resolve(response.decision);
|
|
4150
|
-
}
|
|
4151
|
-
}
|
|
4152
|
-
};
|
|
4153
|
-
this.on(APPROVAL_EVENT.RESPONSE, responseHandler);
|
|
4154
|
-
});
|
|
4155
|
-
}
|
|
4156
|
-
/**
|
|
4157
|
-
* Respond to an approval request (called by UI)
|
|
4158
|
-
*/
|
|
4159
|
-
respond(requestId, decision) {
|
|
4160
|
-
const response = {
|
|
4161
|
-
requestId,
|
|
4162
|
-
decision,
|
|
4163
|
-
respondedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4164
|
-
};
|
|
4165
|
-
this.emit(APPROVAL_EVENT.RESPONSE, response);
|
|
4166
|
-
}
|
|
4167
|
-
/**
|
|
4168
|
-
* Get pending requests
|
|
4169
|
-
*/
|
|
4170
|
-
getPendingRequests() {
|
|
4171
|
-
return Array.from(this.pendingRequests.values());
|
|
4172
|
-
}
|
|
4173
|
-
/**
|
|
4174
|
-
* Get auto-approved tools
|
|
4175
|
-
*/
|
|
4176
|
-
getAutoApprovedTools() {
|
|
4177
|
-
return Array.from(this.autoApprovedTools);
|
|
4178
|
-
}
|
|
4179
|
-
/**
|
|
4180
|
-
* Reset all auto decisions
|
|
4181
|
-
*/
|
|
4182
|
-
resetAutoDecisions() {
|
|
4183
|
-
this.autoApprovedTools.clear();
|
|
4184
|
-
this.autoDeniedTools.clear();
|
|
4185
|
-
}
|
|
4186
|
-
};
|
|
4187
|
-
var approvalManager = null;
|
|
4188
|
-
function getApprovalManager(options) {
|
|
4189
|
-
if (!approvalManager) {
|
|
4190
|
-
approvalManager = new ApprovalManager(options);
|
|
4191
|
-
}
|
|
4192
|
-
return approvalManager;
|
|
4193
|
-
}
|
|
4194
|
-
|
|
4195
4234
|
// src/config/theme.ts
|
|
4196
4235
|
var THEME = {
|
|
4197
4236
|
// Primary backgrounds (dark purple tones)
|
|
@@ -4287,6 +4326,7 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
4287
4326
|
const [currentStatus, setCurrentStatus] = useState("");
|
|
4288
4327
|
const [elapsedTime, setElapsedTime] = useState(0);
|
|
4289
4328
|
const [pendingApproval, setPendingApproval] = useState(null);
|
|
4329
|
+
const [tokenUsage, setTokenUsage] = useState({ input: 0, output: 0, total: 0 });
|
|
4290
4330
|
const [agent] = useState(() => new AutonomousHackingAgent(void 0, { autoApprove }));
|
|
4291
4331
|
const sessionManager2 = getSessionManager();
|
|
4292
4332
|
const approvalManager2 = getApprovalManager({ yoloMode: autoApprove });
|
|
@@ -4350,6 +4390,18 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
4350
4390
|
agent.on(AGENT_EVENT.CONTEXT_COMPACTED, () => {
|
|
4351
4391
|
addMessage(MESSAGE_TYPE.SYSTEM, "\u{1F4BE} Context compacted to save tokens");
|
|
4352
4392
|
});
|
|
4393
|
+
agent.on(AGENT_EVENT.TOKEN_USAGE, (usage) => {
|
|
4394
|
+
setTokenUsage(usage);
|
|
4395
|
+
});
|
|
4396
|
+
agent.on(AGENT_EVENT.APPROVAL_NEEDED, (data) => {
|
|
4397
|
+
setPendingApproval({
|
|
4398
|
+
id: data.id,
|
|
4399
|
+
toolName: data.toolName,
|
|
4400
|
+
riskLevel: data.riskLevel
|
|
4401
|
+
});
|
|
4402
|
+
addMessage(MESSAGE_TYPE.SYSTEM, `\u26A0\uFE0F APPROVAL NEEDED: ${data.toolName} (${data.riskLevel} risk)`);
|
|
4403
|
+
addMessage(MESSAGE_TYPE.SYSTEM, " Type /approve or /deny");
|
|
4404
|
+
});
|
|
4353
4405
|
agent.on(AGENT_EVENT.COMPLETE, () => {
|
|
4354
4406
|
const duration = stopTimer();
|
|
4355
4407
|
addMessage(MESSAGE_TYPE.SYSTEM, `\u2713 Complete (${duration}s)`);
|
|
@@ -4622,6 +4674,7 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
4622
4674
|
" findings \u2502",
|
|
4623
4675
|
state.credentials.length,
|
|
4624
4676
|
" creds \u2502",
|
|
4677
|
+
tokenUsage.total > 0 && `${(tokenUsage.total / 1e3).toFixed(1)}k tokens \u2502`,
|
|
4625
4678
|
state.currentPhase !== AGENT_STATUS.IDLE && ` ${state.currentPhase} \u2502`
|
|
4626
4679
|
] }),
|
|
4627
4680
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|