pentesting 0.4.9 → 0.5.3

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.
@@ -8,8 +8,8 @@ import {
8
8
  readVersionCache,
9
9
  semverTuple,
10
10
  writeVersionCache
11
- } from "./chunk-L4MURCOP.js";
12
- import "./chunk-X3X45KYT.js";
11
+ } from "./chunk-ZC53SMRU.js";
12
+ import "./chunk-FHPP7RP2.js";
13
13
  import "./chunk-3RG5ZIWI.js";
14
14
  export {
15
15
  checkForUpdate,
@@ -132,7 +132,7 @@ var SENSITIVE_TOOLS = [
132
132
 
133
133
  // src/config/constants.ts
134
134
  var APP_NAME = "pentesting";
135
- var APP_VERSION = "0.4.9";
135
+ var APP_VERSION = "0.5.1";
136
136
  var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
137
137
  var LLM_API_KEY = process.env.PENTEST_API_KEY || process.env.ANTHROPIC_API_KEY || "";
138
138
  var LLM_BASE_URL = process.env.PENTEST_BASE_URL || void 0;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  APP_NAME,
3
3
  APP_VERSION
4
- } from "./chunk-X3X45KYT.js";
4
+ } from "./chunk-FHPP7RP2.js";
5
5
 
6
6
  // src/core/update/auto-update.ts
7
7
  import { execSync } from "child_process";
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  PHASE_STATUS,
16
16
  THOUGHT_TYPE,
17
17
  TOOL_NAME
18
- } from "./chunk-X3X45KYT.js";
18
+ } from "./chunk-FHPP7RP2.js";
19
19
  import {
20
20
  __require
21
21
  } from "./chunk-3RG5ZIWI.js";
