pentesting 0.70.4 → 0.70.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.
Files changed (2) hide show
  1. package/dist/main.js +225 -214
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -762,7 +762,7 @@ var INPUT_PROMPT_PATTERNS = [
762
762
 
763
763
  // src/shared/constants/agent.ts
764
764
  var APP_NAME = "Pentest AI";
765
- var APP_VERSION = "0.70.4";
765
+ var APP_VERSION = "0.70.5";
766
766
  var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
767
767
  var LLM_ROLES = {
768
768
  SYSTEM: "system",
@@ -817,7 +817,7 @@ import { render } from "ink";
817
817
  import chalk from "chalk";
818
818
 
819
819
  // src/platform/tui/app.tsx
820
- import { useState as useState8, useCallback as useCallback11, useRef as useRef10 } from "react";
820
+ import { useState as useState7, useCallback as useCallback11, useRef as useRef10 } from "react";
821
821
  import { Box as Box19, useApp, useStdout as useStdout4 } from "ink";
822
822
 
823
823
  // src/platform/tui/hooks/useAgent.ts
@@ -15237,11 +15237,12 @@ ${firstLine}`);
15237
15237
  }
15238
15238
 
15239
15239
  // src/platform/tui/hooks/useAgentEvents/handlers/input.ts
15240
- function setupInputHandlers(setInputRequest) {
15240
+ function setupInputHandlers(setInputRequest, addMessage) {
15241
15241
  setInputHandler((p) => {
15242
15242
  return new Promise((resolve) => {
15243
15243
  const isPassword = /password|passphrase/i.test(p);
15244
15244
  const inputType = /sudo/i.test(p) ? INPUT_TYPES.SUDO_PASSWORD : isPassword ? INPUT_TYPES.PASSWORD : INPUT_TYPES.TEXT;
15245
+ addMessage("ai", `\u{1F512} ${p.trim()}`);
15245
15246
  setInputRequest({
15246
15247
  status: "active",
15247
15248
  prompt: p.trim(),
@@ -15255,6 +15256,7 @@ function setupInputHandlers(setInputRequest) {
15255
15256
  return new Promise((resolve) => {
15256
15257
  const isPassword = SENSITIVE_INPUT_TYPES.includes(request.type);
15257
15258
  const displayPrompt = buildCredentialPrompt(request);
15259
+ addMessage("ai", `\u{1F512} ${displayPrompt}`);
15258
15260
  setInputRequest({
15259
15261
  status: "active",
15260
15262
  prompt: displayPrompt,
@@ -15322,7 +15324,7 @@ var useAgentEvents = (agent, eventsRef, state) => {
15322
15324
  lastStepTokensRef
15323
15325
  }, reasoningBufferRef);
15324
15326
  const reasoningHandlers = createReasoningHandlers({ addMessage, setCurrentStatus }, reasoningBufferRef);
15325
- const cleanupInput = setupInputHandlers(setInputRequest);
15327
+ const cleanupInput = setupInputHandlers(setInputRequest, addMessage);
15326
15328
  const cleanupCommand = setupCommandHandlers(addMessage);
15327
15329
  const updateStats = () => {
15328
15330
  const s = agent.getState();
@@ -16157,14 +16159,31 @@ var useKeyboardShortcuts = ({
16157
16159
  return { handleCtrlC };
16158
16160
  };
16159
16161
 
16162
+ // src/platform/tui/hooks/useAnimationTick.tsx
16163
+ import { createContext, useContext, useState as useState3, useEffect as useEffect5 } from "react";
16164
+ import { jsx } from "react/jsx-runtime";
16165
+ var ANIM_TICK_MS = 100;
16166
+ var AnimationContext = createContext(0);
16167
+ var AnimationProvider = ({ children }) => {
16168
+ const [tick, setTick] = useState3(0);
16169
+ useEffect5(() => {
16170
+ const timer = setInterval(() => {
16171
+ setTick((t) => t + 1);
16172
+ }, ANIM_TICK_MS);
16173
+ return () => clearInterval(timer);
16174
+ }, []);
16175
+ return /* @__PURE__ */ jsx(AnimationContext.Provider, { value: tick, children });
16176
+ };
16177
+ var useAnimationTick = () => useContext(AnimationContext);
16178
+
16160
16179
  // src/platform/tui/components/MessageList.tsx
16161
- import { memo as memo7, useState as useState3, useCallback as useCallback8, useRef as useRef6 } from "react";
16180
+ import { memo as memo7, useState as useState4, useCallback as useCallback8, useRef as useRef6 } from "react";
16162
16181
  import { Box as Box8, Text as Text8, useInput as useInput2 } from "ink";
16163
16182
 
16164
16183
  // src/platform/tui/components/messages/ThinkingBlock.tsx
16165
16184
  import { memo } from "react";
16166
16185
  import { Box, Text } from "ink";
16167
- import { jsx, jsxs } from "react/jsx-runtime";
16186
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
16168
16187
  var THINKING_PREVIEW_LINES = 3;
16169
16188
  var ThinkingBlock = memo(({ msg, isExpanded }) => {
16170
16189
  const lines = msg.content.split("\n");
@@ -16174,19 +16193,19 @@ var ThinkingBlock = memo(({ msg, isExpanded }) => {
16174
16193
  const visibleLines = isExpanded ? lines : lines.slice(0, THINKING_PREVIEW_LINES);
16175
16194
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 0, children: [
16176
16195
  /* @__PURE__ */ jsxs(Box, { children: [
16177
- /* @__PURE__ */ jsx(Text, { color: THEME.dimGray, children: " \u25C6 " }),
16178
- /* @__PURE__ */ jsx(Text, { color: THEME.gray, children: "Reasoning" }),
16179
- /* @__PURE__ */ jsx(Text, { color: THEME.dimGray, children: ` (~${estTokens} tokens)` }),
16180
- !isExpanded && hiddenCount > 0 && /* @__PURE__ */ jsx(Text, { color: THEME.dimGray, children: ` [+${hiddenCount} lines \xB7 R]` }),
16181
- isExpanded && /* @__PURE__ */ jsx(Text, { color: THEME.dimGray, children: " [R to collapse]" })
16196
+ /* @__PURE__ */ jsx2(Text, { color: THEME.dimGray, children: " \u25C6 " }),
16197
+ /* @__PURE__ */ jsx2(Text, { color: THEME.gray, children: "Reasoning" }),
16198
+ /* @__PURE__ */ jsx2(Text, { color: THEME.dimGray, children: ` (~${estTokens} tokens)` }),
16199
+ !isExpanded && hiddenCount > 0 && /* @__PURE__ */ jsx2(Text, { color: THEME.dimGray, children: ` [+${hiddenCount} lines \xB7 R]` }),
16200
+ isExpanded && /* @__PURE__ */ jsx2(Text, { color: THEME.dimGray, children: " [R to collapse]" })
16182
16201
  ] }),
16183
16202
  visibleLines.map((line, i) => /* @__PURE__ */ jsxs(Box, { children: [
16184
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
16185
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: line })
16203
+ /* @__PURE__ */ jsx2(Text, { dimColor: true, children: " \u2502 " }),
16204
+ /* @__PURE__ */ jsx2(Text, { dimColor: true, children: line })
16186
16205
  ] }, i)),
16187
16206
  !isExpanded && hiddenCount > 0 && /* @__PURE__ */ jsxs(Box, { children: [
16188
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
16189
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: "..." })
16207
+ /* @__PURE__ */ jsx2(Text, { dimColor: true, children: " \u2502 " }),
16208
+ /* @__PURE__ */ jsx2(Text, { dimColor: true, children: "..." })
16190
16209
  ] })
16191
16210
  ] });
16192
16211
  });
@@ -16233,7 +16252,7 @@ var MESSAGE_STYLES = {
16233
16252
 
16234
16253
  // src/platform/tui/components/inline-status.tsx
16235
16254
  import { Box as Box2, Text as Text2 } from "ink";
16236
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
16255
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
16237
16256
  function formatDuration3(ms) {
16238
16257
  const seconds = Math.floor(ms / 1e3);
16239
16258
  if (seconds < 60) return `${seconds}s`;
@@ -16281,13 +16300,13 @@ function ProcessRow({ proc, isCompact }) {
16281
16300
  const purpose = proc.purpose || proc.description || "";
16282
16301
  const truncatedPurpose = isCompact && purpose.length > TUI_DISPLAY_LIMITS.purposeMaxLength ? purpose.slice(0, TUI_DISPLAY_LIMITS.purposeTruncated) + "..." : purpose;
16283
16302
  return /* @__PURE__ */ jsxs2(Box2, { children: [
16284
- /* @__PURE__ */ jsx2(StatusIndicator, { isRunning: proc.isRunning, exitCode: proc.exitCode }),
16303
+ /* @__PURE__ */ jsx3(StatusIndicator, { isRunning: proc.isRunning, exitCode: proc.exitCode }),
16285
16304
  /* @__PURE__ */ jsxs2(Text2, { color: THEME.gray, children: [
16286
16305
  "[",
16287
16306
  proc.id,
16288
16307
  "]"
16289
16308
  ] }),
16290
- /* @__PURE__ */ jsx2(Text2, { children: " " }),
16309
+ /* @__PURE__ */ jsx3(Text2, { children: " " }),
16291
16310
  /* @__PURE__ */ jsxs2(Text2, { color: getRoleColor(proc.role), bold: true, children: [
16292
16311
  proc.role,
16293
16312
  port
@@ -16298,8 +16317,8 @@ function ProcessRow({ proc, isCompact }) {
16298
16317
  ")"
16299
16318
  ] }),
16300
16319
  truncatedPurpose && /* @__PURE__ */ jsxs2(Fragment, { children: [
16301
- /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: " - " }),
16302
- /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: truncatedPurpose })
16320
+ /* @__PURE__ */ jsx3(Text2, { color: THEME.gray, children: " - " }),
16321
+ /* @__PURE__ */ jsx3(Text2, { color: THEME.gray, children: truncatedPurpose })
16303
16322
  ] })
16304
16323
  ] });
16305
16324
  }
@@ -16310,7 +16329,7 @@ var InlineStatus = ({
16310
16329
  isCompact = true
16311
16330
  }) => {
16312
16331
  if (processes.length === 0 && zombies.length === 0) {
16313
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: "\u2022 No active background processes" }) });
16332
+ return /* @__PURE__ */ jsx3(Box2, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx3(Text2, { color: THEME.gray, children: "\u2022 No active background processes" }) });
16314
16333
  }
16315
16334
  const running = processes.filter((p) => p.isRunning);
16316
16335
  const stopped = processes.filter((p) => !p.isRunning);
@@ -16327,7 +16346,7 @@ var InlineStatus = ({
16327
16346
  running.length,
16328
16347
  ")"
16329
16348
  ] }),
16330
- running.map((proc) => /* @__PURE__ */ jsx2(ProcessRow, { proc, isCompact }, proc.id))
16349
+ running.map((proc) => /* @__PURE__ */ jsx3(ProcessRow, { proc, isCompact }, proc.id))
16331
16350
  ] }),
16332
16351
  stopped.length > 0 && !isCompact && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: running.length > 0 ? 1 : 0, children: [
16333
16352
  /* @__PURE__ */ jsxs2(Text2, { color: THEME.gray, children: [
@@ -16336,7 +16355,7 @@ var InlineStatus = ({
16336
16355
  stopped.length,
16337
16356
  ")"
16338
16357
  ] }),
16339
- stopped.slice(0, TUI_DISPLAY_LIMITS.maxStoppedProcesses).map((proc) => /* @__PURE__ */ jsx2(ProcessRow, { proc, isCompact }, proc.id)),
16358
+ stopped.slice(0, TUI_DISPLAY_LIMITS.maxStoppedProcesses).map((proc) => /* @__PURE__ */ jsx3(ProcessRow, { proc, isCompact }, proc.id)),
16340
16359
  stopped.length > TUI_DISPLAY_LIMITS.maxStoppedProcesses && /* @__PURE__ */ jsxs2(Text2, { color: THEME.gray, children: [
16341
16360
  " ... and ",
16342
16361
  stopped.length - TUI_DISPLAY_LIMITS.maxStoppedProcesses,
@@ -16366,11 +16385,11 @@ var InlineStatus = ({
16366
16385
  " orphaned children"
16367
16386
  ] })
16368
16387
  ] }, z.processId)),
16369
- /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: " Run /cleanup to terminate" })
16388
+ /* @__PURE__ */ jsx3(Text2, { color: THEME.gray, children: " Run /cleanup to terminate" })
16370
16389
  ] }),
16371
16390
  /* @__PURE__ */ jsxs2(Box2, { marginTop: running.length > 0 ? 1 : 0, children: [
16372
- /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: "Health: " }),
16373
- /* @__PURE__ */ jsx2(Text2, { color: healthColor, bold: true, children: health.toUpperCase() })
16391
+ /* @__PURE__ */ jsx3(Text2, { color: THEME.gray, children: "Health: " }),
16392
+ /* @__PURE__ */ jsx3(Text2, { color: healthColor, bold: true, children: health.toUpperCase() })
16374
16393
  ] })
16375
16394
  ] });
16376
16395
  };
@@ -16378,7 +16397,7 @@ var InlineStatus = ({
16378
16397
  // src/platform/tui/components/ToolCard.tsx
16379
16398
  import { memo as memo2 } from "react";
16380
16399
  import { Box as Box3, Text as Text3 } from "ink";
16381
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
16400
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
16382
16401
  var ARGS_MAX = 72;
16383
16402
  function truncate(s, max) {
16384
16403
  return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
@@ -16423,12 +16442,12 @@ function parseToolContent(content) {
16423
16442
  var ToolCard = memo2(({ content }) => {
16424
16443
  const { name, args } = parseToolContent(content);
16425
16444
  return /* @__PURE__ */ jsxs3(Box3, { children: [
16426
- /* @__PURE__ */ jsx3(Text3, { color: THEME.primary, children: " \u2295 " }),
16427
- /* @__PURE__ */ jsx3(Text3, { color: THEME.white, bold: true, children: name }),
16445
+ /* @__PURE__ */ jsx4(Text3, { color: THEME.primary, children: " \u2295 " }),
16446
+ /* @__PURE__ */ jsx4(Text3, { color: THEME.white, bold: true, children: name }),
16428
16447
  args && /* @__PURE__ */ jsxs3(Fragment2, { children: [
16429
- /* @__PURE__ */ jsx3(Text3, { color: THEME.dimGray, children: "(" }),
16430
- /* @__PURE__ */ jsx3(Text3, { color: THEME.gray, children: args }),
16431
- /* @__PURE__ */ jsx3(Text3, { color: THEME.dimGray, children: ")" })
16448
+ /* @__PURE__ */ jsx4(Text3, { color: THEME.dimGray, children: "(" }),
16449
+ /* @__PURE__ */ jsx4(Text3, { color: THEME.gray, children: args }),
16450
+ /* @__PURE__ */ jsx4(Text3, { color: THEME.dimGray, children: ")" })
16432
16451
  ] })
16433
16452
  ] });
16434
16453
  });
@@ -16436,7 +16455,7 @@ var ToolCard = memo2(({ content }) => {
16436
16455
  // src/platform/tui/components/MarkdownText.tsx
16437
16456
  import { memo as memo3 } from "react";
16438
16457
  import { Box as Box4, Text as Text4 } from "ink";
16439
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
16458
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
16440
16459
  function tokenizeLine(line) {
16441
16460
  const tokens = [];
16442
16461
  let i = 0;
@@ -16460,14 +16479,14 @@ function tokenizeLine(line) {
16460
16479
  }
16461
16480
  return tokens;
16462
16481
  }
16463
- var InlineContent = ({ tokens }) => /* @__PURE__ */ jsx4(Fragment3, { children: tokens.map((tok, i) => {
16482
+ var InlineContent = ({ tokens }) => /* @__PURE__ */ jsx5(Fragment3, { children: tokens.map((tok, i) => {
16464
16483
  if (tok.type === "bold") {
16465
- return /* @__PURE__ */ jsx4(Text4, { bold: true, color: THEME.white, children: tok.value }, i);
16484
+ return /* @__PURE__ */ jsx5(Text4, { bold: true, color: THEME.white, children: tok.value }, i);
16466
16485
  }
16467
16486
  if (tok.type === "code") {
16468
- return /* @__PURE__ */ jsx4(Text4, { color: THEME.cyan, children: `\`${tok.value}\`` }, i);
16487
+ return /* @__PURE__ */ jsx5(Text4, { color: THEME.cyan, children: `\`${tok.value}\`` }, i);
16469
16488
  }
