pentesting 0.21.9 → 0.21.10
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 +3 -0
- package/dist/main.js +179 -43
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/main.js
CHANGED
|
@@ -157,7 +157,7 @@ var EXIT_CODES = {
|
|
|
157
157
|
var ID_LENGTH = AGENT_LIMITS.ID_LENGTH;
|
|
158
158
|
var ID_RADIX = AGENT_LIMITS.ID_RADIX;
|
|
159
159
|
var APP_NAME = "Pentest AI";
|
|
160
|
-
var APP_VERSION = "0.21.
|
|
160
|
+
var APP_VERSION = "0.21.10";
|
|
161
161
|
var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
|
|
162
162
|
var LLM_ROLES = {
|
|
163
163
|
SYSTEM: "system",
|
|
@@ -2995,12 +2995,57 @@ var SEARCH_LIMIT = {
|
|
|
2995
2995
|
// src/shared/utils/debug-logger.ts
|
|
2996
2996
|
import { appendFileSync as appendFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
2997
2997
|
import { join as join2 } from "path";
|
|
2998
|
+
|
|
2999
|
+
// src/shared/constants/paths.ts
|
|
3000
|
+
import path2 from "path";
|
|
3001
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3002
|
+
import { homedir } from "os";
|
|
3003
|
+
var __filename2 = fileURLToPath2(import.meta.url);
|
|
3004
|
+
var __dirname2 = path2.dirname(__filename2);
|
|
3005
|
+
var PROJECT_ROOT = path2.resolve(__dirname2, "../../../");
|
|
3006
|
+
var WORKSPACE_DIR_NAME = ".pentesting";
|
|
3007
|
+
function getWorkspaceRoot() {
|
|
3008
|
+
return path2.join(homedir(), WORKSPACE_DIR_NAME);
|
|
3009
|
+
}
|
|
3010
|
+
var WORKSPACE = {
|
|
3011
|
+
/** Root directory (resolved lazily via getWorkspaceRoot) */
|
|
3012
|
+
get ROOT() {
|
|
3013
|
+
return getWorkspaceRoot();
|
|
3014
|
+
},
|
|
3015
|
+
/** Per-session state snapshots */
|
|
3016
|
+
get SESSIONS() {
|
|
3017
|
+
return path2.join(getWorkspaceRoot(), "sessions");
|
|
3018
|
+
},
|
|
3019
|
+
/** Debug logs */
|
|
3020
|
+
get DEBUG() {
|
|
3021
|
+
return path2.join(getWorkspaceRoot(), "debug");
|
|
3022
|
+
},
|
|
3023
|
+
/** Generated reports */
|
|
3024
|
+
get REPORTS() {
|
|
3025
|
+
return path2.join(getWorkspaceRoot(), "reports");
|
|
3026
|
+
},
|
|
3027
|
+
/** Downloaded loot, captured files */
|
|
3028
|
+
get LOOT() {
|
|
3029
|
+
return path2.join(getWorkspaceRoot(), "loot");
|
|
3030
|
+
},
|
|
3031
|
+
/** Temporary files for active operations */
|
|
3032
|
+
get TEMP() {
|
|
3033
|
+
return path2.join(getWorkspaceRoot(), "temp");
|
|
3034
|
+
}
|
|
3035
|
+
};
|
|
3036
|
+
var PATHS = {
|
|
3037
|
+
ROOT: PROJECT_ROOT,
|
|
3038
|
+
SRC: path2.join(PROJECT_ROOT, "src"),
|
|
3039
|
+
DIST: path2.join(PROJECT_ROOT, "dist")
|
|
3040
|
+
};
|
|
3041
|
+
|
|
3042
|
+
// src/shared/utils/debug-logger.ts
|
|
2998
3043
|
var DebugLogger = class _DebugLogger {
|
|
2999
3044
|
static instance;
|
|
3000
3045
|
logPath;
|
|
3001
3046
|
initialized = false;
|
|
3002
3047
|
constructor(clearOnInit = false) {
|
|
3003
|
-
const debugDir =
|
|
3048
|
+
const debugDir = WORKSPACE.DEBUG;
|
|
3004
3049
|
try {
|
|
3005
3050
|
ensureDirExists(debugDir);
|
|
3006
3051
|
this.logPath = join2(debugDir, "debug.log");
|
|
@@ -3071,7 +3116,8 @@ function debugLog(category, message, data) {
|
|
|
3071
3116
|
}
|
|
3072
3117
|
|
|
3073
3118
|
// src/engine/tools/web-browser.ts
|
|
3074
|
-
import { join as join5
|
|
3119
|
+
import { join as join5 } from "path";
|
|
3120
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
3075
3121
|
|
|
3076
3122
|
// src/shared/constants/browser/config.ts
|
|
3077
3123
|
var BROWSER_CONFIG = {
|
|
@@ -3188,7 +3234,8 @@ async function installPlaywright() {
|
|
|
3188
3234
|
// src/engine/tools/web-browser-script.ts
|
|
3189
3235
|
import { spawn as spawn4 } from "child_process";
|
|
3190
3236
|
import { writeFileSync as writeFileSync4, unlinkSync as unlinkSync2 } from "fs";
|
|
3191
|
-
import { join as join4
|
|
3237
|
+
import { join as join4 } from "path";
|
|
3238
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
3192
3239
|
function safeJsString(str) {
|
|
3193
3240
|
return JSON.stringify(str);
|
|
3194
3241
|
}
|
|
@@ -4683,8 +4730,8 @@ Returns: All available wordlists with their paths, sizes, and categories.`,
|
|
|
4683
4730
|
}
|
|
4684
4731
|
},
|
|
4685
4732
|
execute: async (p) => {
|
|
4686
|
-
const { existsSync:
|
|
4687
|
-
const { join:
|
|
4733
|
+
const { existsSync: existsSync7, statSync: statSync2, readdirSync: readdirSync3 } = await import("fs");
|
|
4734
|
+
const { join: join10 } = await import("path");
|
|
4688
4735
|
const category = p.category || "";
|
|
4689
4736
|
const search = p.search || "";
|
|
4690
4737
|
const minSize = p.min_size || 0;
|
|
@@ -4699,11 +4746,11 @@ Returns: All available wordlists with their paths, sizes, and categories.`,
|
|
|
4699
4746
|
let totalCount = 0;
|
|
4700
4747
|
const scanDir = (dirPath, maxDepth = 3, currentDepth = 0) => {
|
|
4701
4748
|
if (currentDepth > maxDepth) return;
|
|
4702
|
-
if (!
|
|
4749
|
+
if (!existsSync7(dirPath)) return;
|
|
4703
4750
|
try {
|
|
4704
|
-
const entries =
|
|
4751
|
+
const entries = readdirSync3(dirPath, { withFileTypes: true });
|
|
4705
4752
|
for (const entry of entries) {
|
|
4706
|
-
const fullPath =
|
|
4753
|
+
const fullPath = join10(dirPath, entry.name);
|
|
4707
4754
|
if (entry.isDirectory()) {
|
|
4708
4755
|
if (entry.name.startsWith(".")) continue;
|
|
4709
4756
|
if (entry.name === "doc") continue;
|
|
@@ -4714,7 +4761,7 @@ Returns: All available wordlists with their paths, sizes, and categories.`,
|
|
|
4714
4761
|
continue;
|
|
4715
4762
|
}
|
|
4716
4763
|
try {
|
|
4717
|
-
const stats =
|
|
4764
|
+
const stats = statSync2(fullPath);
|
|
4718
4765
|
const sizeBytes = stats.size;
|
|
4719
4766
|
if (sizeBytes < minSize) continue;
|
|
4720
4767
|
const relPath = fullPath;
|
|
@@ -5124,8 +5171,8 @@ Requires root/sudo privileges.`,
|
|
|
5124
5171
|
const iface = p.interface || "";
|
|
5125
5172
|
const duration = p.duration || NETWORK_CONFIG.DEFAULT_SPOOF_DURATION;
|
|
5126
5173
|
const hostsFile = createTempFile(".hosts");
|
|
5127
|
-
const { writeFileSync:
|
|
5128
|
-
|
|
5174
|
+
const { writeFileSync: writeFileSync6 } = await import("fs");
|
|
5175
|
+
writeFileSync6(hostsFile, `${spoofIp} ${domain}
|
|
5129
5176
|
${spoofIp} *.${domain}
|
|
5130
5177
|
`);
|
|
5131
5178
|
const ifaceFlag = iface ? `-i ${iface}` : "";
|
|
@@ -5828,80 +5875,80 @@ var ServiceParser = class {
|
|
|
5828
5875
|
|
|
5829
5876
|
// src/domains/registry.ts
|
|
5830
5877
|
import { join as join6, dirname as dirname3 } from "path";
|
|
5831
|
-
import { fileURLToPath as
|
|
5832
|
-
var
|
|
5878
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
5879
|
+
var __dirname3 = dirname3(fileURLToPath3(import.meta.url));
|
|
5833
5880
|
var DOMAINS = {
|
|
5834
5881
|
[SERVICE_CATEGORIES.NETWORK]: {
|
|
5835
5882
|
id: SERVICE_CATEGORIES.NETWORK,
|
|
5836
5883
|
name: "Network Infrastructure",
|
|
5837
5884
|
description: "Vulnerability scanning, port mapping, and network service exploitation.",
|
|
5838
|
-
promptPath: join6(
|
|
5885
|
+
promptPath: join6(__dirname3, "network/prompt.md")
|
|
5839
5886
|
},
|
|
5840
5887
|
[SERVICE_CATEGORIES.WEB]: {
|
|
5841
5888
|
id: SERVICE_CATEGORIES.WEB,
|
|
5842
5889
|
name: "Web Application",
|
|
5843
5890
|
description: "Web app security testing, injection attacks, and auth bypass.",
|
|
5844
|
-
promptPath: join6(
|
|
5891
|
+
promptPath: join6(__dirname3, "web/prompt.md")
|
|
5845
5892
|
},
|
|
5846
5893
|
[SERVICE_CATEGORIES.DATABASE]: {
|
|
5847
5894
|
id: SERVICE_CATEGORIES.DATABASE,
|
|
5848
5895
|
name: "Database Security",
|
|
5849
5896
|
description: "SQL injection, database enumeration, and data extraction.",
|
|
5850
|
-
promptPath: join6(
|
|
5897
|
+
promptPath: join6(__dirname3, "database/prompt.md")
|
|
5851
5898
|
},
|
|
5852
5899
|
[SERVICE_CATEGORIES.AD]: {
|
|
5853
5900
|
id: SERVICE_CATEGORIES.AD,
|
|
5854
5901
|
name: "Active Directory",
|
|
5855
5902
|
description: "Kerberos, LDAP, and Windows domain privilege escalation.",
|
|
5856
|
-
promptPath: join6(
|
|
5903
|
+
promptPath: join6(__dirname3, "ad/prompt.md")
|
|
5857
5904
|
},
|
|
5858
5905
|
[SERVICE_CATEGORIES.EMAIL]: {
|
|
5859
5906
|
id: SERVICE_CATEGORIES.EMAIL,
|
|
5860
5907
|
name: "Email Services",
|
|
5861
5908
|
description: "SMTP, IMAP, POP3 security and user enumeration.",
|
|
5862
|
-
promptPath: join6(
|
|
5909
|
+
promptPath: join6(__dirname3, "email/prompt.md")
|
|
5863
5910
|
},
|
|
5864
5911
|
[SERVICE_CATEGORIES.REMOTE_ACCESS]: {
|
|
5865
5912
|
id: SERVICE_CATEGORIES.REMOTE_ACCESS,
|
|
5866
5913
|
name: "Remote Access",
|
|
5867
5914
|
description: "SSH, RDP, VNC and other remote control protocols.",
|
|
5868
|
-
promptPath: join6(
|
|
5915
|
+
promptPath: join6(__dirname3, "remote-access/prompt.md")
|
|
5869
5916
|
},
|
|
5870
5917
|
[SERVICE_CATEGORIES.FILE_SHARING]: {
|
|
5871
5918
|
id: SERVICE_CATEGORIES.FILE_SHARING,
|
|
5872
5919
|
name: "File Sharing",
|
|
5873
5920
|
description: "SMB, NFS, FTP and shared resource security.",
|
|
5874
|
-
promptPath: join6(
|
|
5921
|
+
promptPath: join6(__dirname3, "file-sharing/prompt.md")
|
|
5875
5922
|
},
|
|
5876
5923
|
[SERVICE_CATEGORIES.CLOUD]: {
|
|
5877
5924
|
id: SERVICE_CATEGORIES.CLOUD,
|
|
5878
5925
|
name: "Cloud Infrastructure",
|
|
5879
5926
|
description: "AWS, Azure, and GCP security and misconfiguration.",
|
|
5880
|
-
promptPath: join6(
|
|
5927
|
+
promptPath: join6(__dirname3, "cloud/prompt.md")
|
|
5881
5928
|
},
|
|
5882
5929
|
[SERVICE_CATEGORIES.CONTAINER]: {
|
|
5883
5930
|
id: SERVICE_CATEGORIES.CONTAINER,
|
|
5884
5931
|
name: "Container Systems",
|
|
5885
5932
|
description: "Docker and Kubernetes security testing.",
|
|
5886
|
-
promptPath: join6(
|
|
5933
|
+
promptPath: join6(__dirname3, "container/prompt.md")
|
|
5887
5934
|
},
|
|
5888
5935
|
[SERVICE_CATEGORIES.API]: {
|
|
5889
5936
|
id: SERVICE_CATEGORIES.API,
|
|
5890
5937
|
name: "API Security",
|
|
5891
5938
|
description: "REST, GraphQL, and SOAP API security testing.",
|
|
5892
|
-
promptPath: join6(
|
|
5939
|
+
promptPath: join6(__dirname3, "api/prompt.md")
|
|
5893
5940
|
},
|
|
5894
5941
|
[SERVICE_CATEGORIES.WIRELESS]: {
|
|
5895
5942
|
id: SERVICE_CATEGORIES.WIRELESS,
|
|
5896
5943
|
name: "Wireless Networks",
|
|
5897
5944
|
description: "WiFi and Bluetooth security testing.",
|
|
5898
|
-
promptPath: join6(
|
|
5945
|
+
promptPath: join6(__dirname3, "wireless/prompt.md")
|
|
5899
5946
|
},
|
|
5900
5947
|
[SERVICE_CATEGORIES.ICS]: {
|
|
5901
5948
|
id: SERVICE_CATEGORIES.ICS,
|
|
5902
5949
|
name: "Industrial Systems",
|
|
5903
5950
|
description: "Critical infrastructure - Modbus, DNP3, ENIP.",
|
|
5904
|
-
promptPath: join6(
|
|
5951
|
+
promptPath: join6(__dirname3, "ics/prompt.md")
|
|
5905
5952
|
}
|
|
5906
5953
|
};
|
|
5907
5954
|
|
|
@@ -6681,10 +6728,77 @@ function logLLM(message, data) {
|
|
|
6681
6728
|
}
|
|
6682
6729
|
|
|
6683
6730
|
// src/engine/orchestrator/orchestrator.ts
|
|
6684
|
-
import { fileURLToPath as
|
|
6731
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
6685
6732
|
import { dirname as dirname4, join as join7 } from "path";
|
|
6686
|
-
var
|
|
6687
|
-
var
|
|
6733
|
+
var __filename3 = fileURLToPath4(import.meta.url);
|
|
6734
|
+
var __dirname4 = dirname4(__filename3);
|
|
6735
|
+
|
|
6736
|
+
// src/engine/state-persistence.ts
|
|
6737
|
+
import { writeFileSync as writeFileSync5, readFileSync as readFileSync3, existsSync as existsSync5, readdirSync, statSync } from "fs";
|
|
6738
|
+
import { join as join8, basename } from "path";
|
|
6739
|
+
function saveState(state) {
|
|
6740
|
+
const sessionsDir = WORKSPACE.SESSIONS;
|
|
6741
|
+
ensureDirExists(sessionsDir);
|
|
6742
|
+
const snapshot = {
|
|
6743
|
+
version: 1,
|
|
6744
|
+
savedAt: Date.now(),
|
|
6745
|
+
engagement: state.getEngagement(),
|
|
6746
|
+
targets: Array.from(state.getTargets().entries()).map(([key, value]) => ({ key, value })),
|
|
6747
|
+
findings: state.getFindings(),
|
|
6748
|
+
loot: state.getLoot(),
|
|
6749
|
+
todo: state.getTodo(),
|
|
6750
|
+
actionLog: state.getRecentActions(9999),
|
|
6751
|
+
currentPhase: state.getPhase(),
|
|
6752
|
+
missionSummary: state.getMissionSummary(),
|
|
6753
|
+
missionChecklist: state.getMissionChecklist()
|
|
6754
|
+
};
|
|
6755
|
+
const sessionId = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
6756
|
+
const sessionFile = join8(sessionsDir, `${sessionId}.json`);
|
|
6757
|
+
writeFileSync5(sessionFile, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
6758
|
+
const latestFile = join8(sessionsDir, "latest.json");
|
|
6759
|
+
writeFileSync5(latestFile, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
6760
|
+
return sessionFile;
|
|
6761
|
+
}
|
|
6762
|
+
function loadState(state) {
|
|
6763
|
+
const latestFile = join8(WORKSPACE.SESSIONS, "latest.json");
|
|
6764
|
+
if (!existsSync5(latestFile)) {
|
|
6765
|
+
return false;
|
|
6766
|
+
}
|
|
6767
|
+
try {
|
|
6768
|
+
const raw = readFileSync3(latestFile, "utf-8");
|
|
6769
|
+
const snapshot = JSON.parse(raw);
|
|
6770
|
+
if (snapshot.version !== 1) {
|
|
6771
|
+
console.warn(`[StatePersistence] Unknown snapshot version: ${snapshot.version}`);
|
|
6772
|
+
return false;
|
|
6773
|
+
}
|
|
6774
|
+
if (snapshot.engagement) {
|
|
6775
|
+
state.setEngagement(snapshot.engagement);
|
|
6776
|
+
}
|
|
6777
|
+
for (const { value } of snapshot.targets) {
|
|
6778
|
+
state.addTarget(value);
|
|
6779
|
+
}
|
|
6780
|
+
for (const finding of snapshot.findings) {
|
|
6781
|
+
state.addFinding(finding);
|
|
6782
|
+
}
|
|
6783
|
+
for (const loot of snapshot.loot) {
|
|
6784
|
+
state.addLoot(loot);
|
|
6785
|
+
}
|
|
6786
|
+
for (const item of snapshot.todo) {
|
|
6787
|
+
state.addTodo(item.content, item.priority);
|
|
6788
|
+
}
|
|
6789
|
+
state.setPhase(snapshot.currentPhase);
|
|
6790
|
+
if (snapshot.missionSummary) {
|
|
6791
|
+
state.setMissionSummary(snapshot.missionSummary);
|
|
6792
|
+
}
|
|
6793
|
+
if (snapshot.missionChecklist?.length > 0) {
|
|
6794
|
+
state.addMissionChecklistItems(snapshot.missionChecklist.map((c) => c.text));
|
|
6795
|
+
}
|
|
6796
|
+
return true;
|
|
6797
|
+
} catch (err) {
|
|
6798
|
+
console.warn(`[StatePersistence] Failed to load state: ${err}`);
|
|
6799
|
+
return false;
|
|
6800
|
+
}
|
|
6801
|
+
}
|
|
6688
6802
|
|
|
6689
6803
|
// src/agents/core-agent.ts
|
|
6690
6804
|
var CoreAgent = class _CoreAgent {
|
|
@@ -7213,9 +7327,9 @@ Please decide how to handle this error and continue.`;
|
|
|
7213
7327
|
};
|
|
7214
7328
|
|
|
7215
7329
|
// src/agents/prompt-builder.ts
|
|
7216
|
-
import { readFileSync as
|
|
7217
|
-
import { join as
|
|
7218
|
-
import { fileURLToPath as
|
|
7330
|
+
import { readFileSync as readFileSync4, existsSync as existsSync6 } from "fs";
|
|
7331
|
+
import { join as join9, dirname as dirname5 } from "path";
|
|
7332
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
7219
7333
|
|
|
7220
7334
|
// src/shared/constants/prompts.ts
|
|
7221
7335
|
var PROMPT_PATHS = {
|
|
@@ -7268,9 +7382,9 @@ var INITIAL_TASKS = {
|
|
|
7268
7382
|
};
|
|
7269
7383
|
|
|
7270
7384
|
// src/agents/prompt-builder.ts
|
|
7271
|
-
var
|
|
7272
|
-
var PROMPTS_DIR =
|
|
7273
|
-
var TECHNIQUES_DIR =
|
|
7385
|
+
var __dirname5 = dirname5(fileURLToPath5(import.meta.url));
|
|
7386
|
+
var PROMPTS_DIR = join9(__dirname5, "prompts");
|
|
7387
|
+
var TECHNIQUES_DIR = join9(PROMPTS_DIR, PROMPT_PATHS.TECHNIQUES_DIR);
|
|
7274
7388
|
var { AGENT_FILES } = PROMPT_PATHS;
|
|
7275
7389
|
var PHASE_PROMPT_MAP = {
|
|
7276
7390
|
// Direct mappings — phase has its own prompt file
|
|
@@ -7346,8 +7460,8 @@ var PromptBuilder = class {
|
|
|
7346
7460
|
* Load a prompt file from src/agents/prompts/
|
|
7347
7461
|
*/
|
|
7348
7462
|
loadPromptFile(filename) {
|
|
7349
|
-
const
|
|
7350
|
-
return
|
|
7463
|
+
const path3 = join9(PROMPTS_DIR, filename);
|
|
7464
|
+
return existsSync6(path3) ? readFileSync4(path3, PROMPT_CONFIG.ENCODING) : "";
|
|
7351
7465
|
}
|
|
7352
7466
|
/**
|
|
7353
7467
|
* Load phase-specific prompt.
|
|
@@ -7390,15 +7504,15 @@ ${content}
|
|
|
7390
7504
|
* use web_search to look up specific attack techniques on demand.
|
|
7391
7505
|
*/
|
|
7392
7506
|
loadPhaseRelevantTechniques(phase) {
|
|
7393
|
-
if (!
|
|
7507
|
+
if (!existsSync6(TECHNIQUES_DIR)) return "";
|
|
7394
7508
|
const relevantTechniques = PHASE_TECHNIQUE_MAP[phase] || [];
|
|
7395
7509
|
if (relevantTechniques.length === 0) return "";
|
|
7396
7510
|
const fragments = [];
|
|
7397
7511
|
for (const technique of relevantTechniques) {
|
|
7398
|
-
const filePath =
|
|
7512
|
+
const filePath = join9(TECHNIQUES_DIR, `${technique}.md`);
|
|
7399
7513
|
try {
|
|
7400
|
-
if (!
|
|
7401
|
-
const content =
|
|
7514
|
+
if (!existsSync6(filePath)) continue;
|
|
7515
|
+
const content = readFileSync4(filePath, PROMPT_CONFIG.ENCODING);
|
|
7402
7516
|
if (content) {
|
|
7403
7517
|
fragments.push(`<technique-reference category="${technique}">
|
|
7404
7518
|
${content}
|
|
@@ -7454,6 +7568,10 @@ var MainAgent = class extends CoreAgent {
|
|
|
7454
7568
|
const result2 = await this.run(userInput, this.getCurrentPrompt());
|
|
7455
7569
|
return result2.output;
|
|
7456
7570
|
} finally {
|
|
7571
|
+
try {
|
|
7572
|
+
saveState(this.state);
|
|
7573
|
+
} catch {
|
|
7574
|
+
}
|
|
7457
7575
|
await cleanupAllProcesses();
|
|
7458
7576
|
}
|
|
7459
7577
|
}
|
|
@@ -7472,10 +7590,28 @@ var MainAgent = class extends CoreAgent {
|
|
|
7472
7590
|
}
|
|
7473
7591
|
// ─── Internal Helpers ────────────────────────────────────────
|
|
7474
7592
|
initializeTask() {
|
|
7593
|
+
try {
|
|
7594
|
+
ensureDirExists(WORKSPACE.ROOT);
|
|
7595
|
+
} catch {
|
|
7596
|
+
}
|
|
7475
7597
|
if (this.state.getTodo().length === 0) {
|
|
7476
7598
|
this.state.addTodo(INITIAL_TASKS.RECON, PRIORITIES.HIGH);
|
|
7477
7599
|
}
|
|
7478
7600
|
}
|
|
7601
|
+
/**
|
|
7602
|
+
* Load previous session state from .pentesting/sessions/latest.json
|
|
7603
|
+
* @returns true if a previous session was restored
|
|
7604
|
+
*/
|
|
7605
|
+
loadPreviousSession() {
|
|
7606
|
+
return loadState(this.state);
|
|
7607
|
+
}
|
|
7608
|
+
/**
|
|
7609
|
+
* Manually save current state to .pentesting/sessions/
|
|
7610
|
+
* @returns Path to the saved session file
|
|
7611
|
+
*/
|
|
7612
|
+
saveCurrentState() {
|
|
7613
|
+
return saveState(this.state);
|
|
7614
|
+
}
|
|
7479
7615
|
getCurrentPrompt() {
|
|
7480
7616
|
const phase = this.state.getPhase() || PHASES.RECON;
|
|
7481
7617
|
return this.promptBuilder.build(this.userInput, phase);
|
|
@@ -8028,7 +8164,7 @@ var useAgentEvents = (agent, eventsRef, state) => {
|
|
|
8028
8164
|
isPassword,
|
|
8029
8165
|
inputType: request.type,
|
|
8030
8166
|
context: request.context,
|
|
8031
|
-
optional: request.
|
|
8167
|
+
optional: request.isOptional,
|
|
8032
8168
|
options: request.options,
|
|
8033
8169
|
resolve
|
|
8034
8170
|
});
|
|
@@ -8123,7 +8259,7 @@ function buildCredentialPrompt(request) {
|
|
|
8123
8259
|
displayPrompt = `${displayPrompt}
|
|
8124
8260
|
Context: ${request.context}`;
|
|
8125
8261
|
}
|
|
8126
|
-
if (request.
|
|
8262
|
+
if (request.isOptional) {
|
|
8127
8263
|
displayPrompt += " (optional - press Enter to skip)";
|
|
8128
8264
|
}
|
|
8129
8265
|
if (request.options && request.options.length > 0) {
|