@@ -1723,9 +1723,27 @@ var ApprovalManager = class extends EventEmitter3 {
1723
1723
  this.removeListener(APPROVAL_EVENT.RESPONSE, responseHandler);
1724
1724
  if (response.decision === "approve_always") {
1725
1725
  this.autoApprovedTools.add(toolName);
1726
+ const pendingForSameTool = Array.from(this.pendingRequests.entries()).filter(([_, req]) => req.toolName === toolName);
1727
+ for (const [pendingId, _] of pendingForSameTool) {
1728
+ this.pendingRequests.delete(pendingId);
1729
+ this.emit(APPROVAL_EVENT.RESPONSE, {
1730
+ requestId: pendingId,
1731
+ decision: "approve",
1732
+ respondedAt: (/* @__PURE__ */ new Date()).toISOString()
1733
+ });
1734
+ }
1726
1735
  resolve("approve");
1727
1736
  } else if (response.decision === "deny_always") {
1728
1737
  this.autoDeniedTools.add(toolName);
1738
+ const pendingForSameTool = Array.from(this.pendingRequests.entries()).filter(([_, req]) => req.toolName === toolName);
1739
+ for (const [pendingId, _] of pendingForSameTool) {
1740
+ this.pendingRequests.delete(pendingId);
1741
+ this.emit(APPROVAL_EVENT.RESPONSE, {
1742
+ requestId: pendingId,
1743
+ decision: "deny",
1744
+ respondedAt: (/* @__PURE__ */ new Date()).toISOString()
1745
+ });
1746
+ }
1729
1747
  resolve("deny");
1730
1748
  } else {
1731
1749
  resolve(response.decision);
@@ -3298,6 +3316,14 @@ ${prompt}`
3298
3316
  this.state.lastProgressTime = /* @__PURE__ */ new Date();
3299
3317
  this.state.repeatedActions.clear();
3300
3318
  }
3319
+ /**
3320
+ * Check if the main loop should stop (due to pause, completion, etc.)
3321
+ * Uses string comparison to avoid TypeScript narrowing issues with const enums
3322
+ */
3323
+ shouldStopLoop() {
3324
+ const status = this.state.status;
3325
+ return status === AGENT_STATUS.PAUSED || status === AGENT_STATUS.COMPLETED || status === AGENT_STATUS.IDLE;
3326
+ }
3301
3327
  trackAction(action) {
3302
3328
  const count = this.state.repeatedActions.get(action) || 0;
3303
3329
  this.state.repeatedActions.set(action, count + 1);
@@ -3399,7 +3425,7 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
3399
3425
  });
3400
3426
  let iteration = 0;
3401
3427
  const maxIterations = this.config.maxIterations;
3402
- while (iteration < maxIterations && this.state.status === AGENT_STATUS.RUNNING) {
3428
+ while (iteration < maxIterations && !this.shouldStopLoop()) {
3403
3429
  iteration++;
3404
3430
  this.state.iteration = iteration;
3405
3431
  this.getCurrentPhase().attempts++;
@@ -3422,7 +3448,15 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
3422
3448
  continue;
3423
3449
  }
3424
3450
  const response = await this.executeStep();
3451
+ if (this.shouldStopLoop()) {
3452
+ this.think(THOUGHT_TYPE.OBSERVATION, "Execution paused by user");
3453
+ break;
3454
+ }
3425
3455
  await this.analyzeResponse(response);
3456
+ if (this.shouldStopLoop()) {
3457
+ this.think(THOUGHT_TYPE.OBSERVATION, "Execution paused by user");
3458
+ break;
3459
+ }
3426
3460
  if (this.shouldAdvancePhase()) {
3427
3461
  if (!this.advanceToNextPhase()) {
3428
3462
  this.think(THOUGHT_TYPE.OBSERVATION, "[done] All phases completed!");
@@ -3436,9 +3470,14 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
3436
3470
  await this.attemptRecovery(error);
3437
3471
  }
3438
3472
  }
3439
- this.state.status = AGENT_STATUS.COMPLETED;
3440
- await this.generateFinalReport();
3441
- this.emit(AGENT_EVENT.COMPLETE, this.getSummary());
3473
+ const finalStatus = this.state.status;
3474
+ if (finalStatus !== AGENT_STATUS.PAUSED && finalStatus !== AGENT_STATUS.COMPLETED) {
3475
+ this.state.status = AGENT_STATUS.COMPLETED;
3476
+ await this.generateFinalReport();
3477
+ this.emit(AGENT_EVENT.COMPLETE, this.getSummary());
3478
+ } else if (finalStatus === AGENT_STATUS.PAUSED) {
3479
+ this.emit(AGENT_EVENT.PAUSED);
3480
+ }
3442
3481
  }
3443
3482
  // ===== Step Execution =====
3444
3483
  async executeStep() {
@@ -3596,6 +3635,25 @@ Use report_finding tool for important discoveries.
3596
3635
  is_error: !result.success
3597
3636
  }]
3598
3637
  });
3638
+ if (!this.state.target.primary && result.success && result.output) {
3639
+ const ipMatches = result.output.match(/\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/g);
3640
+ if (ipMatches) {
3641
+ const validIPs = [...new Set(ipMatches)].filter(
3642
+ (ip) => !ip.startsWith("127.") && !ip.startsWith("0.") && !ip.startsWith("255.")
3643
+ );
3644
+ if (validIPs.length === 1) {
3645
+ this.setTarget(validIPs[0]);
3646
+ this.emit(AGENT_EVENT.RESPONSE, `
3647
+ [Target auto-set: ${validIPs[0]}]
3648
+ `);
3649
+ } else if (validIPs.length > 1) {
3650
+ this.emit(AGENT_EVENT.RESPONSE, `
3651
+ [Multiple IPs found: ${validIPs.join(", ")}]
3652
+ [Use /target <ip> to select one]
3653
+ `);
3654
+ }
3655
+ }
3656
+ }
3599
3657
  if (response.stop_reason === "tool_use") {
3600
3658
  return this.executeStep();
3601
3659
  }
@@ -4917,6 +4975,235 @@ var FindingDisplay = ({ block }) => {
4917
4975
  // src/cli/app.tsx
4918
4976
  import { homedir } from "os";
4919
4977
  import { join as join6 } from "path";
4978
+
4979
+ // src/cli/utils/keyboard-listener.ts
4980
+ import { EventEmitter as EventEmitter7 } from "events";
4981
+ import * as readline2 from "readline";
4982
+ var KeyboardListener = class extends EventEmitter7 {
4983
+ isListening = false;
4984
+ isPaused = false;
4985
+ stdin = process.stdin;
4986
+ originalRawMode;
4987
+ preInputBuffer = "";
4988
+ constructor() {
4989
+ super();
4990
+ this.handleKeypress = this.handleKeypress.bind(this);
4991
+ this.handleData = this.handleData.bind(this);
4992
+ }
4993
+ /**
4994
+ * Start listening for keyboard input in raw mode
4995
+ */
4996
+ start() {
4997
+ if (this.isListening) return;
4998
+ try {
4999
+ if (this.stdin.isTTY) {
5000
+ this.originalRawMode = this.stdin.isRaw;
5001
+ this.stdin.setRawMode(true);
5002
+ readline2.emitKeypressEvents(this.stdin);
5003
+ this.stdin.on("keypress", this.handleKeypress);
5004
+ this.stdin.resume();
5005
+ this.isListening = true;
5006
+ }
5007
+ } catch {
5008
+ this.stdin.on("data", this.handleData);
5009
+ this.isListening = true;
5010
+ }
5011
+ }
5012
+ /**
5013
+ * Stop listening and restore terminal state
5014
+ */
5015
+ stop() {
5016
+ if (!this.isListening) return;
5017
+ try {
5018
+ this.stdin.off("keypress", this.handleKeypress);
5019
+ this.stdin.off("data", this.handleData);
5020
+ if (this.stdin.isTTY && this.originalRawMode !== void 0) {
5021
+ this.stdin.setRawMode(this.originalRawMode);
5022
+ }
5023
+ } catch {
5024
+ }
5025
+ this.isListening = false;
5026
+ }
5027
+ /**
5028
+ * Pause listening (for when Ink needs control)
5029
+ */
5030
+ pause() {
5031
+ if (!this.isListening || this.isPaused) return;
5032
+ try {
5033
+ if (this.stdin.isTTY && this.originalRawMode !== void 0) {
5034
+ this.stdin.setRawMode(this.originalRawMode);
5035
+ }
5036
+ this.isPaused = true;
5037
+ } catch {
5038
+ }
5039
+ }
5040
+ /**
5041
+ * Resume listening (after Ink releases control)
5042
+ */
5043
+ resume() {
5044
+ if (!this.isListening || !this.isPaused) return;
5045
+ try {
5046
+ if (this.stdin.isTTY) {
5047
+ this.stdin.setRawMode(true);
5048
+ }
5049
+ this.isPaused = false;
5050
+ } catch {
5051
+ }
5052
+ }
5053
+ /**
5054
+ * Get the current pre-input buffer
5055
+ */
5056
+ getPreInputBuffer() {
5057
+ return this.preInputBuffer;
5058
+ }
5059
+ /**
5060
+ * Clear the pre-input buffer
5061
+ */
5062
+ clearPreInputBuffer() {
5063
+ this.preInputBuffer = "";
5064
+ }
5065
+ /**
5066
+ * Get and clear the pre-input buffer
5067
+ */
5068
+ consumePreInputBuffer() {
5069
+ const buffer = this.preInputBuffer;
5070
+ this.preInputBuffer = "";
5071
+ return buffer;
5072
+ }
5073
+ /**
5074
+ * Handle keypress events (readline mode)
5075
+ */
5076
+ handleKeypress(_str, key) {
5077
+ if (this.isPaused) return;
5078
+ if (key.name === "escape") {
5079
+ this.emit("escape" /* ESCAPE */);
5080
+ return;
5081
+ }
5082
+ if (key.ctrl && key.name === "c") {
5083
+ this.emit("ctrl_c" /* CTRL_C */);
5084
+ return;
5085
+ }
5086
+ if (key.name === "return" || key.name === "enter") {
5087
+ if (this.preInputBuffer) {
5088
+ this.emit("line", this.preInputBuffer);
5089
+ }
5090
+ this.emit("enter" /* ENTER */);
5091
+ return;
5092
+ }
5093
+ if (key.name === "backspace") {
5094
+ if (this.preInputBuffer.length > 0) {
5095
+ this.preInputBuffer = this.preInputBuffer.slice(0, -1);
5096
+ }
5097
+ this.emit("backspace" /* BACKSPACE */);
5098
+ return;
5099
+ }
5100
+ if (key.name === "up") {
5101
+ this.emit("up" /* UP */);
5102
+ return;
5103
+ }
5104
+ if (key.name === "down") {
5105
+ this.emit("down" /* DOWN */);
5106
+ return;
5107
+ }
5108
+ if (key.name === "left") {
5109
+ this.emit("left" /* LEFT */);
5110
+ return;
5111
+ }
5112
+ if (key.name === "right") {
5113
+ this.emit("right" /* RIGHT */);
5114
+ return;
5115
+ }
5116
+ if (key.name === "tab") {
5117
+ this.emit("tab" /* TAB */);
5118
+ return;
5119
+ }
5120
+ if (_str && !key.ctrl && !key.meta && _str.length === 1) {
5121
+ const charCode = _str.charCodeAt(0);
5122
+ if (charCode >= 32 && charCode <= 126) {
5123
+ this.preInputBuffer += _str;
5124
+ this.emit("char", _str);
5125
+ }
5126
+ }
5127
+ }
5128
+ /**
5129
+ * Handle raw data events (fallback mode)
5130
+ */
5131
+ handleData(data) {
5132
+ if (this.isPaused) return;
5133
+ const str = data.toString();
5134
+ for (let i = 0; i < str.length; i++) {
5135
+ const char = str[i];
5136
+ const code = char.charCodeAt(0);
5137
+ if (code === 27) {
5138
+ if (i + 1 < str.length && str[i + 1] === "[") {
5139
+ if (i + 2 < str.length) {
5140
+ const arrow = str[i + 2];
5141
+ switch (arrow) {
5142
+ case "A":
5143
+ this.emit("up" /* UP */);
5144
+ break;
5145
+ case "B":
5146
+ this.emit("down" /* DOWN */);
5147
+ break;
5148
+ case "C":
5149
+ this.emit("right" /* RIGHT */);
5150
+ break;
5151
+ case "D":
5152
+ this.emit("left" /* LEFT */);
5153
+ break;
5154
+ }
5155
+ i += 2;
5156
+ continue;
5157
+ }
5158
+ } else {
5159
+ this.emit("escape" /* ESCAPE */);
5160
+ continue;
5161
+ }
5162
+ }
5163
+ if (code === 3) {
5164
+ this.emit("ctrl_c" /* CTRL_C */);
5165
+ continue;
5166
+ }
5167
+ if (code === 13 || code === 10) {
5168
+ if (this.preInputBuffer) {
5169
+ this.emit("line", this.preInputBuffer);
5170
+ }
5171
+ this.emit("enter" /* ENTER */);
5172
+ continue;
5173
+ }
5174
+ if (code === 127 || code === 8) {
5175
+ if (this.preInputBuffer.length > 0) {
5176
+ this.preInputBuffer = this.preInputBuffer.slice(0, -1);
5177
+ }
5178
+ this.emit("backspace" /* BACKSPACE */);
5179
+ continue;
5180
+ }
5181
+ if (code === 9) {
5182
+ this.emit("tab" /* TAB */);
5183
+ continue;
5184
+ }
5185
+ if (code >= 32 && code <= 126) {
5186
+ this.preInputBuffer += char;
5187
+ this.emit("char", char);
5188
+ }
5189
+ }
5190
+ }
5191
+ /**
5192
+ * Check if currently listening
5193
+ */
5194
+ isActive() {
5195
+ return this.isListening && !this.isPaused;
5196
+ }
5197
+ };
5198
+ var keyboardListenerInstance = null;
5199
+ function getKeyboardListener() {
5200
+ if (!keyboardListenerInstance) {
5201
+ keyboardListenerInstance = new KeyboardListener();
5202
+ }
5203
+ return keyboardListenerInstance;
5204
+ }
5205
+
5206
+ // src/cli/app.tsx
4920
5207
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
4921
5208
  var App = ({ autoApprove = false, target }) => {
4922
5209
  const { exit } = useApp();
@@ -4931,12 +5218,19 @@ var App = ({ autoApprove = false, target }) => {
4931
5218
  const [showCommandHints, setShowCommandHints] = useState(false);
4932
5219
  const [mode, setMode] = useState("agent");
4933
5220
  const [checkpointCount, setCheckpointCount] = useState(0);
5221
+ const [preInputBuffer, setPreInputBuffer] = useState("");
5222
+ const [wasInterrupted, setWasInterrupted] = useState(false);
4934
5223
  const [agent] = useState(() => new AutonomousHackingAgent(void 0, { autoApprove }));
4935
5224
  const sessionManager2 = getSessionManager();
4936
5225
  const approvalManager2 = getApprovalManager({ yoloMode: autoApprove });
4937
5226
  const sessionDirRef = useRef(join6(homedir(), ".pentest", "sessions", `session-${Date.now()}`));
4938
5227
  const contextManagerRef = useRef(null);
4939
5228
  const wireLoggerRef = useRef(null);
5229
+ const keyboardListenerRef = useRef(getKeyboardListener());
5230
+ const isProcessingRef = useRef(false);
5231
+ useEffect(() => {
5232
+ isProcessingRef.current = isProcessing;
5233
+ }, [isProcessing]);
4940
5234
  useEffect(() => {
4941
5235
  const sessionId = `session-${Date.now()}`;
4942
5236
  contextManagerRef.current = new ContextManager2(sessionDirRef.current);
@@ -4946,7 +5240,7 @@ var App = ({ autoApprove = false, target }) => {
4946
5240
  setCheckpointCount(contextManagerRef.current?.getCheckpoints().length || 0);
4947
5241
  }
4948
5242
  });
4949
- import("./auto-update-GKUAPLBP.js").then(({ checkForUpdateAsync, formatUpdateNotification }) => {
5243
+ import("./auto-update-IDSABTT4.js").then(({ checkForUpdateAsync, formatUpdateNotification }) => {
4950
5244
  checkForUpdateAsync().then((result) => {
4951
5245
  if (result.hasUpdate) {
4952
5246
  const notification = formatUpdateNotification(result);
@@ -4988,6 +5282,60 @@ var App = ({ autoApprove = false, target }) => {
4988
5282
  setElapsedTime(0);
4989
5283
  return duration;
4990
5284
  }, []);
5285
+ useEffect(() => {
5286
+ const listener = keyboardListenerRef.current;
5287
+ const handleEscape = () => {
5288
+ if (isProcessingRef.current && !pendingApproval) {
5289
+ agent.pause();
5290
+ stopTimer();
5291
+ setIsProcessing(false);
5292
+ setCurrentStatus("");
5293
+ setWasInterrupted(true);
5294
+ addMessage(MESSAGE_TYPE.SYSTEM, "\u23F8 Interrupted by ESC - Ready for input");
5295
+ const buffered = listener.consumePreInputBuffer();
5296
+ if (buffered) {
5297
+ setInput(buffered);
5298
+ }
5299
+ listener.pause();
5300
+ }
5301
+ };
5302
+ const handleChar = () => {
5303
+ setPreInputBuffer(listener.getPreInputBuffer());
5304
+ };
5305
+ const handleBackspace = () => {
5306
+ setPreInputBuffer(listener.getPreInputBuffer());
5307
+ };
5308
+ listener.on("escape" /* ESCAPE */, handleEscape);
5309
+ listener.on("char", handleChar);
5310
+ listener.on("backspace" /* BACKSPACE */, handleBackspace);
5311
+ return () => {
5312
+ listener.off("escape" /* ESCAPE */, handleEscape);
5313
+ listener.off("char", handleChar);
5314
+ listener.off("backspace" /* BACKSPACE */, handleBackspace);
5315
+ };
5316
+ }, [agent, addMessage, stopTimer, pendingApproval]);
5317
+ useEffect(() => {
5318
+ const listener = keyboardListenerRef.current;
5319
+ if (isProcessing && !pendingApproval) {
5320
+ listener.clearPreInputBuffer();
5321
+ setPreInputBuffer("");
5322
+ listener.start();
5323
+ listener.resume();
5324
+ } else {
5325
+ const buffered = listener.consumePreInputBuffer();
5326
+ if (buffered && !wasInterrupted) {
5327
+ setInput((prev) => prev + buffered);
5328
+ }
5329
+ setPreInputBuffer("");
5330
+ setWasInterrupted(false);
5331
+ listener.pause();
5332
+ }
5333
+ }, [isProcessing, pendingApproval, wasInterrupted]);
5334
+ useEffect(() => {
5335
+ return () => {
5336
+ keyboardListenerRef.current.stop();
5337
+ };
5338
+ }, []);
4991
5339
  useEffect(() => {
4992
5340
  const banner = `
4993
5341
  \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
@@ -5166,13 +5514,20 @@ pentesting v${APP_VERSION}`
5166
5514
  return;
5167
5515
  case CLI_COMMAND.START:
5168
5516
  case "s":
5517
+ let startObjective = args.join(" ");
5518
+ const firstArg = args[0];
5519
+ if (firstArg && (firstArg.includes(".") || /^\d+\.\d+\.\d+\.\d+$/.test(firstArg))) {
5520
+ agent.setTarget(firstArg);
5521
+ addMessage(MESSAGE_TYPE.SYSTEM, `Target \u2192 ${firstArg}`);
5522
+ startObjective = args.slice(1).join(" ") || "Perform comprehensive penetration testing";
5523
+ }
5169
5524
  if (!agent.getState().target.primary) {
5170
- addMessage(MESSAGE_TYPE.ERROR, "Set target first: /target <ip>");
5525
+ addMessage(MESSAGE_TYPE.ERROR, "Set target first: /target <ip> or /start <domain>");
5171
5526
  return;
5172
5527
  }
5173
5528
  setIsProcessing(true);
5174
5529
  startTimer();
5175
- const objective = args.join(" ") || "Perform comprehensive penetration testing";
5530
+ const objective = startObjective || "Perform comprehensive penetration testing";
5176
5531
  setCurrentStatus("Initializing...");
5177
5532
  addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F680} Starting: ${objective}`);
5178
5533
  try {
@@ -5421,7 +5776,7 @@ pentesting v${APP_VERSION}`
5421
5776
  return;
5422
5777
  case "update":
5423
5778
  try {
5424
- const { checkForUpdate, formatUpdateNotification, doUpdate } = await import("./update-2U2TR7HJ.js");
5779
+ const { checkForUpdate, formatUpdateNotification, doUpdate } = await import("./update-OWR4FHRQ.js");
5425
5780
  const result = checkForUpdate(true);
5426
5781
  if (result.hasUpdate) {
5427
5782
  const notification = formatUpdateNotification(result);
@@ -5586,17 +5941,27 @@ pentesting v${APP_VERSION}`
5586
5941
  ] }, opt.decision)) }),