16470
- return /* @__PURE__ */ jsx4(Text4, { color: THEME.white, children: tok.value }, i);
16489
+ return /* @__PURE__ */ jsx5(Text4, { color: THEME.white, children: tok.value }, i);
16471
16490
  }) });
16472
16491
  function parseBlocks(lines) {
16473
16492
  const blocks = [];
@@ -16517,12 +16536,12 @@ function parseBlocks(lines) {
16517
16536
  }
16518
16537
  var BlockRenderer = ({ block, blockIdx }) => {
16519
16538
  if (block.type === "blank") {
16520
- return /* @__PURE__ */ jsx4(Text4, { children: " " }, blockIdx);
16539
+ return /* @__PURE__ */ jsx5(Text4, { children: " " }, blockIdx);
16521
16540
  }
16522
16541
  if (block.type === "heading") {
16523
16542
  const prefixes = { 1: "\u25B8 ", 2: " \u25B9 ", 3: " \xB7 " };
16524
16543
  const colors = { 1: THEME.primary, 2: THEME.cyan, 3: THEME.white };
16525
- return /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsxs4(Text4, { color: colors[block.level], bold: true, children: [
16544
+ return /* @__PURE__ */ jsx5(Box4, { children: /* @__PURE__ */ jsxs4(Text4, { color: colors[block.level], bold: true, children: [
16526
16545
  prefixes[block.level],
16527
16546
  block.content
16528
16547
  ] }) }, blockIdx);
@@ -16534,7 +16553,7 @@ var BlockRenderer = ({ block, blockIdx }) => {
16534
16553
  bullet,
16535
16554
  " "
16536
16555
  ] }),
16537
- /* @__PURE__ */ jsx4(InlineContent, { tokens: tokenizeLine(block.content) })
16556
+ /* @__PURE__ */ jsx5(InlineContent, { tokens: tokenizeLine(block.content) })
16538
16557
  ] }, blockIdx);
16539
16558
  }
