pentesting 0.70.3 → 0.70.4

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 (2) hide show
  1. package/dist/main.js +97 -84
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -120,7 +120,7 @@ var ICONS = {
120
120
  };
121
121
 
122
122
  // src/shared/utils/debug/debug-logger.ts
123
- import { appendFileSync, writeFileSync } from "fs";
123
+ import { appendFileSync, writeFileSync, statSync, readFileSync } from "fs";
124
124
  import { join } from "path";
125
125
 
126
126
  // src/shared/utils/file-ops/file-utils.ts
@@ -275,10 +275,14 @@ var FILE_PATTERNS = {
275
275
  };
276
276
 
277
277
  // src/shared/utils/debug/debug-logger.ts
278
+ var ROTATE_BYTES = 5 * 1024 * 1024;
279
+ var WIPE_BYTES = 20 * 1024 * 1024;
280
+ var ROTATE_CHECK_INTERVAL = 500;
278
281
  var DebugLogger = class _DebugLogger {
279
282
  static instance;
280
283
  logPath;
281
284
  initialized = false;
285
+ writeCount = 0;
282
286
  constructor(clearOnInit = false) {
283
287
  const debugDir = WORKSPACE.DEBUG;
284
288
  try {
@@ -306,6 +310,31 @@ var DebugLogger = class _DebugLogger {
306
310
  _DebugLogger.instance = new _DebugLogger(clearOnInit);
307
311
  return _DebugLogger.instance;
308
312
  }
313
+ /**
314
+ * Rotate or wipe debug.log if it exceeds size thresholds.
315
+ * Called every ROTATE_CHECK_INTERVAL writes to amortize statSync cost.
316
+ *
317
+ * Policy:
318
+ * > 20 MB → wipe entirely (too much data, disk pressure)
319
+ * > 5 MB → keep latest half (recent logs more useful than old ones)
320
+ */
321
+ rotateIfNeeded() {
322
+ try {
323
+ const size = statSync(this.logPath).size;
324
+ if (size > WIPE_BYTES) {
325
+ writeFileSync(this.logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [GENERAL] === LOG WIPED (exceeded ${Math.round(WIPE_BYTES / 1024 / 1024)}MB) ===
326
+ `);
327
+ } else if (size > ROTATE_BYTES) {
328
+ const content = readFileSync(this.logPath, "utf-8");
329
+ const half = content.slice(Math.floor(content.length / 2));
330
+ const firstNewline = half.indexOf("\n");
331
+ const trimmed = firstNewline >= 0 ? half.slice(firstNewline + 1) : half;
332
+ writeFileSync(this.logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [GENERAL] === LOG ROTATED (exceeded ${Math.round(ROTATE_BYTES / 1024 / 1024)}MB, kept latest half) ===
333
+ ` + trimmed);
334
+ }
335
+ } catch {
336
+ }
337
+ }
309
338
  log(category, message, data) {
310
339
  if (!this.initialized || !this.logPath) return;
311
340
  try {
@@ -316,6 +345,9 @@ var DebugLogger = class _DebugLogger {
316
345
  }
317
346
  logLine += "\n";
318
347
  appendFileSync(this.logPath, logLine);
348
+ if (++this.writeCount % ROTATE_CHECK_INTERVAL === 0) {
349
+ this.rotateIfNeeded();
350
+ }
319
351
  } catch (e) {
320
352
  console.error("[DebugLogger] Write error:", e);
321
353
  }
@@ -329,6 +361,9 @@ ${raw}
329
361
  ---
330
362
  `;
331
363
  appendFileSync(this.logPath, logLine);
364
+ if (++this.writeCount % ROTATE_CHECK_INTERVAL === 0) {
365
+ this.rotateIfNeeded();
366
+ }
332
367
  } catch (e) {
333
368
  console.error("[DebugLogger] Write error:", e);
334
369
  }
@@ -727,7 +762,7 @@ var INPUT_PROMPT_PATTERNS = [
727
762
 
728
763
  // src/shared/constants/agent.ts
729
764
  var APP_NAME = "Pentest AI";
730
- var APP_VERSION = "0.70.3";
765
+ var APP_VERSION = "0.70.4";
731
766
  var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
732
767
  var LLM_ROLES = {
733
768
  SYSTEM: "system",
@@ -782,7 +817,7 @@ import { render } from "ink";
782
817
  import chalk from "chalk";
783
818
 
784
819
  // src/platform/tui/app.tsx
785
- import { useState as useState9, useCallback as useCallback11, useRef as useRef10 } from "react";
820
+ import { useState as useState8, useCallback as useCallback11, useRef as useRef10 } from "react";
786
821
  import { Box as Box19, useApp, useStdout as useStdout4 } from "ink";
787
822
 
788
823
  // src/platform/tui/hooks/useAgent.ts
@@ -2458,7 +2493,7 @@ var EpisodicMemory = class {
2458
2493
  };
2459
2494
 
2460
2495
  // src/shared/utils/agent-memory/persistent-memory.ts
2461
- import { existsSync as existsSync2, readFileSync, writeFileSync as writeFileSync2, unlinkSync } from "fs";
2496
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync } from "fs";
2462
2497
  import { join as join2 } from "path";
2463
2498
 
2464
2499
  // src/shared/utils/agent-memory/similarity.ts
@@ -2634,7 +2669,7 @@ var PersistentMemory = class {
2634
2669
  loadSessionSnapshot() {
2635
2670
  try {
2636
2671
  if (existsSync2(SNAPSHOT_FILE)) {
2637
- return JSON.parse(readFileSync(SNAPSHOT_FILE, "utf-8"));
2672
+ return JSON.parse(readFileSync2(SNAPSHOT_FILE, "utf-8"));
2638
2673
  }
2639
2674
  } catch {
2640
2675
  }
@@ -2670,7 +2705,7 @@ var PersistentMemory = class {
2670
2705
  load() {
2671
2706
  try {
2672
2707
  if (existsSync2(MEMORY_FILE)) {
2673
- const data = JSON.parse(readFileSync(MEMORY_FILE, "utf-8"));
2708
+ const data = JSON.parse(readFileSync2(MEMORY_FILE, "utf-8"));
2674
2709
  return {
2675
2710
  ...data,
2676
2711
  exploitChains: data.exploitChains ?? []
@@ -4555,7 +4590,7 @@ Suggestion: ${torLeak.suggestion}`
4555
4590
  }
4556
4591
 
4557
4592
  // src/engine/tools-base/file-operations.ts
4558
- import { readFileSync as readFileSync2, existsSync as existsSync3, writeFileSync as writeFileSync3 } from "fs";
4593
+ import { readFileSync as readFileSync3, existsSync as existsSync3, writeFileSync as writeFileSync3 } from "fs";
4559
4594
  import { dirname } from "path";
4560
4595
  import { join as join3 } from "path";
4561
4596
  import { tmpdir } from "os";
@@ -4575,7 +4610,7 @@ async function readFileContent(filePath) {
4575
4610
  error: `File not found: ${filePath}`
4576
4611
  };
4577
4612
  }
4578
- const content = readFileSync2(filePath, "utf-8");
4613
+ const content = readFileSync3(filePath, "utf-8");
4579
4614
  return {
4580
4615
  success: true,
4581
4616
  output: content
@@ -4679,7 +4714,7 @@ function startBackgroundProcess(command, options = {}) {
4679
4714
  }
4680
4715
 
4681
4716
  // src/engine/process/process-interaction.ts
4682
- import { existsSync as existsSync4, readFileSync as readFileSync3, appendFileSync as appendFileSync2 } from "fs";
4717
+ import { existsSync as existsSync4, readFileSync as readFileSync4, appendFileSync as appendFileSync2 } from "fs";
4683
4718
  async function sendToProcess(processId, input, waitMs = SYSTEM_LIMITS.DEFAULT_WAIT_MS_INTERACT) {
4684
4719
  const proc = getProcess(processId);
4685
4720
  if (!proc) return { success: false, output: `Process ${processId} not found`, newOutput: "" };
@@ -4688,7 +4723,7 @@ async function sendToProcess(processId, input, waitMs = SYSTEM_LIMITS.DEFAULT_WA
4688
4723
  let currentLen = 0;
4689
4724
  try {
4690
4725
  if (existsSync4(proc.stdoutFile)) {
4691
- currentLen = readFileSync3(proc.stdoutFile, "utf-8").length;
4726
+ currentLen = readFileSync4(proc.stdoutFile, "utf-8").length;
4692
4727
  }
4693
4728
  } catch {
4694
4729
  }
@@ -4702,7 +4737,7 @@ async function sendToProcess(processId, input, waitMs = SYSTEM_LIMITS.DEFAULT_WA
4702
4737
  let fullStdout = "";
4703
4738
  try {
4704
4739
  if (existsSync4(proc.stdoutFile)) {
4705
- fullStdout = readFileSync3(proc.stdoutFile, "utf-8");
4740
+ fullStdout = readFileSync4(proc.stdoutFile, "utf-8");
4706
4741
  }
4707
4742
  } catch {
4708
4743
  }
@@ -4724,7 +4759,7 @@ function promoteToShell(processId, description) {
4724
4759
  }
4725
4760
 
4726
4761
  // src/engine/process/process-monitor.ts
4727
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
4762
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
4728
4763
  function isProcessRunning(processId) {
4729
4764
  const proc = getProcess(processId);
4730
4765
  if (!proc) return false;
@@ -4738,7 +4773,7 @@ function isProcessRunning(processId) {
4738
4773
  if (proc.role === PROCESS_ROLES.LISTENER) {
4739
4774
  try {
4740
4775
  if (existsSync5(proc.stdoutFile)) {
4741
- const stdout = readFileSync4(proc.stdoutFile, "utf-8");
4776
+ const stdout = readFileSync5(proc.stdoutFile, "utf-8");
4742
4777
  if (detectConnection(stdout)) {
4743
4778
  promoteToShell(processId, "Reverse shell connected (auto-detected)");
4744
4779
  logEvent(processId, PROCESS_EVENTS.CONNECTION_DETECTED, `Connection detected on port ${proc.listeningPort}`);
@@ -4757,7 +4792,7 @@ function getProcessOutput(processId) {
4757
4792
  let stderr = "";
4758
4793
  try {
4759
4794
  if (existsSync5(proc.stdoutFile)) {
4760
- const content = readFileSync4(proc.stdoutFile, "utf-8");
4795
+ const content = readFileSync5(proc.stdoutFile, "utf-8");
4761
4796
  stdout = content.length > SYSTEM_LIMITS.MAX_STDOUT_SLICE ? `... [truncated ${content.length - SYSTEM_LIMITS.MAX_STDOUT_SLICE} chars] ...
4762
4797
  ` + content.slice(-SYSTEM_LIMITS.MAX_STDOUT_SLICE) : content;
4763
4798
  }
@@ -4765,7 +4800,7 @@ function getProcessOutput(processId) {
4765
4800
  }
4766
4801
  try {
4767
4802
  if (existsSync5(proc.stderrFile)) {
4768
- const content = readFileSync4(proc.stderrFile, "utf-8");
4803
+ const content = readFileSync5(proc.stderrFile, "utf-8");
4769
4804
  stderr = content.length > SYSTEM_LIMITS.MAX_STDERR_SLICE ? `... [truncated ${content.length - SYSTEM_LIMITS.MAX_STDERR_SLICE} chars] ...
4770
4805
  ` + content.slice(-SYSTEM_LIMITS.MAX_STDERR_SLICE) : content;
4771
4806
  }
@@ -4938,7 +4973,7 @@ async function cleanupAllProcesses() {
4938
4973
  }
4939
4974
 
4940
4975
  // src/engine/process/resource-summary.ts
4941
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
4976
+ import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
4942
4977
  function getResourceSummary() {
4943
4978
  const procs = listBackgroundProcesses();
4944
4979
  const running = procs.filter((p) => p.isRunning);
@@ -4958,7 +4993,7 @@ function getResourceSummary() {
4958
4993
  let lastOutput = "";
4959
4994
  try {
4960
4995
  if (p.stdoutFile && existsSync6(p.stdoutFile)) {
4961
- const content = readFileSync5(p.stdoutFile, "utf-8");
4996
+ const content = readFileSync6(p.stdoutFile, "utf-8");
4962
4997
  const outputLines = content.trim().split("\n");
4963
4998
  lastOutput = outputLines.slice(-SYSTEM_LIMITS.RECENT_OUTPUT_LINES).join(" | ").replace(/\n/g, " ");
4964
4999
  }
@@ -5203,7 +5238,7 @@ BLOCKED (leak real IP): ping, traceroute, dig, nslookup, nmap -sU`
5203
5238
  };
5204
5239
 
5205
5240
  // src/engine/state/persistence/saver.ts
5206
- import { writeFileSync as writeFileSync5, readdirSync, statSync, unlinkSync as unlinkSync5 } from "fs";
5241
+ import { writeFileSync as writeFileSync5, readdirSync, statSync as statSync2, unlinkSync as unlinkSync5 } from "fs";
5207
5242
  import { join as join4 } from "path";
5208
5243
  function saveState(state) {
5209
5244
  const sessionsDir = WORKSPACE.SESSIONS;
@@ -5236,7 +5271,7 @@ function pruneOldSessions(sessionsDir) {
5236
5271
  return {
5237
5272
  name: f,
5238
5273
  path: filePath,
5239
- mtime: statSync(filePath).mtimeMs
5274
+ mtime: statSync2(filePath).mtimeMs
5240
5275
  };
5241
5276
  }).sort((a, b) => b.mtime - a.mtime);
5242
5277
  const toDelete = sessionFiles.slice(AGENT_LIMITS.MAX_SESSION_FILES);
@@ -5248,7 +5283,7 @@ function pruneOldSessions(sessionsDir) {
5248
5283
  }
5249
5284
 
5250
5285
  // src/engine/state/persistence/loader.ts
5251
- import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
5286
+ import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
5252
5287
  import { join as join5 } from "path";
5253
5288
  function loadState(state) {
5254
5289
  const latestFile = join5(WORKSPACE.SESSIONS, "latest.json");
@@ -5256,7 +5291,7 @@ function loadState(state) {
5256
5291
  return false;
5257
5292
  }
5258
5293
  try {
5259
- const raw = readFileSync6(latestFile, "utf-8");
5294
+ const raw = readFileSync7(latestFile, "utf-8");
5260
5295
  const snapshot = JSON.parse(raw);
5261
5296
  if (snapshot.version !== 1) {
5262
5297
  debugLog("general", `Unknown snapshot version: ${snapshot.version}`);
@@ -10357,7 +10392,7 @@ function mutatePayload(request) {
10357
10392
  }
10358
10393
 
10359
10394
  // src/domains/exploit/tools.ts
10360
- import { existsSync as existsSync10, statSync as statSync2, readdirSync as readdirSync2 } from "fs";
10395
+ import { existsSync as existsSync10, statSync as statSync3, readdirSync as readdirSync2 } from "fs";
10361
10396
  import { join as join10 } from "path";
10362
10397
  var hashCrackTool = {
10363
10398
  name: TOOL_NAMES.HASH_CRACK,
@@ -10516,7 +10551,7 @@ Returns: All available wordlists with their paths, sizes, and categories.`,
10516
10551
  const processFile = (fullPath, fileName) => {
10517
10552
  const ext = fileName.split(".").pop()?.toLowerCase();
10518
10553
  if (!WORDLIST_EXTENSIONS.has(ext || "")) return;
10519
- const stats = statSync2(fullPath);
10554
+ const stats = statSync3(fullPath);
10520
10555
  if (stats.size < minSize) return;
10521
10556
  if (!matchesCategory(fullPath)) return;
10522
10557
  if (!matchesSearch(fullPath, fileName)) return;
@@ -13135,7 +13170,7 @@ var PHASE_TECHNIQUE_MAP = {
13135
13170
  };
13136
13171
 
13137
13172
  // src/agents/prompt-builder/prompt-loader.ts
13138
- import { readFileSync as readFileSync7, existsSync as existsSync11 } from "fs";
13173
+ import { readFileSync as readFileSync8, existsSync as existsSync11 } from "fs";
13139
13174
  import { join as join12, dirname as dirname4 } from "path";
13140
13175
  import { fileURLToPath as fileURLToPath2 } from "url";
13141
13176
  var __dirname2 = dirname4(fileURLToPath2(import.meta.url));
@@ -13143,13 +13178,13 @@ var PROMPTS_DIR = join12(__dirname2, "../prompts");
13143
13178
  var TECHNIQUES_DIR = join12(PROMPTS_DIR, PROMPT_PATHS.TECHNIQUES_DIR);
13144
13179
  function loadPromptFile(filename) {
13145
13180
  const path2 = join12(PROMPTS_DIR, filename);
13146
- return existsSync11(path2) ? readFileSync7(path2, PROMPT_CONFIG.ENCODING) : "";
13181
+ return existsSync11(path2) ? readFileSync8(path2, PROMPT_CONFIG.ENCODING) : "";
13147
13182
  }
13148
13183
  function loadTechniqueFile(techniqueName) {
13149
13184
  const filePath = join12(TECHNIQUES_DIR, `${techniqueName}.md`);
13150
13185
  try {
13151
13186
  if (!existsSync11(filePath)) return "";
13152
- return readFileSync7(filePath, PROMPT_CONFIG.ENCODING);
13187
+ return readFileSync8(filePath, PROMPT_CONFIG.ENCODING);
13153
13188
  } catch {
13154
13189
  return "";
13155
13190
  }
@@ -13294,11 +13329,11 @@ ${lines.join("\n")}
13294
13329
  }
13295
13330
 
13296
13331
  // src/shared/utils/journal/reader.ts
13297
- import { readFileSync as readFileSync8, existsSync as existsSync13 } from "fs";
13332
+ import { readFileSync as readFileSync9, existsSync as existsSync13 } from "fs";
13298
13333
  import { join as join14 } from "path";
13299
13334
 
13300
13335
  // src/shared/utils/journal/rotation.ts
13301
- import { existsSync as existsSync12, readdirSync as readdirSync3, statSync as statSync3, rmSync as rmSync2 } from "fs";
13336
+ import { existsSync as existsSync12, readdirSync as readdirSync3, statSync as statSync4, rmSync as rmSync2 } from "fs";
13302
13337
  import { join as join13 } from "path";
13303
13338
  function parseTurnNumbers(turnsDir) {
13304
13339
  if (!existsSync12(turnsDir)) return [];
@@ -13308,7 +13343,7 @@ function rotateTurnRecords() {
13308
13343
  try {
13309
13344
  const turnsDir = WORKSPACE.TURNS;
13310
13345
  if (!existsSync12(turnsDir)) return;
13311
- const turnDirs = parseTurnNumbers(turnsDir).map((n) => `${TURN_FOLDER_PREFIX}${n}`).filter((e) => statSync3(join13(turnsDir, e)).isDirectory()).sort((a, b) => Number(a.slice(TURN_FOLDER_PREFIX.length)) - Number(b.slice(TURN_FOLDER_PREFIX.length)));
13346
+ const turnDirs = parseTurnNumbers(turnsDir).map((n) => `${TURN_FOLDER_PREFIX}${n}`).filter((e) => statSync4(join13(turnsDir, e)).isDirectory()).sort((a, b) => Number(a.slice(TURN_FOLDER_PREFIX.length)) - Number(b.slice(TURN_FOLDER_PREFIX.length)));
13312
13347
  if (turnDirs.length > MEMORY_LIMITS.MAX_TURN_ENTRIES) {
13313
13348
  const dirsToDel = turnDirs.slice(0, turnDirs.length - MEMORY_LIMITS.MAX_TURN_ENTRIES);
13314
13349
  for (const dir of dirsToDel) {
@@ -13334,7 +13369,7 @@ function readJournalSummary() {
13334
13369
  for (const turn of turnDirs) {
13335
13370
  const summaryPath = join14(WORKSPACE.turnPath(turn), TURN_FILES.SUMMARY);
13336
13371
  if (existsSync13(summaryPath)) {
13337
- return readFileSync8(summaryPath, "utf-8");
13372
+ return readFileSync9(summaryPath, "utf-8");
13338
13373
  }
13339
13374
  }
13340
13375
  return "";
@@ -13351,7 +13386,7 @@ function getRecentEntries(count = MEMORY_LIMITS.MAX_TURN_ENTRIES) {
13351
13386
  try {
13352
13387
  const filePath = join14(WORKSPACE.turnPath(turn), TURN_FILES.STRUCTURED);
13353
13388
  if (existsSync13(filePath)) {
13354
- const raw = readFileSync8(filePath, "utf-8");
13389
+ const raw = readFileSync9(filePath, "utf-8");
13355
13390
  entries.push(JSON.parse(raw));
13356
13391
  }
13357
13392
  } catch {
@@ -14073,7 +14108,7 @@ function formatForPrompt(directive, isStale = false) {
14073
14108
  }
14074
14109
 
14075
14110
  // src/agents/strategist/prompt-loader.ts
14076
- import { readFileSync as readFileSync9, existsSync as existsSync14 } from "fs";
14111
+ import { readFileSync as readFileSync10, existsSync as existsSync14 } from "fs";
14077
14112
  import { join as join16, dirname as dirname5 } from "path";
14078
14113
  import { fileURLToPath as fileURLToPath3 } from "url";
14079
14114
  var __dirname3 = dirname5(fileURLToPath3(import.meta.url));
@@ -14081,7 +14116,7 @@ var STRATEGIST_PROMPT_PATH = join16(__dirname3, "../prompts", "strategist-system
14081
14116
  function loadSystemPrompt() {
14082
14117
  try {
14083
14118
  if (existsSync14(STRATEGIST_PROMPT_PATH)) {
14084
- return readFileSync9(STRATEGIST_PROMPT_PATH, "utf-8");
14119
+ return readFileSync10(STRATEGIST_PROMPT_PATH, "utf-8");
14085
14120
  }
14086
14121
  } catch {
14087
14122
  }
@@ -14477,7 +14512,7 @@ async function processReflection(toolJournal, memo14, phase, reflector) {
14477
14512
  }
14478
14513
 
14479
14514
  // src/agents/main-agent/turn-recorder.ts
14480
- import { writeFileSync as writeFileSync10, existsSync as existsSync15, readFileSync as readFileSync10 } from "fs";
14515
+ import { writeFileSync as writeFileSync10, existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
14481
14516
  import { join as join17 } from "path";
14482
14517
  async function recordTurn(context) {
14483
14518
  const { turnCounter, phase, toolJournal, memo: memo14, reflections, summaryRegenerator } = context;
@@ -14550,7 +14585,7 @@ async function regenerateSummary(turnCounter, summaryRegenerator, ctx) {
14550
14585
  if (prevTurn >= 1) {
14551
14586
  const prevSummaryPath = join17(WORKSPACE.turnPath(prevTurn), TURN_FILES.SUMMARY);
14552
14587
  if (existsSync15(prevSummaryPath)) {
14553
- existingSummary = readFileSync10(prevSummaryPath, "utf-8");
14588
+ existingSummary = readFileSync11(prevSummaryPath, "utf-8");
14554
14589
  }
14555
14590
  }
14556
14591
  const turnData = formatTurnRecord({
@@ -16123,7 +16158,7 @@ var useKeyboardShortcuts = ({
16123
16158
  };
16124
16159
 
16125
16160
  // src/platform/tui/components/MessageList.tsx
16126
- import { memo as memo7, useState as useState4, useCallback as useCallback8, useRef as useRef6 } from "react";
16161
+ import { memo as memo7, useState as useState3, useCallback as useCallback8, useRef as useRef6 } from "react";
16127
16162
  import { Box as Box8, Text as Text8, useInput as useInput2 } from "ink";
16128
16163
 
16129
16164
  // src/platform/tui/components/messages/ThinkingBlock.tsx
@@ -16659,34 +16694,12 @@ import { memo as memo6 } from "react";
16659
16694
  import { Box as Box7, Text as Text7 } from "ink";
16660
16695
 
16661
16696
  // src/platform/tui/components/ShimmerBanner.tsx
16662
- import { useState as useState3, useEffect as useEffect5, memo as memo5 } from "react";
16697
+ import { memo as memo5 } from "react";
16663
16698
  import { Box as Box6, Text as Text6 } from "ink";
16664
16699
  import { jsx as jsx6 } from "react/jsx-runtime";
16665
- var FRAME_INTERVAL = 60;
16666
- var WAVE_SPEED = 0.22;
16667
- var CHAR_GAP = 0.18;
16668
- var ROW_GAP = 1.6;
16669
- function waveColor(sin) {
16670
- const t = (sin + 1) / 2;
16671
- const r = Math.round(36 + t * (255 - 36));
16672
- const g = Math.round(150 + t * (255 - 150));
16673
- const b = Math.round(237 + t * (255 - 237));
16674
- return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
16675
- }
16676
16700
  var ShimmerBanner = memo5(({ banner }) => {
16677
- const [tick, setTick] = useState3(0);
16678
- useEffect5(() => {
16679
- const timer = setInterval(() => setTick((t) => t + 1), FRAME_INTERVAL);
16680
- return () => clearInterval(timer);
16681
- }, []);
16682
- const globalPhase = tick * WAVE_SPEED;
16683
16701
  const lines = banner.split("\n").filter((l) => l.length > 0);
16684
- return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", children: lines.map((line, row) => /* @__PURE__ */ jsx6(Text6, { children: Array.from(line).map((char, col) => {
16685
- const phase = globalPhase - col * CHAR_GAP - row * ROW_GAP;
16686
- const sin = Math.sin(phase);
16687
- const color = char.trim() === "" ? HEX.primary : waveColor(sin);
16688
- return /* @__PURE__ */ jsx6(Text6, { color, children: char }, col);
16689
- }) }, row)) });
16702
+ return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", children: lines.map((line, row) => /* @__PURE__ */ jsx6(Text6, { color: HEX.primary, children: line }, row)) });
16690
16703
  });
16691
16704
 
16692
16705
  // src/platform/tui/components/messages/EmptyState.tsx
@@ -16752,7 +16765,7 @@ function computeSlidingWindow(messages, scrollOffset) {
16752
16765
  // src/platform/tui/components/MessageList.tsx
16753
16766
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
16754
16767
  var MessageList = memo7(({ messages, isModalOpen, modelName, autoApproveMode, version, scrollOffset = 0 }) => {
16755
- const [expandedIds, setExpandedIds] = useState4(/* @__PURE__ */ new Set());
16768
+ const [expandedIds, setExpandedIds] = useState3(/* @__PURE__ */ new Set());
16756
16769
  const messagesRef = useRef6(messages);
16757
16770
  messagesRef.current = messages;
16758
16771
  const isModalOpenRef = useRef6(isModalOpen);
@@ -16834,12 +16847,12 @@ import { memo as memo10 } from "react";
16834
16847
  import { Box as Box11, Text as Text13 } from "ink";
16835
16848
 
16836
16849
  // src/platform/tui/hooks/useStatusTimer.ts
16837
- import { useState as useState5, useEffect as useEffect6, useRef as useRef7 } from "react";
16850
+ import { useState as useState4, useEffect as useEffect5, useRef as useRef7 } from "react";
16838
16851
  var useStatusTimer = (currentStatus, isProcessing) => {
16839
- const [statusElapsed, setStatusElapsed] = useState5(0);
16852
+ const [statusElapsed, setStatusElapsed] = useState4(0);
16840
16853
  const statusTimerRef = useRef7(null);
16841
16854
  const statusStartRef = useRef7(Date.now());
16842
- useEffect6(() => {
16855
+ useEffect5(() => {
16843
16856
  if (statusTimerRef.current) clearInterval(statusTimerRef.current);
16844
16857
  if (isProcessing && currentStatus) {
16845
16858
  statusStartRef.current = Date.now();
@@ -16862,7 +16875,7 @@ var useStatusTimer = (currentStatus, isProcessing) => {
16862
16875
  import { Box as Box9, Text as Text10 } from "ink";
16863
16876
 
16864
16877
  // src/platform/tui/components/MusicSpinner.tsx
16865
- import { useState as useState6, useEffect as useEffect7, memo as memo8 } from "react";
16878
+ import { useState as useState5, useEffect as useEffect6, memo as memo8 } from "react";
16866
16879
  import { Text as Text9 } from "ink";
16867
16880
  import { jsx as jsx9 } from "react/jsx-runtime";
16868
16881
  var FRAMES = [
@@ -16883,8 +16896,8 @@ var FRAMES = [
16883
16896
  ];
16884
16897
  var INTERVAL = 150;
16885
16898
  var MusicSpinner = memo8(({ color }) => {
16886
- const [index, setIndex] = useState6(0);
16887
- useEffect7(() => {
16899
+ const [index, setIndex] = useState5(0);
16900
+ useEffect6(() => {
16888
16901
  const timer = setInterval(() => {
16889
16902
  setIndex((i) => (i + 1) % FRAMES.length);
16890
16903
  }, INTERVAL);
@@ -16925,11 +16938,11 @@ var RetryView = ({ retryState }) => {
16925
16938
  import { Box as Box10, Text as Text12 } from "ink";
16926
16939
 
16927
16940
  // src/platform/tui/components/ShimmerText.tsx
16928
- import { useState as useState7, useEffect as useEffect8, memo as memo9 } from "react";
16941
+ import { useState as useState6, useEffect as useEffect7, memo as memo9 } from "react";
16929
16942
  import { Text as Text11 } from "ink";
16930
16943
  import { jsx as jsx11 } from "react/jsx-runtime";
16931
- var FRAME_INTERVAL2 = 120;
16932
- var WAVE_SPEED2 = 0.25;
16944
+ var FRAME_INTERVAL = 120;
16945
+ var WAVE_SPEED = 0.25;
16933
16946
  var CHAR_PHASE_GAP = 0.55;
16934
16947
  function sinToColor(sin) {
16935
16948
  const t = (sin + 1) / 2;
@@ -16938,14 +16951,14 @@ function sinToColor(sin) {
16938
16951
  return `#${hex}${hex}${hex}`;
16939
16952
  }
16940
16953
  var ShimmerText = memo9(({ children, bold, phase = 0 }) => {
16941
- const [tick, setTick] = useState7(0);
16942
- useEffect8(() => {
16954
+ const [tick, setTick] = useState6(0);
16955
+ useEffect7(() => {
16943
16956
  const timer = setInterval(() => {
16944
16957
  setTick((t) => t + 1);
16945
- }, FRAME_INTERVAL2);
16958
+ }, FRAME_INTERVAL);
16946
16959
  return () => clearInterval(timer);
16947
16960
  }, []);
16948
- const globalPhase = tick * WAVE_SPEED2 + phase;
16961
+ const globalPhase = tick * WAVE_SPEED + phase;
16949
16962
  return /* @__PURE__ */ jsx11(Text11, { bold, children: Array.from(children).map((char, i) => {
16950
16963
  const charPhase = globalPhase - i * CHAR_PHASE_GAP;
16951
16964
  const sin = Math.sin(charPhase);
@@ -17023,7 +17036,7 @@ var StatusDisplay = memo10(({
17023
17036
  });
17024
17037
 
17025
17038
  // src/platform/tui/components/ChatInput.tsx
17026
- import { useMemo, useCallback as useCallback9, useRef as useRef8, memo as memo11, useState as useState8, useEffect as useEffect9 } from "react";
17039
+ import { useMemo, useCallback as useCallback9, useRef as useRef8, memo as memo11, useState as useState7, useEffect as useEffect8 } from "react";
17027
17040
  import { Box as Box15, Text as Text17, useInput as useInput3 } from "ink";
17028
17041
 
17029
17042
  // src/platform/tui/components/input/AutocompletePreview.tsx
@@ -17146,7 +17159,7 @@ var ChatInput = memo11(({
17146
17159
  return getMatchingCommands(partialCmd).slice(0, MAX_SUGGESTIONS);
17147
17160
  }, [isSlashMode, partialCmd, hasArgs]);
17148
17161
  const showPreview = isSlashMode && !hasArgs && suggestions.length > 0;
17149
- const [selectedIdx, setSelectedIdx] = useState8(0);
17162
+ const [selectedIdx, setSelectedIdx] = useState7(0);
17150
17163
  const clampedIdx = Math.min(selectedIdx, Math.max(0, suggestions.length - 1));
17151
17164
  const selectedIdxRef = useRef8(clampedIdx);
17152
17165
  selectedIdxRef.current = clampedIdx;
@@ -17162,10 +17175,10 @@ var ChatInput = memo11(({
17162
17175
  inputRequestRef.current = inputRequest;
17163
17176
  const onChangeRef = useRef8(onChange);
17164
17177
  onChangeRef.current = onChange;
17165
- const [pastedHint, setPastedHint] = useState8(null);
17178
+ const [pastedHint, setPastedHint] = useState7(null);
17166
17179
  const prevValueRef = useRef8(value);
17167
17180
  const pasteTimerRef = useRef8(null);
17168
- useEffect9(() => {
17181
+ useEffect8(() => {
17169
17182
  const diff = value.length - prevValueRef.current.length;
17170
17183
  if (diff > 20) {
17171
17184
  if (pasteTimerRef.current) clearTimeout(pasteTimerRef.current);
@@ -17177,7 +17190,7 @@ var ChatInput = memo11(({
17177
17190
  if (pasteTimerRef.current) clearTimeout(pasteTimerRef.current);
17178
17191
  };
17179
17192
  }, [value]);
17180
- const [inputKey, setInputKey] = useState8(0);
17193
+ const [inputKey, setInputKey] = useState7(0);
17181
17194
  const completeCommand = useCallback9((idx) => {
17182
17195
  const sug = suggestionsRef.current;
17183
17196
  if (!sug.length) return;
@@ -17498,10 +17511,10 @@ var App = ({ autoApprove = false, target }) => {
17498
17511
  const { exit } = useApp();
17499
17512
  const { stdout } = useStdout4();
17500
17513
  const terminalWidth = stdout?.columns ?? 80;
17501
- const [input, setInput] = useState9("");
17502
- const [secretInput, setSecretInput] = useState9("");
17503
- const [autoApproveMode, setAutoApproveMode] = useState9(autoApprove);
17504
- const [modal, setModal] = useState9({ type: null, content: "", scrollOffset: 0 });
17514
+ const [input, setInput] = useState8("");
17515
+ const [secretInput, setSecretInput] = useState8("");
17516
+ const [autoApproveMode, setAutoApproveMode] = useState8(autoApprove);
17517
+ const [modal, setModal] = useState8({ type: null, content: "", scrollOffset: 0 });
17505
17518
  const {
17506
17519
  agent,
17507
17520
  messages,
@@ -17534,7 +17547,7 @@ var App = ({ autoApprove = false, target }) => {
17534
17547
  const clearInput = useCallback11(() => {
17535
17548
  setInput("");
17536
17549
  }, []);
17537
- const [historyScrollOffset, setHistoryScrollOffset] = useState9(0);
17550
+ const [historyScrollOffset, setHistoryScrollOffset] = useState8(0);
17538
17551
  const handleScroll = useCallback11((delta) => {
17539
17552
  setHistoryScrollOffset((prev) => Math.max(0, prev - delta));
17540
17553
  }, []);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pentesting",
3
- "version": "0.70.3",
3
+ "version": "0.70.4",
4
4
  "description": "Autonomous Penetration Testing AI Agent",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",