5587
5942
  /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "\u2191\u2193 to select, Enter to confirm, or type /y /n /ya" }) })
5588
5943
  ] }),
5589
- isProcessing ? /* @__PURE__ */ jsxs2(Box2, { children: [
5590
- /* @__PURE__ */ jsx2(Text2, { color: THEME.status.running, children: /* @__PURE__ */ jsx2(Spinner, { type: "dots" }) }),
5591
- /* @__PURE__ */ jsxs2(Text2, { color: THEME.text.muted, children: [
5592
- " ",
5593
- currentStatus,
5594
- elapsedTime > 0 && /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
5595
- " (",
5596
- elapsedTime,
5597
- "s)"
5944
+ isProcessing ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
5945
+ /* @__PURE__ */ jsxs2(Box2, { children: [
5946
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.status.running, children: /* @__PURE__ */ jsx2(Spinner, { type: "dots" }) }),
5947
+ /* @__PURE__ */ jsxs2(Text2, { color: THEME.text.muted, children: [
5948
+ " ",
5949
+ currentStatus,
5950
+ elapsedTime > 0 && /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
5951
+ " (",
5952
+ elapsedTime,
5953
+ "s)"
5954
+ ] })
5598
5955
  ] })
5599
- ] })
5956
+ ] }),
5957
+ preInputBuffer && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
5958
+ /* @__PURE__ */ jsxs2(Text2, { color: THEME.text.accent, children: [
5959
+ "\u2728 ",
5960
+ preInputBuffer
5961
+ ] }),
5962
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.text.muted, children: "\u258C" })
5963
+ ] }),
5964
+ /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "ESC to interrupt \u2502 Type ahead to queue input" }) })
5600
5965
  ] }) : /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