16540
16559
  if (block.type === "codeBlock") {
@@ -16547,19 +16566,19 @@ var BlockRenderer = ({ block, blockIdx }) => {
16547
16566
  paddingX: 1,
16548
16567
  marginY: 0,
16549
16568
  children: [
16550
- block.lang && /* @__PURE__ */ jsx4(Text4, { color: THEME.dimGray, children: block.lang }),
16551
- block.lines.map((l, li) => /* @__PURE__ */ jsx4(Text4, { color: THEME.cyan, children: l }, li))
16569
+ block.lang && /* @__PURE__ */ jsx5(Text4, { color: THEME.dimGray, children: block.lang }),
16570
+ block.lines.map((l, li) => /* @__PURE__ */ jsx5(Text4, { color: THEME.cyan, children: l }, li))
16552
16571
  ]
16553
16572
  },
16554
16573
  blockIdx
16555
16574
  );
16556
16575
  }
16557
- return /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsx4(InlineContent, { tokens: tokenizeLine(block.content) }) }, blockIdx);
16576
+ return /* @__PURE__ */ jsx5(Box4, { children: /* @__PURE__ */ jsx5(InlineContent, { tokens: tokenizeLine(block.content) }) }, blockIdx);
16558
16577
  };
16559
16578
  var MarkdownText = memo3(({ content }) => {
16560
16579
  const lines = content.split("\n");
16561
16580
  const blocks = parseBlocks(lines);
16562
- return /* @__PURE__ */ jsx4(Box4, { flexDirection: "column", children: blocks.map((block, i) => /* @__PURE__ */ jsx4(BlockRenderer, { block, blockIdx: i }, i)) });
16581
+ return /* @__PURE__ */ jsx5(Box4, { flexDirection: "column", children: blocks.map((block, i) => /* @__PURE__ */ jsx5(BlockRenderer, { block, blockIdx: i }, i)) });
16563
16582
  });
16564
16583
 
16565
16584
  // src/platform/tui/components/messages/parseStatusContent.ts
@@ -16607,12 +16626,12 @@ function computeResultDisplay(content, isExpanded) {
16607
16626
  }
16608
16627
 
16609
16628
  // src/platform/tui/components/messages/MessageRow.tsx
16610
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
16629
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
16611
16630
  var MessageRow = memo4(({ msg, isExpanded }) => {
16612
16631
  if (msg.type === "status") {
16613
16632
  const statusData = parseStatusContent(msg.content);
16614
16633
  if (statusData) {
16615
- return /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsx5(
16634
+ return /* @__PURE__ */ jsx6(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsx6(
16616
16635
  InlineStatus,
16617
16636
  {
16618
16637
  processes: statusData.processes,
@@ -16622,15 +16641,15 @@ var MessageRow = memo4(({ msg, isExpanded }) => {
16622
16641
  ) }, msg.id);
16623
16642
  }
16624
16643
  return /* @__PURE__ */ jsxs5(Box5, { children: [
16625
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.dimGray, children: " \xB7 " }),
16626
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.gray, children: msg.content })
16644
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.dimGray, children: " \xB7 " }),
16645
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.gray, children: msg.content })
16627
16646
  ] }, msg.id);
16628
16647
  }
16629
16648
  if (msg.type === "thinking") {
16630
- return /* @__PURE__ */ jsx5(ThinkingBlock, { msg, isExpanded });
16649
+ return /* @__PURE__ */ jsx6(ThinkingBlock, { msg, isExpanded });
16631
16650
  }
16632
16651
  if (msg.type === "tool") {
16633
- return /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(ToolCard, { content: msg.content }) }, msg.id);
16652
+ return /* @__PURE__ */ jsx6(Box5, { children: /* @__PURE__ */ jsx6(ToolCard, { content: msg.content }) }, msg.id);
16634
16653
  }
16635
16654
  if (msg.type === "result") {
16636
16655
  const kind = classifyResult(msg.content);
@@ -16640,19 +16659,19 @@ var MessageRow = memo4(({ msg, isExpanded }) => {
16640
16659
  const isFailure = kind === "failure";
16641
16660
  return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
16642
16661
  /* @__PURE__ */ jsxs5(Box5, { children: [
16643
- /* @__PURE__ */ jsx5(Text5, { color: THEME.dimGray, children: " \u2514 " }),
16644
- /* @__PURE__ */ jsx5(Text5, { color, children: firstLine }),
16645
- hasMore && /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.dimGray, children: ` [+${hiddenCount - RESULT_PREVIEW_LINES} \xB7 T]` }),
16646
- effectiveExpanded && hiddenCount > RESULT_PREVIEW_LINES && !isFailure && /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.dimGray, children: " [T \u2193]" })
16662
+ /* @__PURE__ */ jsx6(Text5, { color: THEME.dimGray, children: " \u2514 " }),
16663
+ /* @__PURE__ */ jsx6(Text5, { color, children: firstLine }),
16664
+ hasMore && /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.dimGray, children: ` [+${hiddenCount - RESULT_PREVIEW_LINES} \xB7 T]` }),
16665
+ effectiveExpanded && hiddenCount > RESULT_PREVIEW_LINES && !isFailure && /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.dimGray, children: " [T \u2193]" })
16647
16666
  ] }),
16648
16667
  visibleRest.map((line, i) => /* @__PURE__ */ jsxs5(Box5, { children: [
16649
- /* @__PURE__ */ jsx5(Text5, { color: THEME.dimGray, children: " " }),
16650
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.gray, children: line })
16668
+ /* @__PURE__ */ jsx6(Text5, { color: THEME.dimGray, children: " " }),
16669
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.gray, children: line })
16651
16670
  ] }, i))
16652
16671
  ] }, msg.id);
16653
16672
  }
16654
16673
  if (msg.type === "ai" || msg.type === "assistant") {
16655
- return /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", marginBottom: 0, children: /* @__PURE__ */ jsx5(MarkdownText, { content: msg.content }) }, msg.id);
16674
+ return /* @__PURE__ */ jsx6(Box5, { flexDirection: "column", marginBottom: 0, children: /* @__PURE__ */ jsx6(MarkdownText, { content: msg.content }) }, msg.id);
16656
16675
  }
16657
16676
  if (msg.type === "error") {
16658
16677
  const eLines = msg.content.split("\n");
@@ -16660,32 +16679,32 @@ var MessageRow = memo4(({ msg, isExpanded }) => {
16660
16679
  const eHidden = eLines.length - 1;
16661
16680
  return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
16662
16681
  /* @__PURE__ */ jsxs5(Box5, { children: [
16663
- /* @__PURE__ */ jsx5(Text5, { color: THEME.red, children: " \u2717 " }),
16664
- /* @__PURE__ */ jsx5(Text5, { color: THEME.red, children: eFirst }),
16665
- !isExpanded && eHidden > 0 && /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.dimGray, children: ` [+${eHidden} \xB7 E]` }),
16666
- isExpanded && eHidden > 0 && /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.dimGray, children: " [E \u2191]" })
16682
+ /* @__PURE__ */ jsx6(Text5, { color: THEME.red, children: " \u2717 " }),
16683
+ /* @__PURE__ */ jsx6(Text5, { color: THEME.red, children: eFirst }),
16684
+ !isExpanded && eHidden > 0 && /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.dimGray, children: ` [+${eHidden} \xB7 E]` }),
16685
+ isExpanded && eHidden > 0 && /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.dimGray, children: " [E \u2191]" })
16667
16686
  ] }),
16668
16687
  isExpanded && eLines.slice(1).map((line, i) => /* @__PURE__ */ jsxs5(Box5, { children: [
16669
- /* @__PURE__ */ jsx5(Text5, { color: THEME.dimGray, children: " " }),
16670
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.red, children: line })
16688
+ /* @__PURE__ */ jsx6(Text5, { color: THEME.dimGray, children: " " }),
16689
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.red, children: line })
16671
16690
  ] }, i))
16672
16691
  ] }, msg.id);
16673
16692
  }
16674
16693
  if (msg.type === "user") {
16675
16694
  return /* @__PURE__ */ jsxs5(Box5, { children: [
16676
- /* @__PURE__ */ jsx5(Text5, { color: THEME.primary, children: "\u276F " }),
16677
- /* @__PURE__ */ jsx5(Text5, { color: THEME.white, bold: true, children: msg.content })
16695
+ /* @__PURE__ */ jsx6(Text5, { color: THEME.primary, children: "\u276F " }),
16696
+ /* @__PURE__ */ jsx6(Text5, { color: THEME.white, bold: true, children: msg.content })
16678
16697
  ] }, msg.id);
16679
16698
  }
16680
16699
  if (msg.type === "system") {
16681
16700
  return /* @__PURE__ */ jsxs5(Box5, { children: [
16682
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.dimGray, children: " \xB7 " }),
16683
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.gray, children: msg.content })
16701
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.dimGray, children: " \xB7 " }),
16702
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.gray, children: msg.content })
16684
16703
  ] }, msg.id);
16685
16704
  }
16686
16705
  return /* @__PURE__ */ jsxs5(Box5, { children: [
16687
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, color: THEME.dimGray, children: " \xB7 " }),
16688
- /* @__PURE__ */ jsx5(Text5, { color: MESSAGE_STYLES.colors[msg.type] ?? THEME.gray, children: msg.content })
16706
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, color: THEME.dimGray, children: " \xB7 " }),
16707
+ /* @__PURE__ */ jsx6(Text5, { color: MESSAGE_STYLES.colors[msg.type] ?? THEME.gray, children: msg.content })
16689
16708
  ] }, msg.id);
16690
16709
  });
16691
16710
 
@@ -16696,36 +16715,36 @@ import { Box as Box7, Text as Text7 } from "ink";
16696
16715
  // src/platform/tui/components/ShimmerBanner.tsx
16697
16716
  import { memo as memo5 } from "react";
16698
16717
  import { Box as Box6, Text as Text6 } from "ink";
16699
- import { jsx as jsx6 } from "react/jsx-runtime";
16718
+ import { jsx as jsx7 } from "react/jsx-runtime";
16700
16719
  var ShimmerBanner = memo5(({ banner }) => {
16701
16720
  const lines = banner.split("\n").filter((l) => l.length > 0);
16702
- return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", children: lines.map((line, row) => /* @__PURE__ */ jsx6(Text6, { color: HEX.primary, children: line }, row)) });
16721
+ return /* @__PURE__ */ jsx7(Box6, { flexDirection: "column", children: lines.map((line, row) => /* @__PURE__ */ jsx7(Text6, { color: HEX.primary, children: line }, row)) });
16703
16722
  });
16704
16723
 
16705
16724
  // src/platform/tui/components/messages/EmptyState.tsx
16706
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
16725
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
16707
16726
  var EmptyState = memo6(({ modelName, autoApproveMode, version }) => {
16708
16727
  const autoLabel = autoApproveMode ? "ON" : "OFF";
16709
16728
  const autoColor = autoApproveMode ? THEME.primary : THEME.gray;
16710
16729
  return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", paddingX: 1, paddingY: 1, children: [
16711
- /* @__PURE__ */ jsx7(ShimmerBanner, { banner: ASCII_BANNER }),
16712
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
16730
+ /* @__PURE__ */ jsx8(ShimmerBanner, { banner: ASCII_BANNER }),
16731
+ /* @__PURE__ */ jsx8(Text7, { children: " " }),
16713
16732
  /* @__PURE__ */ jsxs6(Box7, { gap: 2, children: [
16714
- /* @__PURE__ */ jsx7(Text7, { color: THEME.primary, bold: true, children: "\u25C8 Pentesting" }),
16715
- version && /* @__PURE__ */ jsx7(Text7, { color: THEME.dimGray, children: `v${version}` }),
16733
+ /* @__PURE__ */ jsx8(Text7, { color: THEME.primary, bold: true, children: "\u25C8 Pentesting" }),
16734
+ version && /* @__PURE__ */ jsx8(Text7, { color: THEME.dimGray, children: `v${version}` }),
16716
16735
  modelName && /* @__PURE__ */ jsxs6(Text7, { color: THEME.dimGray, children: [
16717
16736
  "\xB7",
16718
16737
  " ",
16719
- /* @__PURE__ */ jsx7(Text7, { color: THEME.gray, children: modelName })
16738
+ /* @__PURE__ */ jsx8(Text7, { color: THEME.gray, children: modelName })
16720
16739
  ] }),
16721
16740
  /* @__PURE__ */ jsxs6(Text7, { color: THEME.dimGray, children: [
16722
16741
  "\xB7",
16723
16742
  " Auto: ",
16724
- /* @__PURE__ */ jsx7(Text7, { color: autoColor, children: autoLabel })
16743
+ /* @__PURE__ */ jsx8(Text7, { color: autoColor, children: autoLabel })
16725
16744
  ] })
16726
16745
  ] }),
16727
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
16728
- /* @__PURE__ */ jsx7(Text7, { color: THEME.gray, children: " Get started:" }),
16746
+ /* @__PURE__ */ jsx8(Text7, { children: " " }),
16747
+ /* @__PURE__ */ jsx8(Text7, { color: THEME.gray, children: " Get started:" }),
16729
16748
  /* @__PURE__ */ jsxs6(Text7, { color: THEME.gray, children: [
16730
16749
  " ",
16731
16750
  " ",
@@ -16738,17 +16757,17 @@ var EmptyState = memo6(({ modelName, autoApproveMode, version }) => {
16738
16757
  /* @__PURE__ */ jsxs6(Text7, { color: THEME.gray, children: [
16739
16758
  " ",
16740
16759
  " ",
16741
- /* @__PURE__ */ jsx7(Text7, { color: THEME.white, children: "/start" }),
16760
+ /* @__PURE__ */ jsx8(Text7, { color: THEME.white, children: "/start" }),
16742
16761
  " \u2014 Begin autonomous pentest"
16743
16762
  ] }),
16744
16763
  /* @__PURE__ */ jsxs6(Text7, { color: THEME.gray, children: [
16745
16764
  " ",
16746
16765
  " ",
16747
- /* @__PURE__ */ jsx7(Text7, { color: THEME.white, children: "/help" }),
16766
+ /* @__PURE__ */ jsx8(Text7, { color: THEME.white, children: "/help" }),
16748
16767
  " \u2014 Show all commands"
16749
16768
  ] }),
16750
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
16751
- /* @__PURE__ */ jsx7(Text7, { color: THEME.dimGray, children: " Or just type a task and press Enter." })
16769
+ /* @__PURE__ */ jsx8(Text7, { children: " " }),
16770
+ /* @__PURE__ */ jsx8(Text7, { color: THEME.dimGray, children: " Or just type a task and press Enter." })
16752
16771
  ] });
16753
16772
  });
16754
16773
 
@@ -16763,9 +16782,9 @@ function computeSlidingWindow(messages, scrollOffset) {
16763
16782
  }
16764
16783
 
16765
16784
  // src/platform/tui/components/MessageList.tsx
16766
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
16785
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
16767
16786
  var MessageList = memo7(({ messages, isModalOpen, modelName, autoApproveMode, version, scrollOffset = 0 }) => {
16768
- const [expandedIds, setExpandedIds] = useState3(/* @__PURE__ */ new Set());
16787
+ const [expandedIds, setExpandedIds] = useState4(/* @__PURE__ */ new Set());
16769
16788
  const messagesRef = useRef6(messages);
16770
16789
  messagesRef.current = messages;
16771
16790
  const isModalOpenRef = useRef6(isModalOpen);
@@ -16819,7 +16838,7 @@ var MessageList = memo7(({ messages, isModalOpen, modelName, autoApproveMode, ve
16819
16838
  }
16820
16839
  }, []));
16821
16840
  if (messages.length === 0) {
16822
- return /* @__PURE__ */ jsx8(
16841
+ return /* @__PURE__ */ jsx9(
16823
16842
  EmptyState,
16824
16843
  {
16825
16844
  modelName,
@@ -16830,8 +16849,8 @@ var MessageList = memo7(({ messages, isModalOpen, modelName, autoApproveMode, ve
16830
16849
  }
16831
16850
  const { visibleMessages, hiddenAbove, clampedOffset } = computeSlidingWindow(messages, scrollOffset);
16832
16851
  return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
16833
- clampedOffset > 0 && /* @__PURE__ */ jsx8(Box8, { paddingX: 1, children: /* @__PURE__ */ jsx8(Text8, { dimColor: true, color: THEME.dimGray, children: `\u2191 ${hiddenAbove} message${hiddenAbove !== 1 ? "s" : ""} above \xB7 PgDn to scroll down` }) }),
16834
- visibleMessages.map((msg) => /* @__PURE__ */ jsx8(
16852
+ clampedOffset > 0 && /* @__PURE__ */ jsx9(Box8, { paddingX: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, color: THEME.dimGray, children: `\u2191 ${hiddenAbove} message${hiddenAbove !== 1 ? "s" : ""} above \xB7 PgDn to scroll down` }) }),
16853
+ visibleMessages.map((msg) => /* @__PURE__ */ jsx9(
16835
16854
  MessageRow,
16836
16855
  {
16837
16856
  msg,
@@ -16847,12 +16866,12 @@ import { memo as memo10 } from "react";
16847
16866
  import { Box as Box11, Text as Text13 } from "ink";
16848
16867
 
16849
16868
  // src/platform/tui/hooks/useStatusTimer.ts
16850
- import { useState as useState4, useEffect as useEffect5, useRef as useRef7 } from "react";
16869
+ import { useState as useState5, useEffect as useEffect6, useRef as useRef7 } from "react";
16851
16870
  var useStatusTimer = (currentStatus, isProcessing) => {
16852
- const [statusElapsed, setStatusElapsed] = useState4(0);
16871
+ const [statusElapsed, setStatusElapsed] = useState5(0);
16853
16872
  const statusTimerRef = useRef7(null);
16854
16873
  const statusStartRef = useRef7(Date.now());
16855
- useEffect5(() => {
16874
+ useEffect6(() => {
16856
16875
  if (statusTimerRef.current) clearInterval(statusTimerRef.current);
16857
16876
  if (isProcessing && currentStatus) {
16858
16877
  statusStartRef.current = Date.now();
@@ -16874,10 +16893,10 @@ var useStatusTimer = (currentStatus, isProcessing) => {
16874
16893
  // src/platform/tui/components/status/RetryView.tsx
16875
16894
  import { Box as Box9, Text as Text10 } from "ink";
16876
16895
 
16877
- // src/platform/tui/components/MusicSpinner.tsx
16878
- import { useState as useState5, useEffect as useEffect6, memo as memo8 } from "react";
16896
+ // src/platform/tui/components/StarSpinner.tsx
16897
+ import { memo as memo8 } from "react";
16879
16898
  import { Text as Text9 } from "ink";
16880
- import { jsx as jsx9 } from "react/jsx-runtime";
16899
+ import { jsx as jsx10 } from "react/jsx-runtime";
16881
16900
  var FRAMES = [
16882
16901
  "\xB7",
16883
16902
  "\u2726",
@@ -16894,27 +16913,21 @@ var FRAMES = [
16894
16913
  "\u2727",
16895
16914
  "\u2726"
16896
16915
  ];
16897
- var INTERVAL = 150;
16898
- var MusicSpinner = memo8(({ color }) => {
16899
- const [index, setIndex] = useState5(0);
16900
- useEffect6(() => {
16901
- const timer = setInterval(() => {
16902
- setIndex((i) => (i + 1) % FRAMES.length);
16903
- }, INTERVAL);
16904
- return () => clearInterval(timer);
16905
- }, []);
16906
- return /* @__PURE__ */ jsx9(Text9, { color: color || "yellow", children: FRAMES[index] });
16916
+ var StarSpinner = memo8(({ color }) => {
16917
+ const tick = useAnimationTick();
16918
+ const index = tick % FRAMES.length;
16919
+ return /* @__PURE__ */ jsx10(Text9, { color: color || "yellow", children: FRAMES[index] });
16907
16920
  });
16908
16921
 
16909
16922
  // src/platform/tui/components/status/RetryView.tsx
16910
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
16923
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
16911
16924
  var RetryView = ({ retryState }) => {
16912
16925
  const truncateError = (err) => {
16913
16926
  return err.length > DISPLAY_LIMITS.RETRY_ERROR_PREVIEW ? err.substring(0, DISPLAY_LIMITS.RETRY_ERROR_TRUNCATED) + "..." : err;
16914
16927
  };
16915
16928
  return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", height: 2, children: [
16916
16929
  /* @__PURE__ */ jsxs8(Box9, { children: [
16917
- /* @__PURE__ */ jsx10(Text10, { color: THEME.yellow, wrap: "truncate", children: /* @__PURE__ */ jsx10(MusicSpinner, { color: THEME.yellow }) }),
16930
+ /* @__PURE__ */ jsx11(Text10, { color: THEME.yellow, wrap: "truncate", children: /* @__PURE__ */ jsx11(StarSpinner, { color: THEME.yellow }) }),
16918
16931
  /* @__PURE__ */ jsxs8(Text10, { color: THEME.yellow, bold: true, wrap: "truncate", children: [
16919
16932
  " \u29F3 Retry #",
16920
16933
  retryState.attempt,
@@ -16927,7 +16940,7 @@ var RetryView = ({ retryState }) => {
16927
16940
  "s"
16928
16941
  ] })
16929
16942
  ] }),
16930
- /* @__PURE__ */ jsx10(Box9, { children: /* @__PURE__ */ jsxs8(Text10, { color: THEME.gray, wrap: "truncate", children: [
16943
+ /* @__PURE__ */ jsx11(Box9, { children: /* @__PURE__ */ jsxs8(Text10, { color: THEME.gray, wrap: "truncate", children: [
16931
16944
  " ",
16932
16945
  truncateError(retryState.error)
16933
16946
  ] }) })
@@ -16938,11 +16951,10 @@ var RetryView = ({ retryState }) => {
16938
16951
  import { Box as Box10, Text as Text12 } from "ink";
16939
16952
 
16940
16953
  // src/platform/tui/components/ShimmerText.tsx
16941
- import { useState as useState6, useEffect as useEffect7, memo as memo9 } from "react";
16954
+ import { memo as memo9 } from "react";
16942
16955
  import { Text as Text11 } from "ink";
16943
- import { jsx as jsx11 } from "react/jsx-runtime";
16944
- var FRAME_INTERVAL = 120;
16945
- var WAVE_SPEED = 0.25;
16956
+ import { jsx as jsx12 } from "react/jsx-runtime";
16957
+ var WAVE_SPEED = 0.25 * (120 / ANIM_TICK_MS);
16946
16958
  var CHAR_PHASE_GAP = 0.55;
16947
16959
  function sinToColor(sin) {
16948
16960
  const t = (sin + 1) / 2;
@@ -16951,24 +16963,18 @@ function sinToColor(sin) {
16951
16963
  return `#${hex}${hex}${hex}`;
16952
16964
  }
16953
16965
  var ShimmerText = memo9(({ children, bold, phase = 0 }) => {
16954
- const [tick, setTick] = useState6(0);
16955
- useEffect7(() => {
16956
- const timer = setInterval(() => {
16957
- setTick((t) => t + 1);
16958
- }, FRAME_INTERVAL);
16959
- return () => clearInterval(timer);
16960
- }, []);
16966
+ const tick = useAnimationTick();
16961
16967
  const globalPhase = tick * WAVE_SPEED + phase;
16962
- return /* @__PURE__ */ jsx11(Text11, { bold, children: Array.from(children).map((char, i) => {
16968
+ return /* @__PURE__ */ jsx12(Text11, { bold, children: Array.from(children).map((char, i) => {
16963
16969
  const charPhase = globalPhase - i * CHAR_PHASE_GAP;
16964
16970
  const sin = Math.sin(charPhase);
16965
16971
  const color = sinToColor(sin);
16966
- return /* @__PURE__ */ jsx11(Text11, { color, children: char }, i);
16972
+ return /* @__PURE__ */ jsx12(Text11, { color, children: char }, i);
16967
16973
  }) });
16968
16974
  });
16969
16975
 
16970
16976
  // src/platform/tui/components/status/ProcessingView.tsx
16971
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
16977
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
16972
16978
  var ProcessingView = ({
16973
16979
  statusMain,
16974
16980
  detailText,
@@ -16984,41 +16990,53 @@ var ProcessingView = ({
16984
16990
  return parts.length > 0 ? `(${parts.join(" \xB7 ")})` : "";
16985
16991
  };
16986
16992
  const meta = buildMeta();
16993
+ const parenIdx = statusMain.indexOf("(");
16994
+ const shimmerPart = parenIdx > -1 ? statusMain.slice(0, parenIdx).trimEnd() : statusMain;
16995
+ const staticSuffix = parenIdx > -1 ? " " + statusMain.slice(parenIdx) : "";
16987
16996
  return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", height: 2, children: [
16988
16997
  /* @__PURE__ */ jsxs9(Box10, { children: [
16989
- /* @__PURE__ */ jsx12(Text12, { color, wrap: "truncate", children: /* @__PURE__ */ jsx12(MusicSpinner, { color }) }),
16990
- /* @__PURE__ */ jsx12(Text12, { children: " " }),
16991
- /* @__PURE__ */ jsx12(ShimmerText, { bold: true, phase: 0, children: statusMain }),
16998
+ /* @__PURE__ */ jsx13(Text12, { color, wrap: "truncate", children: /* @__PURE__ */ jsx13(StarSpinner, { color }) }),
16999
+ /* @__PURE__ */ jsx13(Text12, { children: " " }),
17000
+ /* @__PURE__ */ jsx13(ShimmerText, { bold: true, phase: 0, children: shimmerPart }),
17001
+ staticSuffix ? /* @__PURE__ */ jsx13(Text12, { color: THEME.dimGray, wrap: "truncate", children: staticSuffix }) : null,
16992
17002
  /* @__PURE__ */ jsxs9(Text12, { color: THEME.dimGray, wrap: "truncate", children: [
16993
17003
  " ",
16994
17004
  meta
16995
17005
  ] })
16996
17006
  ] }),
16997
- /* @__PURE__ */ jsx12(Box10, { children: detailText ? /* @__PURE__ */ jsxs9(Text12, { color: THEME.dimGray, wrap: "truncate", children: [
17007
+ /* @__PURE__ */ jsx13(Box10, { children: detailText ? /* @__PURE__ */ jsxs9(Text12, { color: THEME.dimGray, wrap: "truncate", children: [
16998
17008
  " ",
16999
17009
  detailText
17000
- ] }) : /* @__PURE__ */ jsx12(Text12, { children: " " }) })
17010
+ ] }) : /* @__PURE__ */ jsx13(Text12, { children: " " }) })
17001
17011
  ] });
17002
17012
  };
17003
17013
 
17004
17014
  // src/platform/tui/components/StatusDisplay.tsx
17005
- import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
17015
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
17006
17016
  var StatusDisplay = memo10(({
17007
17017
  retryState,
17008
17018
  isProcessing,
17009
17019
  currentStatus,
17010
- currentTokens
17020
+ currentTokens,
17021
+ inputRequest
17011
17022
  }) => {
17012
- const statusElapsed = useStatusTimer(currentStatus, isProcessing);
17023
+ const isWaitingForInput = inputRequest?.status === "active";
17024
+ const statusElapsed = useStatusTimer(currentStatus, isProcessing && !isWaitingForInput);
17013
17025
  if (retryState && retryState.status === "retrying") {
17014
- return /* @__PURE__ */ jsx13(RetryView, { retryState });
17026
+ return /* @__PURE__ */ jsx14(RetryView, { retryState });
17027
+ }
17028
+ if (isProcessing && isWaitingForInput) {
17029
+ return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", height: 2, children: [
17030
+ /* @__PURE__ */ jsx14(Text13, { children: " " }),
17031
+ /* @__PURE__ */ jsx14(Text13, { children: " " })
17032
+ ] });
17015
17033
  }
17016
17034
  if (isProcessing) {
17017
17035
  const isThinkingStatus = currentStatus.startsWith("Reasoning");
17018
17036
  const statusLines = currentStatus ? currentStatus.split("\n").filter(Boolean) : [];
17019
17037
  const statusMain = statusLines[0] || "Processing...";
17020
17038
  const detailText = isThinkingStatus && statusLines.length > 1 ? statusLines[statusLines.length - 1].slice(0, 120) : "";
17021
- return /* @__PURE__ */ jsx13(
17039
+ return /* @__PURE__ */ jsx14(
17022
17040
  ProcessingView,
17023
17041
  {
17024
17042
  statusMain,
@@ -17030,37 +17048,37 @@ var StatusDisplay = memo10(({
17030
17048
  );
17031
17049
  }
17032
17050
  return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", height: 2, children: [
17033
- /* @__PURE__ */ jsx13(Text13, { children: " " }),
17034
- /* @__PURE__ */ jsx13(Text13, { children: " " })
17051
+ /* @__PURE__ */ jsx14(Text13, { children: " " }),
17052
+ /* @__PURE__ */ jsx14(Text13, { children: " " })
17035
17053
  ] });
17036
17054
  });
17037
17055
 
17038
17056
  // src/platform/tui/components/ChatInput.tsx
17039
- import { useMemo, useCallback as useCallback9, useRef as useRef8, memo as memo11, useState as useState7, useEffect as useEffect8 } from "react";
17057
+ import { useMemo, useCallback as useCallback9, useRef as useRef8, memo as memo11, useState as useState6, useEffect as useEffect7 } from "react";
17040
17058
  import { Box as Box15, Text as Text17, useInput as useInput3 } from "ink";
17041
17059
 
17042
17060
  // src/platform/tui/components/input/AutocompletePreview.tsx
17043
17061
  import { Box as Box12, Text as Text14 } from "ink";
17044
- import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
17062
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
17045
17063
  var AutocompletePreview = ({
17046
17064
  suggestions,
17047
17065
  clampedIdx
17048
17066
  }) => {
17049
- return /* @__PURE__ */ jsx14(Box12, { flexDirection: "column", paddingX: 1, children: suggestions.map((cmd, i) => {
17067
+ return /* @__PURE__ */ jsx15(Box12, { flexDirection: "column", paddingX: 1, children: suggestions.map((cmd, i) => {
17050
17068
  const isSelected = i === clampedIdx;
17051
17069
  const argsText = cmd.args ? ` ${cmd.args}` : "";
17052
17070
  return /* @__PURE__ */ jsxs11(Box12, { children: [
17053
- /* @__PURE__ */ jsx14(Text14, { color: isSelected ? THEME.primary : THEME.dimGray, children: isSelected ? " \u276F " : " " }),
17071
+ /* @__PURE__ */ jsx15(Text14, { color: isSelected ? THEME.primary : THEME.dimGray, children: isSelected ? " \u276F " : " " }),
17054
17072
  /* @__PURE__ */ jsxs11(Text14, { color: isSelected ? THEME.white : THEME.gray, bold: isSelected, children: [
17055
17073
  "/",
17056
17074
  cmd.name
17057
17075
  ] }),
17058
- /* @__PURE__ */ jsx14(Text14, { dimColor: true, color: THEME.gray, children: argsText }),
17076
+ /* @__PURE__ */ jsx15(Text14, { dimColor: true, color: THEME.gray, children: argsText }),
17059
17077
  /* @__PURE__ */ jsxs11(Text14, { dimColor: true, color: THEME.dimGray, children: [
17060
17078
  " \u2014 ",
17061
17079
  cmd.description
17062
17080
  ] }),
17063
- isSelected && cmd.alias && /* @__PURE__ */ jsx14(Text14, { dimColor: true, color: THEME.dimGray, children: ` (/${cmd.alias})` })
17081
+ isSelected && cmd.alias && /* @__PURE__ */ jsx15(Text14, { dimColor: true, color: THEME.dimGray, children: ` (/${cmd.alias})` })
17064
17082
  ] }, cmd.name);
17065
17083
  }) });
17066
17084
  };
@@ -17068,7 +17086,7 @@ var AutocompletePreview = ({
17068
17086
  // src/platform/tui/components/input/SecretInputArea.tsx
17069
17087
  import { Box as Box13, Text as Text15, useStdout } from "ink";
17070
17088
  import TextInput from "ink-text-input";
17071
- import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
17089
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
17072
17090
  var OUTER_PADDING = 2;
17073
17091
  var SecretInputArea = ({
17074
17092
  inputRequest,
@@ -17080,34 +17098,28 @@ var SecretInputArea = ({
17080
17098
  const borderWidth = Math.max(10, (stdout?.columns ?? 80) - OUTER_PADDING);
17081
17099
  const borderLine = "\u2501".repeat(borderWidth);
17082
17100
  return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", children: [
17083
- /* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(Text15, { color: THEME.yellow, children: borderLine }) }),
17084
- /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingX: 1, children: [
17085
- /* @__PURE__ */ jsxs12(Box13, { children: [
17086
- /* @__PURE__ */ jsx15(Text15, { color: THEME.yellow, bold: true, children: "\u{1F512} " }),
17087
- /* @__PURE__ */ jsx15(Text15, { color: THEME.yellow, children: inputRequest.prompt && inputRequest.prompt.length > 68 ? inputRequest.prompt.slice(0, 68) + "\u2026" : inputRequest.prompt })
17088
- ] }),
17089
- /* @__PURE__ */ jsxs12(Box13, { children: [
17090
- /* @__PURE__ */ jsx15(Text15, { color: THEME.yellow, children: " \u25B8 " }),
17091
- /* @__PURE__ */ jsx15(
17092
- TextInput,
17093
- {
17094
- value: secretInput,
17095
- onChange: setSecretInput,
17096
- onSubmit: onSecretSubmit,
17097
- placeholder: "(type and press Enter)",
17098
- mask: inputRequest.isPassword ? "\u2022" : void 0
17099
- }
17100
- )
17101
- ] })
17101
+ /* @__PURE__ */ jsx16(Box13, { children: /* @__PURE__ */ jsx16(Text15, { color: THEME.yellow, children: borderLine }) }),
17102
+ /* @__PURE__ */ jsxs12(Box13, { paddingX: 1, children: [
17103
+ /* @__PURE__ */ jsx16(Text15, { color: THEME.yellow, bold: true, children: "\u25B8 " }),
17104
+ /* @__PURE__ */ jsx16(
17105
+ TextInput,
17106
+ {
17107
+ value: secretInput,
17108
+ onChange: setSecretInput,
17109
+ onSubmit: onSecretSubmit,
17110
+ placeholder: inputRequest.isPassword ? "(hidden \xB7 press Enter)" : "(type and press Enter)",
17111
+ mask: inputRequest.isPassword ? "\u2022" : void 0
17112
+ }
17113
+ )
17102
17114
  ] }),
17103
- /* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(Text15, { color: THEME.yellow, children: borderLine }) })
17115
+ /* @__PURE__ */ jsx16(Box13, { children: /* @__PURE__ */ jsx16(Text15, { color: THEME.yellow, children: borderLine }) })
17104
17116
  ] });
17105
17117
  };
17106
17118
 
17107
17119
  // src/platform/tui/components/input/NormalInputArea.tsx
17108
17120
  import { Box as Box14, Text as Text16, useStdout as useStdout2 } from "ink";
17109
17121
  import TextInput2 from "ink-text-input";
17110
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
17122
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
17111
17123
  var OUTER_PADDING2 = 2;
17112
17124
  var NormalInputArea = ({
17113
17125
  inputKey,
@@ -17120,10 +17132,10 @@ var NormalInputArea = ({
17120
17132
  const borderWidth = Math.max(10, (stdout?.columns ?? 80) - OUTER_PADDING2);
17121
17133
  const borderLine = "\u2500".repeat(borderWidth);
17122
17134
  return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", children: [
17123
- /* @__PURE__ */ jsx16(Box14, { children: /* @__PURE__ */ jsx16(Text16, { dimColor: true, color: THEME.dimGray, children: borderLine }) }),
17135
+ /* @__PURE__ */ jsx17(Box14, { children: /* @__PURE__ */ jsx17(Text16, { dimColor: true, color: THEME.dimGray, children: borderLine }) }),
17124
17136
  /* @__PURE__ */ jsxs13(Box14, { paddingX: 1, children: [
17125
- /* @__PURE__ */ jsx16(Text16, { color: THEME.primary, children: "\u276F " }),
17126
- /* @__PURE__ */ jsx16(
17137
+ /* @__PURE__ */ jsx17(Text16, { color: THEME.primary, children: "\u276F " }),
17138
+ /* @__PURE__ */ jsx17(
17127
17139
  TextInput2,
17128
17140
  {
17129
17141
  value,
@@ -17134,12 +17146,12 @@ var NormalInputArea = ({
17134
17146
  inputKey
17135
17147
  )
17136
17148
  ] }),
17137
- /* @__PURE__ */ jsx16(Box14, { children: /* @__PURE__ */ jsx16(Text16, { dimColor: true, color: THEME.dimGray, children: borderLine }) })
17149
+ /* @__PURE__ */ jsx17(Box14, { children: /* @__PURE__ */ jsx17(Text16, { dimColor: true, color: THEME.dimGray, children: borderLine }) })
17138
17150
  ] });
17139
17151
  };
17140
17152
 
17141
17153
  // src/platform/tui/components/ChatInput.tsx
17142
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
17154
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
17143
17155
  var MAX_SUGGESTIONS = 6;
17144
17156
  var ChatInput = memo11(({
17145
17157
  value,
@@ -17159,7 +17171,7 @@ var ChatInput = memo11(({
17159
17171
  return getMatchingCommands(partialCmd).slice(0, MAX_SUGGESTIONS);
17160
17172
  }, [isSlashMode, partialCmd, hasArgs]);
17161
17173
  const showPreview = isSlashMode && !hasArgs && suggestions.length > 0;
17162
- const [selectedIdx, setSelectedIdx] = useState7(0);
17174
+ const [selectedIdx, setSelectedIdx] = useState6(0);
17163
17175
  const clampedIdx = Math.min(selectedIdx, Math.max(0, suggestions.length - 1));
17164
17176
  const selectedIdxRef = useRef8(clampedIdx);
17165
17177
  selectedIdxRef.current = clampedIdx;
@@ -17175,10 +17187,10 @@ var ChatInput = memo11(({
17175
17187
  inputRequestRef.current = inputRequest;
17176
17188
  const onChangeRef = useRef8(onChange);
17177
17189
  onChangeRef.current = onChange;
17178
- const [pastedHint, setPastedHint] = useState7(null);
17190
+ const [pastedHint, setPastedHint] = useState6(null);
17179
17191
  const prevValueRef = useRef8(value);
17180
17192
  const pasteTimerRef = useRef8(null);
17181
- useEffect8(() => {
17193
+ useEffect7(() => {
17182
17194
  const diff = value.length - prevValueRef.current.length;
17183
17195
  if (diff > 20) {
17184
17196
  if (pasteTimerRef.current) clearTimeout(pasteTimerRef.current);
@@ -17190,7 +17202,7 @@ var ChatInput = memo11(({
17190
17202
  if (pasteTimerRef.current) clearTimeout(pasteTimerRef.current);
17191
17203
  };
17192
17204
  }, [value]);
17193
- const [inputKey, setInputKey] = useState7(0);
17205
+ const [inputKey, setInputKey] = useState6(0);
17194
17206
  const completeCommand = useCallback9((idx) => {
17195
17207
  const sug = suggestionsRef.current;
17196
17208
  if (!sug.length) return;
@@ -17239,7 +17251,7 @@ var ChatInput = memo11(({
17239
17251
  }
17240
17252
  }, [completeCommand]));
17241
17253
  return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", children: [
17242
- showPreview && /* @__PURE__ */ jsx17(
17254
+ showPreview && /* @__PURE__ */ jsx18(
17243
17255
  AutocompletePreview,
17244
17256
  {
17245
17257
  suggestions,
@@ -17248,7 +17260,7 @@ var ChatInput = memo11(({
17248
17260
  ),
17249
17261
  inputRequest.status === "active" ? (
17250
17262
  /* Active input request — yellow top/bottom border */
17251
- /* @__PURE__ */ jsx17(
17263
+ /* @__PURE__ */ jsx18(
17252
17264
  SecretInputArea,
17253
17265
  {
17254
17266
  inputRequest,
@@ -17259,7 +17271,7 @@ var ChatInput = memo11(({
17259
17271
  )
17260
17272
  ) : (
17261
17273
  /* Normal input — dim top/bottom border */
17262
- /* @__PURE__ */ jsx17(
17274
+ /* @__PURE__ */ jsx18(
17263
17275
  NormalInputArea,
17264
17276
  {
17265
17277
  inputKey,
@@ -17270,14 +17282,14 @@ var ChatInput = memo11(({
17270
17282
  }
17271
17283
  )
17272
17284
  ),
17273
- pastedHint && /* @__PURE__ */ jsx17(Box15, { paddingX: 2, children: /* @__PURE__ */ jsx17(Text17, { dimColor: true, color: THEME.dimGray, children: pastedHint }) })
17285
+ pastedHint && /* @__PURE__ */ jsx18(Box15, { paddingX: 2, children: /* @__PURE__ */ jsx18(Text17, { dimColor: true, color: THEME.dimGray, children: pastedHint }) })
17274
17286
  ] });
17275
17287
  });
17276
17288
 
17277
17289
  // src/platform/tui/components/footer.tsx
17278
17290
  import { memo as memo12 } from "react";
17279
17291
  import { Box as Box16, Text as Text18 } from "ink";
17280
- import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
17292
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
17281
17293
  var CTX_WARN_THRESHOLD = 0.8;
17282
17294
  var MAX_CONTEXT_TOKENS = LLM_LIMITS.streamMaxTokens;
17283
17295
  var formatElapsed = (totalSeconds) => {
@@ -17304,26 +17316,26 @@ var Footer = memo12(({ phase, targets, findings, todo, elapsedTime, isProcessing
17304
17316
  /* @__PURE__ */ jsxs15(Box16, { gap: 2, children: [
17305
17317
  /* @__PURE__ */ jsxs15(Text18, { color: THEME.gray, children: [
17306
17318
  "Phase: ",
17307
- /* @__PURE__ */ jsx18(Text18, { color: THEME.white, children: phase })
17319
+ /* @__PURE__ */ jsx19(Text18, { color: THEME.white, children: phase })
17308
17320
  ] }),
17309
17321
  /* @__PURE__ */ jsxs15(Text18, { color: THEME.gray, children: [
17310
17322
  "Targets: ",
17311
- /* @__PURE__ */ jsx18(Text18, { color: THEME.white, children: targets })
17323
+ /* @__PURE__ */ jsx19(Text18, { color: THEME.white, children: targets })
17312
17324
  ] }),
17313
17325
  /* @__PURE__ */ jsxs15(Text18, { color: THEME.gray, children: [
17314
17326
  "Findings: ",
17315
- /* @__PURE__ */ jsx18(Text18, { color: THEME.white, children: findings })
17327
+ /* @__PURE__ */ jsx19(Text18, { color: THEME.white, children: findings })
17316
17328
  ] }),
17317
17329
  /* @__PURE__ */ jsxs15(Text18, { color: THEME.gray, children: [
17318
17330
  "Tasks: ",
17319
- /* @__PURE__ */ jsx18(Text18, { color: THEME.white, children: todo })
17331
+ /* @__PURE__ */ jsx19(Text18, { color: THEME.white, children: todo })
17320
17332
  ] })
17321
17333
  ] }),
17322
17334
  /* @__PURE__ */ jsxs15(Box16, { gap: 2, children: [
17323
17335
  isProcessing ? /* @__PURE__ */ jsxs15(Box16, { gap: 1, children: [
17324
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, color: THEME.dimGray, children: "[ESC] abort" }),
17325
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, color: THEME.dimGray, children: "[^C\xD72] exit" })
17326
- ] }) : /* @__PURE__ */ jsx18(Text18, { dimColor: true, color: THEME.dimGray, children: "[/help] commands" }),
17336
+ /* @__PURE__ */ jsx19(Text18, { dimColor: true, color: THEME.dimGray, children: "[ESC] abort" }),
17337
+ /* @__PURE__ */ jsx19(Text18, { dimColor: true, color: THEME.dimGray, children: "[^C\xD72] exit" })
17338
+ ] }) : /* @__PURE__ */ jsx19(Text18, { dimColor: true, color: THEME.dimGray, children: "[/help] commands" }),
17327
17339
  turnCount > 0 && /* @__PURE__ */ jsxs15(Text18, { dimColor: true, color: THEME.dimGray, children: [
17328
17340
  "turn:",
17329
17341
  turnCount
@@ -17337,8 +17349,8 @@ var Footer = memo12(({ phase, targets, findings, todo, elapsedTime, isProcessing
17337
17349
  "\u2191",
17338
17350
  formatTokens(totalTokens)
17339
17351
  ] }),
17340
- /* @__PURE__ */ jsx18(Text18, { color: isProcessing ? THEME.primary : THEME.gray, children: isProcessing ? "Running " : "Idle " }),
17341
- /* @__PURE__ */ jsx18(Text18, { color: THEME.white, children: formatElapsed(elapsedTime) })
17352
+ /* @__PURE__ */ jsx19(Text18, { color: isProcessing ? THEME.primary : THEME.gray, children: isProcessing ? "Running " : "Idle " }),
17353
+ /* @__PURE__ */ jsx19(Text18, { color: THEME.white, children: formatElapsed(elapsedTime) })
17342
17354
  ] })
17343
17355
  ]
17344
17356
  }
@@ -17349,7 +17361,7 @@ var footer_default = Footer;
17349
17361
  // src/platform/tui/components/Modal.tsx
17350
17362
  import { useMemo as useMemo2, memo as memo13, useCallback as useCallback10, useRef as useRef9 } from "react";
17351
17363
  import { Box as Box17, Text as Text19, useStdout as useStdout3, useInput as useInput4 } from "ink";
17352
- import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
17364
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
17353
17365
  var MODAL_TITLES = {
17354
17366
  findings: "\u25C8 FINDINGS \u25C8",
17355
17367
  graph: "\u25C8 ATTACK GRAPH \u25C8",
@@ -17400,12 +17412,12 @@ var Modal = memo13(({
17400
17412
  width: terminalWidth,
17401
17413
  height: terminalHeight,
17402
17414
  children: [
17403
- /* @__PURE__ */ jsx19(Box17, { justifyContent: "center", marginBottom: 0, children: /* @__PURE__ */ jsx19(Text19, { color: THEME.cyan, bold: true, children: (() => {
17415
+ /* @__PURE__ */ jsx20(Box17, { justifyContent: "center", marginBottom: 0, children: /* @__PURE__ */ jsx20(Text19, { color: THEME.cyan, bold: true, children: (() => {
17404
17416
  const title = MODAL_TITLES[type];
17405
17417
  const sideWidth = Math.max(3, Math.floor((terminalWidth - title.length - 2) / 2));
17406
17418
  return `${"\u2500".repeat(sideWidth)} ${title} ${"\u2500".repeat(sideWidth)}`;
17407
17419
  })() }) }),
17408
- /* @__PURE__ */ jsx19(
17420
+ /* @__PURE__ */ jsx20(
17409
17421
  Box17,
17410
17422
  {
17411
17423
  flexDirection: "column",
@@ -17416,15 +17428,15 @@ var Modal = memo13(({
17416
17428
  children: visibleLines.map((line, i) => {
17417
17429
  const showScrollbar = totalLines > maxHeight && i >= scrollbarPosition && i < scrollbarPosition + scrollbarHeight;
17418
17430
  return /* @__PURE__ */ jsxs16(Box17, { children: [
17419
- /* @__PURE__ */ jsx19(Text19, { color: THEME.white, wrap: "truncate", children: line }),
17420
- /* @__PURE__ */ jsx19(Box17, { flexGrow: 1 }),
17421
- totalLines > maxHeight && /* @__PURE__ */ jsx19(Text19, { color: showScrollbar ? THEME.cyan : THEME.dimGray, children: showScrollbar ? "\u2588" : "\u2502" })
17431
+ /* @__PURE__ */ jsx20(Text19, { color: THEME.white, wrap: "truncate", children: line }),
17432
+ /* @__PURE__ */ jsx20(Box17, { flexGrow: 1 }),
17433
+ totalLines > maxHeight && /* @__PURE__ */ jsx20(Text19, { color: showScrollbar ? THEME.cyan : THEME.dimGray, children: showScrollbar ? "\u2588" : "\u2502" })
17422
17434
  ] }, i);
17423
17435
  })
17424
17436
  }
17425
17437
  ),
17426
17438
  /* @__PURE__ */ jsxs16(Box17, { justifyContent: "space-between", paddingX: 1, children: [
17427
- /* @__PURE__ */ jsx19(Text19, { dimColor: true, color: THEME.gray, children: "\u2191\u2193/jk: scroll | g/G: top/bottom | ESC/q: close" }),
17439
+ /* @__PURE__ */ jsx20(Text19, { dimColor: true, color: THEME.gray, children: "\u2191\u2193/jk: scroll | g/G: top/bottom | ESC/q: close" }),
17428
17440
  /* @__PURE__ */ jsxs16(Text19, { dimColor: true, color: THEME.cyan, children: [
17429
17441
  startLine,
17430
17442
  "-",
@@ -17440,7 +17452,7 @@ var Modal = memo13(({
17440
17452
 
17441
17453
  // src/platform/tui/components/app/bottom-region.tsx
17442
17454
  import { Box as Box18 } from "ink";
17443
- import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
17455
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
17444
17456
  var BottomRegion = ({
17445
17457
  input,
17446
17458
  setInput,
@@ -17463,19 +17475,19 @@ var BottomRegion = ({
17463
17475
  const hasArgs = isSlashMode && input.includes(" ");
17464
17476
  const suggestionCount = isSlashMode && !hasArgs && inputRequest.status !== "active" ? Math.min(getMatchingCommands(partialCmd).length, MAX_SUGGESTIONS) : 0;
17465
17477
  const previewHeight = suggestionCount;
17466
- const inputExtraHeight = inputRequest.status === "active" ? 1 : 0;
17467
- const bottomMinHeight = 7 + inputExtraHeight;
17478
+ const bottomMinHeight = 7;
17468
17479
  return /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", minHeight: bottomMinHeight, children: [
17469
- /* @__PURE__ */ jsx20(
17480
+ /* @__PURE__ */ jsx21(
17470
17481
  StatusDisplay,
17471
17482
  {
17472
17483
  retryState,
17473
17484
  isProcessing,
17474
17485
  currentStatus,
17475
- currentTokens
17486
+ currentTokens,
17487
+ inputRequest
17476
17488
  }
17477
17489
  ),
17478
- /* @__PURE__ */ jsx20(
17490
+ /* @__PURE__ */ jsx21(
17479
17491
  ChatInput,
17480
17492
  {
17481
17493
  value: input,
@@ -17488,7 +17500,7 @@ var BottomRegion = ({
17488
17500
  onSecretSubmit: handleSecretSubmit
17489
17501
  }
17490
17502
  ),
17491
- /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(
17503
+ /* @__PURE__ */ jsx21(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx21(
17492
17504
  footer_default,
17493
17505
  {
17494
17506
  phase: stats.phase,
@@ -17505,16 +17517,16 @@ var BottomRegion = ({
17505
17517
  };
17506
17518
 
17507
17519
  // src/platform/tui/app.tsx
17508
- import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
17520
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
17509
17521
  var MODEL_NAME = getModel() || DEFAULT_MODEL;
17510
17522
  var App = ({ autoApprove = false, target }) => {
17511
17523
  const { exit } = useApp();
17512
17524
  const { stdout } = useStdout4();
17513
17525
  const terminalWidth = stdout?.columns ?? 80;
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 });
17526
+ const [input, setInput] = useState7("");
17527
+ const [secretInput, setSecretInput] = useState7("");
17528
+ const [autoApproveMode, setAutoApproveMode] = useState7(autoApprove);
17529
+ const [modal, setModal] = useState7({ type: null, content: "", scrollOffset: 0 });
17518
17530
  const {
17519
17531
  agent,
17520
17532
  messages,
@@ -17547,7 +17559,7 @@ var App = ({ autoApprove = false, target }) => {
17547
17559
  const clearInput = useCallback11(() => {
17548
17560
  setInput("");
17549
17561
  }, []);
17550
- const [historyScrollOffset, setHistoryScrollOffset] = useState8(0);
17562
+ const [historyScrollOffset, setHistoryScrollOffset] = useState7(0);
17551
17563
  const handleScroll = useCallback11((delta) => {
17552
17564
  setHistoryScrollOffset((prev) => Math.max(0, prev - delta));
17553
17565
  }, []);
@@ -17614,9 +17626,8 @@ var App = ({ autoApprove = false, target }) => {
17614
17626
  const handleSecretSubmit = useCallback11((value) => {
17615
17627
  const ir = inputRequestRef.current;
17616
17628
  if (ir.status !== "active") return;
17617
- const displayText = ir.isPassword ? "\u2022".repeat(value.length) : value;
17618
- const promptLabel = ir.prompt || "Input";
17619
- addMessage("system", `\u21B3 ${promptLabel} ${displayText}`);
17629
+ const displayText = ir.isPassword ? "\u2022".repeat(Math.min(value.length, 20)) : value;
17630
+ addMessage("system", `\u21B3 ${displayText}`);
17620
17631
  ir.resolve(value);
17621
17632
  setInputRequest({ status: "inactive" });
17622
17633
  setSecretInput("");
@@ -17634,7 +17645,7 @@ var App = ({ autoApprove = false, target }) => {
17634
17645
  onScroll: handleScroll
17635
17646
  });
17636
17647
  if (modal.type) {
17637
- return /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", paddingX: 1, width: terminalWidth, children: /* @__PURE__ */ jsx21(
17648
+ return /* @__PURE__ */ jsx22(Box19, { flexDirection: "column", paddingX: 1, width: terminalWidth, children: /* @__PURE__ */ jsx22(
17638
17649
  Modal,
17639
17650
  {
17640
17651
  type: modal.type,
@@ -17646,7 +17657,7 @@ var App = ({ autoApprove = false, target }) => {
17646
17657
  ) });
17647
17658
  }
17648
17659
  return /* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", paddingX: 1, width: terminalWidth, children: [
17649
- /* @__PURE__ */ jsx21(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx21(
17660
+ /* @__PURE__ */ jsx22(Box19, { flexDirection: "column", children: /* @__PURE__ */ jsx22(
17650
17661
  MessageList,
17651
17662
  {
17652
17663
  messages,
@@ -17657,7 +17668,7 @@ var App = ({ autoApprove = false, target }) => {
17657
17668
  scrollOffset: historyScrollOffset
17658
17669
  }
17659
17670
  ) }),
17660
- /* @__PURE__ */ jsx21(
17671
+ /* @__PURE__ */ jsx22(
17661
17672
  BottomRegion,
17662
17673
  {
17663
17674
  input,
@@ -17682,7 +17693,7 @@ var App = ({ autoApprove = false, target }) => {
17682
17693
  var app_default = App;
17683
17694
 
17684
17695
  // src/platform/tui/cli/commands/interactive.tsx
17685
- import { jsx as jsx22 } from "react/jsx-runtime";
17696
+ import { jsx as jsx23 } from "react/jsx-runtime";
17686
17697
  async function interactiveAction(options) {
17687
17698
  const { dangerouslySkipPermissions: skipPermissions = false, target } = options;
17688
17699
  console.clear();
@@ -17691,13 +17702,13 @@ async function interactiveAction(options) {
17691
17702
  console.log(chalk.hex(HEX.red)("[!] All tool executions will be auto-approved!\n"));
17692
17703
  }
17693
17704
  const { waitUntilExit } = render(
17694
- /* @__PURE__ */ jsx22(
17705
+ /* @__PURE__ */ jsx23(AnimationProvider, { children: /* @__PURE__ */ jsx23(
17695
17706
  app_default,
17696
17707
  {
17697
17708
  autoApprove: skipPermissions,
17698
17709
  target
17699
17710
  }
17700
- )
17711
+ ) })
17701
17712
  );
17702
17713
  await waitUntilExit();
17703
17714
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pentesting",
3
- "version": "0.70.4",
3
+ "version": "0.70.5",
4
4
  "description": "Autonomous Penetration Testing AI Agent",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",