5601
5966
  showCommandHints && input.startsWith("/") && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: [
5602
5967
  "/target <ip>",
@@ -5639,7 +6004,11 @@ pentesting v${APP_VERSION}`
5639
6004
  state.currentPhase !== AGENT_STATUS.IDLE && ` ${state.currentPhase} \u2502`
5640
6005
  ] }),
5641
6006
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
5642
- "Ctrl+X mode \u2502 /help \u2502 Ctrl+C ",
6007
+ "v",
6008
+ APP_VERSION,
6009
+ " \u2502 Ctrl+X mode \u2502 /help \u2502 ",
6010
+ isProcessing ? "ESC interrupt \u2502 " : "",
6011
+ "Ctrl+C ",
5643
6012
  isProcessing ? "stop" : "exit"
5644
6013
  ] })
5645
6014
  ] })
@@ -8,8 +8,8 @@ import {
8
8
  readVersionCache,
9
9
  semverTuple,
10
10
  writeVersionCache
11
- } from "./chunk-L4MURCOP.js";
12
- import "./chunk-X3X45KYT.js";
11
+ } from "./chunk-ZC53SMRU.js";
12
+ import "./chunk-FHPP7RP2.js";
13
13
  import "./chunk-3RG5ZIWI.js";
14
14
  export {
15
15
  checkForUpdate,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pentesting",
3
- "version": "0.4.9",
3
+ "version": "0.5.3",
4
4
  "description": "Autonomous Penetration Testing AI Agent",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -78,4 +78,4 @@
78
78
  "tsx": "^4.19.2",
79
79
  "typescript": "^5.7.3"
80
80
  }
81
- }
81
+ }