pentesting 0.44.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -12,11 +12,11 @@ import { Command } from "commander";
12
12
  import chalk from "chalk";
13
13
 
14
14
  // src/platform/tui/app.tsx
15
- import { useState as useState4, useCallback as useCallback4, useEffect as useEffect4, useRef as useRef4 } from "react";
15
+ import { useState as useState5, useCallback as useCallback4, useEffect as useEffect4, useRef as useRef5 } from "react";
16
16
  import { Box as Box6, useInput as useInput2, useApp } from "ink";
17
17
 
18
18
  // src/platform/tui/hooks/useAgent.ts
19
- import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2, useRef as useRef2 } from "react";
19
+ import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2, useRef as useRef3 } from "react";
20
20
 
21
21
  // src/shared/constants/timing.ts
22
22
  var TOOL_TIMEOUTS = {
@@ -311,7 +311,7 @@ var ORPHAN_PROCESS_NAMES = [
311
311
 
312
312
  // src/shared/constants/agent.ts
313
313
  var APP_NAME = "Pentest AI";
314
- var APP_VERSION = "0.44.0";
314
+ var APP_VERSION = "0.45.0";
315
315
  var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
316
316
  var LLM_ROLES = {
317
317
  SYSTEM: "system",
@@ -676,6 +676,7 @@ var EVENT_TYPES = {
676
676
  REASONING_START: "reasoning_start",
677
677
  REASONING_DELTA: "reasoning_delta",
678
678
  REASONING_END: "reasoning_end",
679
+ AI_RESPONSE: "ai_response",
679
680
  TOOL_CALL: "tool_call",
680
681
  TOOL_RESULT: "tool_result",
681
682
  ERROR: "error",
@@ -3903,6 +3904,21 @@ var NOISE_CLASSIFICATION = {
3903
3904
  "gobuster",
3904
3905
  "dirsearch",
3905
3906
  "feroxbuster"
3907
+ ],
3908
+ LOW_VISIBILITY: [
3909
+ // State management — pure bookkeeping, zero operator value
3910
+ "update_mission",
3911
+ "get_state",
3912
+ "update_phase",
3913
+ "update_todo",
3914
+ "add_target",
3915
+ "add_finding",
3916
+ "add_loot",
3917
+ "set_scope",
3918
+ // Resource health checks — noisy periodic calls
3919
+ "bg_status",
3920
+ "bg_cleanup",
3921
+ "health_check"
3906
3922
  ]
3907
3923
  };
3908
3924
 
@@ -5138,7 +5154,9 @@ var ENV_KEYS = {
5138
5154
  BASE_URL: "PENTEST_BASE_URL",
5139
5155
  MODEL: "PENTEST_MODEL",
5140
5156
  SEARCH_API_KEY: "SEARCH_API_KEY",
5141
- SEARCH_API_URL: "SEARCH_API_URL"
5157
+ SEARCH_API_URL: "SEARCH_API_URL",
5158
+ THINKING: "PENTEST_THINKING",
5159
+ THINKING_BUDGET: "PENTEST_THINKING_BUDGET"
5142
5160
  };
5143
5161
  var DEFAULT_SEARCH_API_URL = "https://api.search.brave.com/res/v1/web/search";
5144
5162
  function getApiKey() {
@@ -5156,6 +5174,13 @@ function getSearchApiKey() {
5156
5174
  function getSearchApiUrl() {
5157
5175
  return process.env[ENV_KEYS.SEARCH_API_URL] || DEFAULT_SEARCH_API_URL;
5158
5176
  }
5177
+ function isThinkingEnabled() {
5178
+ return process.env[ENV_KEYS.THINKING] === "true";
5179
+ }
5180
+ function getThinkingBudget() {
5181
+ const val = parseInt(process.env[ENV_KEYS.THINKING_BUDGET] || "", 10);
5182
+ return isNaN(val) ? 8e3 : Math.max(1024, val);
5183
+ }
5159
5184
  function isBrowserHeadless() {
5160
5185
  return true;
5161
5186
  }
@@ -8818,6 +8843,8 @@ var LLM_BLOCK_TYPE = {
8818
8843
  var LLM_DELTA_TYPE = {
8819
8844
  TEXT_DELTA: "text_delta",
8820
8845
  THINKING_DELTA: "thinking_delta",
8846
+ REASONING_DELTA: "reasoning_delta",
8847
+ // Used by some providers (GLM, DeepSeek)
8821
8848
  INPUT_JSON_DELTA: "input_json_delta"
8822
8849
  };
8823
8850
 
@@ -8967,6 +8994,8 @@ var LLMClient = class {
8967
8994
  headers: {
8968
8995
  [LLM_HEADER.CONTENT_TYPE]: LLM_CONTENT_TYPE.JSON,
8969
8996
  [LLM_HEADER.API_KEY]: this.apiKey,
8997
+ // Also send as Bearer for OpenAI-compat proxies (z.ai, GLM, etc.)
8998
+ [LLM_HEADER.AUTHORIZATION]: `${LLM_HEADER.BEARER_PREFIX} ${this.apiKey}`,
8970
8999
  [LLM_HEADER.ANTHROPIC_VERSION]: LLM_API.VERSION
8971
9000
  },
8972
9001
  body: JSON.stringify(body),
@@ -8981,14 +9010,16 @@ var LLMClient = class {
8981
9010
  return response;
8982
9011
  }
8983
9012
  async executeNonStream(messages, tools, systemPrompt) {
9013
+ const thinking = isThinkingEnabled() ? { type: "enabled", budget_tokens: getThinkingBudget() } : void 0;
8984
9014
  const requestBody = {
8985
9015
  model: this.model,
8986
9016
  max_tokens: LLM_LIMITS.nonStreamMaxTokens,
8987
9017
  system: systemPrompt,
8988
9018
  messages: this.convertMessages(messages),
8989
- tools
9019
+ tools,
9020
+ ...thinking && { thinking }
8990
9021
  };
8991
- debugLog("llm", "Non-stream request", { model: this.model, toolCount: tools?.length });
9022
+ debugLog("llm", "Non-stream request", { model: this.model, toolCount: tools?.length, thinking: !!thinking });
8992
9023
  const response = await this.makeRequest(requestBody);
8993
9024
  const data = await response.json();
8994
9025
  const textBlock = data.content.find((b) => b.type === "text");
@@ -9004,15 +9035,17 @@ var LLMClient = class {
9004
9035
  async executeStream(messages, tools, systemPrompt, callbacks) {
9005
9036
  this.requestCount++;
9006
9037
  const requestId = this.requestCount;
9038
+ const thinking = isThinkingEnabled() ? { type: "enabled", budget_tokens: getThinkingBudget() } : void 0;
9007
9039
  const requestBody = {
9008
9040
  model: this.model,
9009
9041
  max_tokens: LLM_LIMITS.streamMaxTokens,
9010
9042
  system: systemPrompt,
9011
9043
  messages: this.convertMessages(messages),
9012
9044
  tools,
9013
- stream: true
9045
+ stream: true,
9046
+ ...thinking && { thinking }
9014
9047
  };
9015
- debugLog("llm", `[${requestId}] Stream request START`, { model: this.model, toolCount: tools?.length, toolNames: tools?.map((t) => t.name) });
9048
+ debugLog("llm", `[${requestId}] Stream request START`, { model: this.model, toolCount: tools?.length, toolNames: tools?.map((t) => t.name), thinking: !!thinking });
9016
9049
  const response = await this.makeRequest(requestBody, callbacks?.abortSignal);
9017
9050
  let fullContent = "";
9018
9051
  let fullReasoning = "";
@@ -9020,6 +9053,7 @@ var LLMClient = class {
9020
9053
  let usage = { input_tokens: 0, output_tokens: 0 };
9021
9054
  let totalChars = 0;
9022
9055
  let wasAborted = false;
9056
+ const currentBlockRef = { value: null };
9023
9057
  const reader = response.body?.getReader();
9024
9058
  if (!reader) throw new Error("Response body is not readable");
9025
9059
  const decoder = new TextDecoder();
@@ -9070,7 +9104,8 @@ var LLMClient = class {
9070
9104
  onUsage: (u) => {
9071
9105
  usage = u;
9072
9106
  },
9073
- getTotalChars: () => totalChars
9107
+ getTotalChars: () => totalChars,
9108
+ currentBlockRef
9074
9109
  });
9075
9110
  } catch {
9076
9111
  }
@@ -9100,28 +9135,53 @@ var LLMClient = class {
9100
9135
  toolCalls.push({ id: toolCall.id, name: toolCall.name, input: toolCall.input });
9101
9136
  }
9102
9137
  debugLog("llm", `[${requestId}] FINAL toolCalls`, { count: toolCalls.length, tools: toolCalls.map((t) => ({ id: t.id, name: t.name, input: t.input })) });
9138
+ const stripped = this.stripThinkTags(fullContent, fullReasoning);
9103
9139
  return {
9104
- content: fullContent,
9140
+ content: stripped.cleanText,
9105
9141
  toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
9106
9142
  rawResponse: null,
9107
- reasoning: fullReasoning || void 0,
9143
+ reasoning: stripped.extractedReasoning || void 0,
9108
9144
  usage: usage.input_tokens > 0 || usage.output_tokens > 0 ? usage : void 0,
9109
9145
  error: wasAborted ? { type: LLM_ERROR_TYPES.UNKNOWN, message: "Stream aborted", isRetryable: false } : void 0
9110
9146
  };
9111
9147
  }
9148
+ /**
9149
+ * Strip inline <think>...</think> XML reasoning tags from LLM text output.
9150
+ *
9151
+ * WHY: Some providers (GLM, DeepSeek, Qwen) output reasoning inline
9152
+ * in text deltas as <think>content</think> instead of separate SSE blocks.
9153
+ * Without stripping, raw tags like "</think>" appear literally in TUI output.
9154
+ *
9155
+ * @param text - Raw text content potentially containing think tags
9156
+ * @param existingReasoning - Accumulated reasoning from SSE reasoning blocks
9157
+ * @returns cleanText (tags removed) and extractedReasoning (tag content appended)
9158
+ */
9159
+ stripThinkTags(text, existingReasoning) {
9160
+ let cleanText = text;
9161
+ let extractedReasoning = existingReasoning;
9162
+ cleanText = cleanText.replace(/<think>([\s\S]*?)<\/think>/gi, (_match, inner) => {
9163
+ extractedReasoning += inner;
9164
+ return "";
9165
+ });
9166
+ cleanText = cleanText.replace(/<\/?think>/gi, "");
9167
+ return { cleanText, extractedReasoning };
9168
+ }
9112
9169
  processStreamEvent(event, requestId, context) {
9113
- const { toolCallsMap, callbacks, onTextStart, onReasoningStart, onTextEnd, onReasoningEnd, onContent, onReasoning, onUsage, getTotalChars } = context;
9170
+ const { toolCallsMap, callbacks, onTextStart, onReasoningStart, onTextEnd, onReasoningEnd, onContent, onReasoning, onUsage, getTotalChars, currentBlockRef } = context;
9114
9171
  switch (event.type) {
9115
9172
  case LLM_SSE_EVENT.CONTENT_BLOCK_START:
9116
9173
  if (event.content_block) {
9117
9174
  const blockType = event.content_block.type;
9118
9175
  if (blockType === LLM_BLOCK_TYPE.TEXT) {
9176
+ currentBlockRef.value = "text";
9119
9177
  onTextStart();
9120
9178
  callbacks?.onOutputStart?.();
9121
9179
  } else if (blockType === LLM_BLOCK_TYPE.THINKING || blockType === LLM_BLOCK_TYPE.REASONING) {
9180
+ currentBlockRef.value = "reasoning";
9122
9181
  onReasoningStart();
9123
9182
  callbacks?.onReasoningStart?.();
9124
9183
  } else if (blockType === LLM_BLOCK_TYPE.TOOL_USE) {
9184
+ currentBlockRef.value = "tool_use";
9125
9185
  toolCallsMap.set(event.content_block.id || "", {
9126
9186
  id: event.content_block.id || "",
9127
9187
  name: event.content_block.name || "",
@@ -9137,9 +9197,13 @@ var LLMClient = class {
9137
9197
  if (event.delta.type === LLM_DELTA_TYPE.TEXT_DELTA && event.delta.text) {
9138
9198
  onContent(event.delta.text);
9139
9199
  callbacks?.onOutputDelta?.(event.delta.text);
9140
- } else if (event.delta.type === LLM_DELTA_TYPE.THINKING_DELTA && event.delta.thinking) {
9141
- onReasoning(event.delta.thinking);
9142
- callbacks?.onReasoningDelta?.(event.delta.thinking);
9200
+ } else if (
9201
+ // Anthropic: thinking_delta / GLM-DeepSeek: reasoning_delta
9202
+ event.delta.type === LLM_DELTA_TYPE.THINKING_DELTA && event.delta.thinking || event.delta.type === LLM_DELTA_TYPE.REASONING_DELTA && event.delta.reasoning
9203
+ ) {
9204
+ const chunk = event.delta.thinking || event.delta.reasoning || "";
9205
+ onReasoning(chunk);
9206
+ callbacks?.onReasoningDelta?.(chunk);
9143
9207
  } else if (event.delta.type === LLM_DELTA_TYPE.INPUT_JSON_DELTA && event.delta.partial_json) {
9144
9208
  const index = event.index;
9145
9209
  if (index !== void 0) {
@@ -9156,12 +9220,18 @@ var LLMClient = class {
9156
9220
  callbacks?.onUsageUpdate?.({ input_tokens: 0, output_tokens: estimatedOutput });
9157
9221
  }
9158
9222
  break;
9159
- case LLM_SSE_EVENT.CONTENT_BLOCK_STOP:
9160
- callbacks?.onReasoningEnd?.();
9161
- callbacks?.onOutputEnd?.();
9162
- onTextEnd();
9163
- onReasoningEnd();
9223
+ case LLM_SSE_EVENT.CONTENT_BLOCK_STOP: {
9224
+ const stoppedType = currentBlockRef.value;
9225
+ currentBlockRef.value = null;
9226
+ if (stoppedType === "text") {
9227
+ onTextEnd();
9228
+ callbacks?.onOutputEnd?.();
9229
+ } else if (stoppedType === "reasoning") {
9230
+ onReasoningEnd();
9231
+ callbacks?.onReasoningEnd?.();
9232
+ }
9164
9233
  break;
9234
+ }
9165
9235
  case LLM_SSE_EVENT.MESSAGE_START:
9166
9236
  if (event.message?.usage) {
9167
9237
  onUsage({ input_tokens: event.message.usage.input_tokens || 0, output_tokens: event.message.usage.output_tokens || 0 });
@@ -10130,7 +10200,7 @@ Please decide how to handle this error and continue.`;
10130
10200
  async step(iteration, messages, systemPrompt, progress) {
10131
10201
  const phase = this.state.getPhase();
10132
10202
  const stepStartTime = Date.now();
10133
- this.emitThink(iteration);
10203
+ this.emitThink(iteration, progress);
10134
10204
  const callbacks = this.buildStreamCallbacks(phase);
10135
10205
  const response = await this.llm.generateResponseStream(
10136
10206
  messages,
@@ -10138,12 +10208,24 @@ Please decide how to handle this error and continue.`;
10138
10208
  systemPrompt,
10139
10209
  callbacks
10140
10210
  );
10211
+ if (response.reasoning && !callbacks.hadReasoningEnd()) {
10212
+ this.emitReasoningStart(phase);
10213
+ this.emitReasoningDelta(response.reasoning, phase);
10214
+ this.emitReasoningEnd(phase);
10215
+ }
10216
+ if (response.content?.trim()) {
10217
+ this.events.emit({
10218
+ type: EVENT_TYPES.AI_RESPONSE,
10219
+ timestamp: Date.now(),
10220
+ data: { content: response.content.trim(), phase }
10221
+ });
10222
+ }
10141
10223
  messages.push({ role: LLM_ROLES.ASSISTANT, content: response.content });
10142
10224
  const stepDuration = Date.now() - stepStartTime;
10143
10225
  const tokens = response.usage ? { input: response.usage.input_tokens, output: response.usage.output_tokens } : void 0;
10144
10226
  if (!response.toolCalls?.length) {
10145
- const hasDonemeaningfulWork = (progress?.totalToolsExecuted ?? 0) > 0;
10146
- if (hasDonemeaningfulWork) {
10227
+ const hasDoneMeaningfulWork = (progress?.totalToolsExecuted ?? 0) > 0;
10228
+ if (hasDoneMeaningfulWork) {
10147
10229
  this.emitComplete(response.content, iteration, 0, stepDuration, tokens);
10148
10230
  return { output: response.content, toolsExecuted: 0, isCompleted: true };
10149
10231
  }
@@ -10157,11 +10239,26 @@ Please decide how to handle this error and continue.`;
10157
10239
  // SUBSECTION: Callback Builder
10158
10240
  // ─────────────────────────────────────────────────────────────────
10159
10241
  buildStreamCallbacks(phase) {
10160
- return {
10242
+ let _reasoningEndFired = false;
10243
+ let _outputBuffer = "";
10244
+ const callbacks = {
10161
10245
  onReasoningStart: () => this.emitReasoningStart(phase),
10162
10246
  onReasoningDelta: (content) => this.emitReasoningDelta(content, phase),
10163
- onReasoningEnd: () => this.emitReasoningEnd(phase),
10164
- onOutputDelta: () => {
10247
+ onReasoningEnd: () => {
10248
+ _reasoningEndFired = true;
10249
+ this.emitReasoningEnd(phase);
10250
+ },
10251
+ // WHY: Show AI text as it streams, not after completion.
10252
+ // The user sees what the AI is writing in real-time via the status bar.
10253
+ onOutputDelta: (text) => {
10254
+ _outputBuffer += text;
10255
+ const firstLine = _outputBuffer.split("\n")[0]?.slice(0, 120) || "";
10256
+ this.events.emit({
10257
+ type: EVENT_TYPES.THINK,
10258
+ timestamp: Date.now(),
10259
+ data: { thought: `Writing\u2026 ${_outputBuffer.length} chars
10260
+ ${firstLine}`, phase }
10261
+ });
10165
10262
  },
10166
10263
  onRetry: (attempt, maxRetries, delayMs, error) => {
10167
10264
  this.events.emit({
@@ -10177,19 +10274,40 @@ Please decide how to handle this error and continue.`;
10177
10274
  data: { inputTokens: usage.input_tokens, outputTokens: usage.output_tokens }
10178
10275
  });
10179
10276
  },
10180
- abortSignal: this.abortController?.signal
10277
+ abortSignal: this.abortController?.signal,
10278
+ // WHY: Used by step() to detect if SSE reasoning blocks fired.
10279
+ // If not, we know it was an inline <think> model and must emit post-stream.
10280
+ hadReasoningEnd: () => _reasoningEndFired
10181
10281
  };
10282
+ return callbacks;
10182
10283
  }
10183
10284
  // ─────────────────────────────────────────────────────────────────
10184
10285
  // SUBSECTION: Event Emitters
10185
10286
  // ─────────────────════════════════════════════════════════════
10186
- emitThink(iteration) {
10287
+ emitThink(iteration, progress) {
10288
+ const phase = this.state.getPhase();
10289
+ const targets = this.state.getTargets().size;
10290
+ const findings = this.state.getFindings().length;
10291
+ const toolsUsed = progress?.totalToolsExecuted ?? 0;
10292
+ const hasErrors = (progress?.toolErrors ?? 0) > 0;
10293
+ let thought;
10294
+ if (iteration === 0) {
10295
+ thought = targets > 0 ? `Analyzing ${targets} target${targets > 1 ? "s" : ""} \xB7 Planning ${phase} approach` : `Reviewing task \xB7 Building ${phase} strategy`;
10296
+ } else if (toolsUsed === 0) {
10297
+ thought = `Iteration ${iteration + 1} \xB7 No actions yet \xB7 Reconsidering approach`;
10298
+ } else if (hasErrors) {
10299
+ thought = `Iteration ${iteration + 1} \xB7 [${phase}] ${toolsUsed} tools \xB7 ${progress?.toolErrors} error${(progress?.toolErrors ?? 0) > 1 ? "s" : ""} \xB7 Adapting strategy`;
10300
+ } else if (findings > 0) {
10301
+ thought = `Iteration ${iteration + 1} \xB7 [${phase}] ${findings} finding${findings > 1 ? "s" : ""} \xB7 ${toolsUsed} tools \xB7 Continuing`;
10302
+ } else {
10303
+ thought = `Iteration ${iteration + 1} \xB7 [${phase}] ${toolsUsed} tool${toolsUsed !== 1 ? "s" : ""} executed \xB7 Evaluating results`;
10304
+ }
10187
10305
  this.events.emit({
10188
10306
  type: EVENT_TYPES.THINK,
10189
10307
  timestamp: Date.now(),
10190
10308
  data: {
10191
- thought: `${this.agentType} agent iteration ${iteration + 1}: Decision making`,
10192
- phase: this.state.getPhase()
10309
+ thought,
10310
+ phase
10193
10311
  }
10194
10312
  });
10195
10313
  }
@@ -11460,59 +11578,67 @@ var formatInlineStatus = () => {
11460
11578
  import { useState, useRef, useCallback } from "react";
11461
11579
 
11462
11580
  // src/shared/constants/theme.ts
11581
+ var HEX = {
11582
+ primary: "#2496ED",
11583
+ // Docker blue
11584
+ cyan: "#58C4F0",
11585
+ // bright sky blue
11586
+ teal: "#4EC9B0",
11587
+ // mint-teal (success states)
11588
+ yellow: "#E0AF68",
11589
+ // warm amber (warning)
11590
+ gray: "#C8C8C8",
11591
+ // secondary text
11592
+ white: "#FFFFFF",
11593
+ red: "#F7768E"
11594
+ // pastel red (error)
11595
+ };
11463
11596
  var COLORS = {
11464
- primary: "#e11d48",
11465
- // Rose 600 - red team primary
11466
- accent: "#fb923c",
11467
- // Orange 400 - fire accent
11468
- secondary: "#94a3b8",
11469
- // Slate - secondary/muted
11470
- white: "#f8fafc",
11471
- // Main text
11472
- red: "#ff4500",
11473
- // OrangeRed - Error/Critical (distinct from rose primary)
11474
- yellow: "#facc15"
11475
- // Yellow 400 - Warning/Pending (pure yellow)
11597
+ primary: "ansi256(33)",
11598
+ // Docker blue (#0087ff) closest to #2496ED
11599
+ cyan: "ansi256(74)",
11600
+ // bright sky blue (#5fafd7)
11601
+ teal: "ansi256(79)",
11602
+ // mint-teal (#5fd7af) — success states
11603
+ yellow: "ansi256(179)",
11604
+ // warm amber (warning)
11605
+ white: "white",
11606
+ // main text unchanged
11607
+ gray: "ansi256(250)",
11608
+ // secondary text bright enough to read
11609
+ dimGray: "ansi256(240)",
11610
+ // dimmer text for sub-lines
11611
+ red: "ansi256(204)"
11612
+ // pastel red (error)
11476
11613
  };
11477
11614
  var THEME = {
11478
11615
  ...COLORS,
11479
- bg: {
11480
- primary: "#050505",
11481
- input: "#020617"
11482
- },
11483
- text: {
11484
- primary: COLORS.white,
11485
- secondary: COLORS.secondary,
11486
- muted: "#64748b",
11487
- accent: COLORS.accent
11488
- // Using Emerald for "accented" text
11489
- },
11490
11616
  status: {
11491
- success: COLORS.accent,
11492
- // Success feels good in emerald
11617
+ success: COLORS.teal,
11618
+ // teal for success
11493
11619
  warning: COLORS.yellow,
11494
- error: COLORS.red,
11495
- running: COLORS.primary
11496
- // System operations in blue
11620
+ // amber for warnings
11621
+ error: COLORS.red
11622
+ // red for errors
11497
11623
  },
11498
11624
  border: {
11499
- default: "#1e293b",
11625
+ default: "ansi256(25)",
11626
+ // muted Docker blue border (#005faf)
11500
11627
  focus: COLORS.primary,
11501
11628
  error: COLORS.red
11502
11629
  },
11503
11630
  gradient: {
11504
- cyber: [COLORS.primary, "#f43f5e", "#fb923c"]
11505
- // Red team fire gradient: rose → pink → amber
11631
+ cyber: [HEX.primary, HEX.cyan, HEX.teal]
11506
11632
  },
11507
11633
  spinner: COLORS.primary
11508
11634
  };
11509
11635
  var ASCII_BANNER = `
11510
- \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557
11511
- \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
11636
+ \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557
11637
+ \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
11512
11638
  \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557
11513
11639
  \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551
11514
11640
  \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
11515
- \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D
11641
+ \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D
11516
11642
  `;
11517
11643
  var ICONS = {
11518
11644
  // Status
@@ -11522,9 +11648,8 @@ var ICONS = {
11522
11648
  info: "\u2139",
11523
11649
  running: "\u25C9",
11524
11650
  thinking: "\u25D0",
11525
- // Actions (pentesting-specific)
11651
+ // Actions
11526
11652
  target: "\u25C8",
11527
- // Diamond for target
11528
11653
  scan: "\u25CE",
11529
11654
  exploit: "\u2607",
11530
11655
  shell: "\u276F",
@@ -11542,9 +11667,7 @@ var ICONS = {
11542
11667
  unlock: "\u2B1A",
11543
11668
  key: "\u26B7",
11544
11669
  flag: "\u2691",
11545
- // Simple flag
11546
11670
  pwned: "\u25C8"
11547
- // Compromised
11548
11671
  };
11549
11672
 
11550
11673
  // src/platform/tui/constants/display.ts
@@ -11555,7 +11678,11 @@ var TUI_DISPLAY_LIMITS = {
11555
11678
  reasoningPreview: 500,
11556
11679
  /** Reasoning history slice for display */
11557
11680
  reasoningHistorySlice: 1e3,
11558
- /** Tool input preview length (for command display) */
11681
+ /** Max number of output lines shown from a tool result (success) */
11682
+ toolOutputLines: 20,
11683
+ /** Max number of output lines shown from a tool result (error — show more) */
11684
+ errorOutputLines: 25,
11685
+ /** Tool output preview length (for command display) */
11559
11686
  toolInputPreview: 200,
11560
11687
  /** Tool input truncated length */
11561
11688
  toolInputTruncated: 197,
@@ -11586,18 +11713,32 @@ var TUI_DISPLAY_LIMITS = {
11586
11713
  /** Max flow nodes to display */
11587
11714
  maxFlowNodes: 50,
11588
11715
  /** Max stopped processes to show */
11589
- maxStoppedProcesses: 3
11716
+ maxStoppedProcesses: 3,
11717
+ /** Max chars for live reasoning preview in status sub-line */
11718
+ reasoningPreviewChars: 100,
11719
+ /** Max chars for thinking block first-line summary */
11720
+ thinkingSummaryChars: 72
11590
11721
  };
11591
11722
  var MESSAGE_STYLES = {
11592
11723
  colors: {
11593
- user: THEME.text.accent,
11594
- assistant: THEME.text.primary,
11595
- ai: THEME.text.primary,
11596
- system: THEME.text.muted,
11597
- error: THEME.status.error,
11598
- tool: THEME.status.running,
11599
- result: THEME.text.muted,
11600
- status: THEME.primary
11724
+ user: THEME.white,
11725
+ // User input - bright white
11726
+ assistant: THEME.white,
11727
+ // AI response - white
11728
+ ai: THEME.white,
11729
+ // AI response - white
11730
+ system: THEME.gray,
11731
+ // System - light gray
11732
+ error: THEME.red,
11733
+ // Errors - red
11734
+ tool: THEME.gray,
11735
+ // Tool commands - light gray
11736
+ result: THEME.gray,
11737
+ // Tool results - light gray
11738
+ status: THEME.primary,
11739
+ // Status - teal accent
11740
+ thinking: THEME.cyan
11741
+ // Extended reasoning — sky blue (distinct from primary)
11601
11742
  },
11602
11743
  prefixes: {
11603
11744
  user: "\u276F",
@@ -11607,7 +11748,9 @@ var MESSAGE_STYLES = {
11607
11748
  error: "\u2717",
11608
11749
  tool: "\u23BF",
11609
11750
  result: "\u21B3",
11610
- status: "\u25C8"
11751
+ status: "\u25C8",
11752
+ thinking: "\u25D0"
11753
+ // Thinking/reasoning icon
11611
11754
  }
11612
11755
  };
11613
11756
  var COMMAND_DEFINITIONS = [
@@ -11730,7 +11873,7 @@ var useAgentState = () => {
11730
11873
  };
11731
11874
 
11732
11875
  // src/platform/tui/hooks/useAgentEvents.ts
11733
- import { useEffect } from "react";
11876
+ import { useEffect, useRef as useRef2 } from "react";
11734
11877
  var useAgentEvents = (agent, eventsRef, state) => {
11735
11878
  const {
11736
11879
  addMessage,
@@ -11746,35 +11889,51 @@ var useAgentEvents = (agent, eventsRef, state) => {
11746
11889
  lastStepTokensRef,
11747
11890
  clearAllTimers
11748
11891
  } = state;
11892
+ const reasoningBufferRef = useRef2("");
11749
11893
  useEffect(() => {
11750
11894
  const events = eventsRef.current;
11751
11895
  const onToolCall = (e) => {
11752
- setCurrentStatus(`Executing: ${e.data.toolName}`);
11896
+ if (NOISE_CLASSIFICATION.LOW_VISIBILITY.includes(e.data.toolName)) return;
11897
+ setCurrentStatus(`${e.data.toolName}\u2026`);
11753
11898
  const inputStr = formatToolInput(e.data.toolName, e.data.input);
11754
- addMessage("tool", inputStr ? `${e.data.toolName} ${inputStr}` : e.data.toolName);
11899
+ const label = inputStr ? `${toDisplayName(e.data.toolName)}(${inputStr})` : `${toDisplayName(e.data.toolName)}`;
11900
+ addMessage("tool", label);
11755
11901
  };
11756
11902
  const onToolResult = (e) => {
11903
+ if (NOISE_CLASSIFICATION.LOW_VISIBILITY.includes(e.data.toolName)) {
11904
+ return;
11905
+ }
11757
11906
  const icon = e.data.success ? "\u2713" : "\u2717";
11758
- const content = e.data.success ? e.data.outputSummary || e.data.output || "" : e.data.error || e.data.output || "Unknown error";
11759
- const maxLen = e.data.success ? TUI_DISPLAY_LIMITS.toolOutputPreview : TUI_DISPLAY_LIMITS.errorPreview;
11760
- const preview = content.slice(0, maxLen).replace(/\n/g, " ");
11761
- const more = content.length > maxLen ? "..." : "";
11762
- addMessage("result", `${icon} ${preview}${more}`);
11907
+ const rawContent = e.data.success ? e.data.outputSummary || e.data.output || "" : e.data.error || e.data.output || "Unknown error";
11908
+ if (!rawContent.trim()) {
11909
+ addMessage("result", `${icon}`);
11910
+ return;
11911
+ }
11912
+ const lines = rawContent.replace(/^\s*-n\s+/gm, "").split("\n").map((l) => l.trimEnd()).filter((l, i, arr) => {
11913
+ if (l === "" && arr[i - 1] === "") return false;
11914
+ return true;
11915
+ });
11916
+ addMessage("result", `${icon} ${lines.join("\n")}`);
11763
11917
  };
11764
11918
  const onComplete = (e) => {
11765
- addMessage("system", `\u2713 Complete ${formatMeta(e.data.durationMs || 0, (e.data.tokens?.input || 0) + (e.data.tokens?.output || 0))}`);
11919
+ const meta = formatMeta(e.data.durationMs || 0, (e.data.tokens?.input || 0) + (e.data.tokens?.output || 0));
11920
+ addMessage("system", `\u2713 Done ${meta}`);
11766
11921
  lastResponseMetaRef.current = { durationMs: e.data.durationMs, tokens: e.data.tokens };
11767
11922
  };
11768
11923
  const onRetry = (e) => {
11769
11924
  handleRetry(e, addMessage, setRetryState, retryCountdownRef, retryCountRef);
11770
11925
  };
11771
11926
  const onThink = (e) => {
11772
- const t = e.data.thought;
11773
- setCurrentStatus(t.length > TUI_DISPLAY_LIMITS.statusThoughtPreview ? t.substring(0, TUI_DISPLAY_LIMITS.statusThoughtTruncated) + "..." : t);
11927
+ setCurrentStatus(e.data.thought);
11774
11928
  };
11775
11929
  const onError = (e) => {
11776
11930
  addMessage("error", e.data.message || "An error occurred");
11777
11931
  };
11932
+ const onAIResponse = (e) => {
11933
+ if (e.data.content?.trim()) {
11934
+ addMessage("ai", e.data.content.trim());
11935
+ }
11936
+ };
11778
11937
  const onUsageUpdate = (e) => {
11779
11938
  const stepTokens = e.data.inputTokens + e.data.outputTokens;
11780
11939
  if (stepTokens < lastStepTokensRef.current) {
@@ -11787,7 +11946,7 @@ var useAgentEvents = (agent, eventsRef, state) => {
11787
11946
  addMessage("system", `[FLAG] ${e.data.flag} (total: ${e.data.totalFlags})`);
11788
11947
  };
11789
11948
  const onPhaseChange = (e) => {
11790
- addMessage("system", `[Phase] ${e.data.fromPhase} -> ${e.data.toPhase} (${e.data.reason})`);
11949
+ addMessage("system", `Phase ${e.data.fromPhase} \u2192 ${e.data.toPhase} (${e.data.reason})`);
11791
11950
  const s = agent.getState();
11792
11951
  setStats({
11793
11952
  phase: e.data.toPhase,
@@ -11796,6 +11955,25 @@ var useAgentEvents = (agent, eventsRef, state) => {
11796
11955
  todo: s.getTodo().length
11797
11956
  });
11798
11957
  };
11958
+ const onReasoningStart = () => {
11959
+ reasoningBufferRef.current = "";
11960
+ setCurrentStatus("Thinking\u2026");
11961
+ };
11962
+ const onReasoningDelta = (e) => {
11963
+ reasoningBufferRef.current += e.data.content;
11964
+ const chars = reasoningBufferRef.current.length;
11965
+ const firstLine = reasoningBufferRef.current.split("\n")[0]?.slice(0, TUI_DISPLAY_LIMITS.reasoningPreviewChars) || "";
11966
+ setCurrentStatus(`Thinking\u2026 ${chars} chars
11967
+ ${firstLine}`);
11968
+ };
11969
+ const onReasoningEnd = () => {
11970
+ const text = reasoningBufferRef.current.trim();
11971
+ reasoningBufferRef.current = "";
11972
+ setCurrentStatus("");
11973
+ if (text) {
11974
+ addMessage("thinking", text);
11975
+ }
11976
+ };
11799
11977
  setInputHandler((p) => {
11800
11978
  return new Promise((resolve) => {
11801
11979
  const isPassword = /password|passphrase/i.test(p);
@@ -11827,9 +12005,11 @@ var useAgentEvents = (agent, eventsRef, state) => {
11827
12005
  });
11828
12006
  });
11829
12007
  setCommandEventEmitter((event) => {
12008
+ if (event.type === COMMAND_EVENT_TYPES.COMMAND_START || event.type === COMMAND_EVENT_TYPES.COMMAND_SUCCESS) {
12009
+ return;
12010
+ }
11830
12011
  const icon = getCommandEventIcon(event.type);
11831
- const msg = event.detail ? `${icon} ${event.message}
11832
- ${event.detail}` : `${icon} ${event.message}`;
12012
+ const msg = event.detail ? `${icon} ${event.message} ${event.detail}` : `${icon} ${event.message}`;
11833
12013
  addMessage("system", msg);
11834
12014
  });
11835
12015
  const updateStats = () => {
@@ -11852,6 +12032,10 @@ var useAgentEvents = (agent, eventsRef, state) => {
11852
12032
  events.on(EVENT_TYPES.PHASE_CHANGE, onPhaseChange);
11853
12033
  events.on(EVENT_TYPES.STATE_CHANGE, updateStats);
11854
12034
  events.on(EVENT_TYPES.START, updateStats);
12035
+ events.on(EVENT_TYPES.REASONING_START, onReasoningStart);
12036
+ events.on(EVENT_TYPES.REASONING_DELTA, onReasoningDelta);
12037
+ events.on(EVENT_TYPES.REASONING_END, onReasoningEnd);
12038
+ events.on(EVENT_TYPES.AI_RESPONSE, onAIResponse);
11855
12039
  updateStats();
11856
12040
  return () => {
11857
12041
  events.removeAllListeners();
@@ -11877,6 +12061,16 @@ var useAgentEvents = (agent, eventsRef, state) => {
11877
12061
  eventsRef
11878
12062
  ]);
11879
12063
  };
12064
+ function toDisplayName(toolName) {
12065
+ const MAP = {
12066
+ [TOOL_NAMES.RUN_CMD]: "Bash",
12067
+ [TOOL_NAMES.BG_PROCESS]: "Process",
12068
+ [TOOL_NAMES.READ_FILE]: "Read",
12069
+ [TOOL_NAMES.WRITE_FILE]: "Write",
12070
+ [TOOL_NAMES.ASK_USER]: "Input"
12071
+ };
12072
+ return MAP[toolName] ?? toolName.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
12073
+ }
11880
12074
  function formatToolInput(toolName, input) {
11881
12075
  if (!input || Object.keys(input).length === 0) return "";
11882
12076
  try {
@@ -11932,24 +12126,24 @@ Options: ${request.options.join(", ")}`;
11932
12126
  }
11933
12127
  function getCommandEventIcon(eventType) {
11934
12128
  const icons = {
11935
- [COMMAND_EVENT_TYPES.TOOL_MISSING]: "[!]",
11936
- [COMMAND_EVENT_TYPES.TOOL_INSTALL]: "[install]",
11937
- [COMMAND_EVENT_TYPES.TOOL_INSTALLED]: "[ok]",
11938
- [COMMAND_EVENT_TYPES.TOOL_INSTALL_FAILED]: "[fail]",
11939
- [COMMAND_EVENT_TYPES.TOOL_RETRY]: "[retry]",
11940
- [COMMAND_EVENT_TYPES.COMMAND_START]: "[>]",
11941
- [COMMAND_EVENT_TYPES.COMMAND_SUCCESS]: "[ok]",
11942
- [COMMAND_EVENT_TYPES.COMMAND_FAILED]: "[x]",
11943
- [COMMAND_EVENT_TYPES.COMMAND_ERROR]: "[err]",
11944
- [COMMAND_EVENT_TYPES.INPUT_REQUIRED]: "[auth]"
12129
+ [COMMAND_EVENT_TYPES.TOOL_MISSING]: "!",
12130
+ [COMMAND_EVENT_TYPES.TOOL_INSTALL]: "\u2193",
12131
+ [COMMAND_EVENT_TYPES.TOOL_INSTALLED]: "\u2713",
12132
+ [COMMAND_EVENT_TYPES.TOOL_INSTALL_FAILED]: "\u2717",
12133
+ [COMMAND_EVENT_TYPES.TOOL_RETRY]: "\u21BA",
12134
+ [COMMAND_EVENT_TYPES.COMMAND_START]: "\u25B6",
12135
+ [COMMAND_EVENT_TYPES.COMMAND_SUCCESS]: "\u2713",
12136
+ [COMMAND_EVENT_TYPES.COMMAND_FAILED]: "\u2717",
12137
+ [COMMAND_EVENT_TYPES.COMMAND_ERROR]: "\u26A0",
12138
+ [COMMAND_EVENT_TYPES.INPUT_REQUIRED]: "\u{1F512}"
11945
12139
  };
11946
- return icons[eventType] || "[-]";
12140
+ return icons[eventType] || "\u2022";
11947
12141
  }
11948
12142
 
11949
12143
  // src/platform/tui/hooks/useAgent.ts
11950
12144
  var useAgent = (shouldAutoApprove, target) => {
11951
12145
  const [agent] = useState2(() => AgentFactory.createMainAgent(shouldAutoApprove));
11952
- const eventsRef = useRef2(agent.getEventEmitter());
12146
+ const eventsRef = useRef3(agent.getEventEmitter());
11953
12147
  const state = useAgentState();
11954
12148
  const {
11955
12149
  messages,
@@ -12002,7 +12196,7 @@ var useAgent = (shouldAutoApprove, target) => {
12002
12196
  setCurrentStatus("");
12003
12197
  addMessage("system", "Interrupted");
12004
12198
  }, [agent, addMessage, manageTimer, setIsProcessing, setCurrentStatus]);
12005
- const inputRequestRef = useRef2(inputRequest);
12199
+ const inputRequestRef = useRef3(inputRequest);
12006
12200
  inputRequestRef.current = inputRequest;
12007
12201
  const cancelInputRequest = useCallback2(() => {
12008
12202
  const ir = inputRequestRef.current;
@@ -12064,29 +12258,29 @@ function getRoleColor(role) {
12064
12258
  const roleColors = {
12065
12259
  listener: THEME.primary,
12066
12260
  active_shell: THEME.primary,
12067
- server: THEME.secondary,
12261
+ server: THEME.gray,
12068
12262
  sniffer: THEME.yellow,
12069
12263
  spoofer: THEME.yellow,
12070
12264
  proxy: THEME.primary,
12071
12265
  callback: THEME.primary,
12072
- background: THEME.text.muted
12266
+ background: THEME.gray
12073
12267
  };
12074
- return roleColors[role] || THEME.text.secondary;
12268
+ return roleColors[role] || THEME.gray;
12075
12269
  }
12076
12270
  function StatusIndicator({ running, exitCode }) {
12077
12271
  if (running) {
12078
- return /* @__PURE__ */ jsxs(Text, { color: THEME.status.running, children: [
12272
+ return /* @__PURE__ */ jsxs(Text, { color: THEME.primary, children: [
12079
12273
  ICONS.running,
12080
12274
  " "
12081
12275
  ] });
12082
12276
  }
12083
12277
  if (exitCode === 0) {
12084
- return /* @__PURE__ */ jsxs(Text, { color: THEME.status.success, children: [
12278
+ return /* @__PURE__ */ jsxs(Text, { color: THEME.gray, children: [
12085
12279
  ICONS.success,
12086
12280
  " "
12087
12281
  ] });
12088
12282
  }
12089
- return /* @__PURE__ */ jsxs(Text, { color: THEME.status.error, children: [
12283
+ return /* @__PURE__ */ jsxs(Text, { color: THEME.red, children: [
12090
12284
  ICONS.error,
12091
12285
  " "
12092
12286
  ] });
@@ -12098,7 +12292,7 @@ function ProcessRow({ proc, compact }) {
12098
12292
  const truncatedPurpose = compact && purpose.length > TUI_DISPLAY_LIMITS.purposeMaxLength ? purpose.slice(0, TUI_DISPLAY_LIMITS.purposeTruncated) + "..." : purpose;
12099
12293
  return /* @__PURE__ */ jsxs(Box, { children: [
12100
12294
  /* @__PURE__ */ jsx(StatusIndicator, { running: proc.running, exitCode: proc.exitCode }),
12101
- /* @__PURE__ */ jsxs(Text, { color: THEME.text.muted, children: [
12295
+ /* @__PURE__ */ jsxs(Text, { color: THEME.gray, children: [
12102
12296
  "[",
12103
12297
  proc.id,
12104
12298
  "]"
@@ -12108,14 +12302,14 @@ function ProcessRow({ proc, compact }) {
12108
12302
  proc.role,
12109
12303
  port
12110
12304
  ] }),
12111
- /* @__PURE__ */ jsxs(Text, { color: THEME.text.muted, children: [
12305
+ /* @__PURE__ */ jsxs(Text, { color: THEME.gray, children: [
12112
12306
  " (",
12113
12307
  duration,
12114
12308
  ")"
12115
12309
  ] }),
12116
12310
  truncatedPurpose && /* @__PURE__ */ jsxs(Fragment, { children: [
12117
- /* @__PURE__ */ jsx(Text, { color: THEME.text.muted, children: " - " }),
12118
- /* @__PURE__ */ jsx(Text, { color: THEME.text.secondary, children: truncatedPurpose })
12311
+ /* @__PURE__ */ jsx(Text, { color: THEME.gray, children: " - " }),
12312
+ /* @__PURE__ */ jsx(Text, { color: THEME.gray, children: truncatedPurpose })
12119
12313
  ] })
12120
12314
  ] });
12121
12315
  }
@@ -12126,18 +12320,18 @@ var InlineStatus = ({
12126
12320
  compact = true
12127
12321
  }) => {
12128
12322
  if (processes.length === 0 && zombies.length === 0) {
12129
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: THEME.text.muted, children: "\u2022 No active background processes" }) });
12323
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: THEME.gray, children: "\u2022 No active background processes" }) });
12130
12324
  }
12131
12325
  const running = processes.filter((p) => p.running);
12132
12326
  const stopped = processes.filter((p) => !p.running);
12133
12327
  const healthColor = {
12134
- healthy: THEME.status.success,
12135
- warning: THEME.status.warning,
12136
- critical: THEME.status.error
12328
+ healthy: THEME.gray,
12329
+ warning: THEME.yellow,
12330
+ critical: THEME.red
12137
12331
  }[health];
12138
12332
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
12139
12333
  running.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
12140
- /* @__PURE__ */ jsxs(Text, { color: THEME.text.muted, bold: true, children: [
12334
+ /* @__PURE__ */ jsxs(Text, { color: THEME.gray, bold: true, children: [
12141
12335
  ICONS.running,
12142
12336
  " Active (",
12143
12337
  running.length,
@@ -12146,46 +12340,46 @@ var InlineStatus = ({
12146
12340
  running.map((proc) => /* @__PURE__ */ jsx(ProcessRow, { proc, compact }, proc.id))
12147
12341
  ] }),
12148
12342
  stopped.length > 0 && !compact && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: running.length > 0 ? 1 : 0, children: [
12149
- /* @__PURE__ */ jsxs(Text, { color: THEME.text.muted, children: [
12343
+ /* @__PURE__ */ jsxs(Text, { color: THEME.gray, children: [
12150
12344
  ICONS.completed,
12151
12345
  " Completed (",
12152
12346
  stopped.length,
12153
12347
  ")"
12154
12348
  ] }),
12155
12349
  stopped.slice(0, TUI_DISPLAY_LIMITS.maxStoppedProcesses).map((proc) => /* @__PURE__ */ jsx(ProcessRow, { proc, compact }, proc.id)),
12156
- stopped.length > TUI_DISPLAY_LIMITS.maxStoppedProcesses && /* @__PURE__ */ jsxs(Text, { color: THEME.text.muted, children: [
12350
+ stopped.length > TUI_DISPLAY_LIMITS.maxStoppedProcesses && /* @__PURE__ */ jsxs(Text, { color: THEME.gray, children: [
12157
12351
  " ... and ",
12158
12352
  stopped.length - TUI_DISPLAY_LIMITS.maxStoppedProcesses,
12159
12353
  " more"
12160
12354
  ] })
12161
12355
  ] }),
12162
12356
  zombies.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
12163
- /* @__PURE__ */ jsxs(Text, { color: THEME.status.warning, children: [
12357
+ /* @__PURE__ */ jsxs(Text, { color: THEME.yellow, children: [
12164
12358
  ICONS.warning,
12165
12359
  " Zombie Processes (",
12166
12360
  zombies.length,
12167
12361
  ")"
12168
12362
  ] }),
12169
12363
  zombies.map((z) => /* @__PURE__ */ jsxs(Box, { children: [
12170
- /* @__PURE__ */ jsxs(Text, { color: THEME.status.error, children: [
12364
+ /* @__PURE__ */ jsxs(Text, { color: THEME.red, children: [
12171
12365
  " ",
12172
12366
  ICONS.error,
12173
12367
  " "
12174
12368
  ] }),
12175
- /* @__PURE__ */ jsxs(Text, { color: THEME.text.muted, children: [
12369
+ /* @__PURE__ */ jsxs(Text, { color: THEME.gray, children: [
12176
12370
  "[",
12177
12371
  z.processId,
12178
12372
  "] "
12179
12373
  ] }),
12180
- /* @__PURE__ */ jsxs(Text, { color: THEME.status.warning, children: [
12374
+ /* @__PURE__ */ jsxs(Text, { color: THEME.yellow, children: [
12181
12375
  z.orphanedChildren.length,
12182
12376
  " orphaned children"
12183
12377
  ] })
12184
12378
  ] }, z.processId)),
12185
- /* @__PURE__ */ jsx(Text, { color: THEME.text.muted, children: " Run /cleanup to terminate" })
12379
+ /* @__PURE__ */ jsx(Text, { color: THEME.gray, children: " Run /cleanup to terminate" })
12186
12380
  ] }),
12187
12381
  /* @__PURE__ */ jsxs(Box, { marginTop: running.length > 0 ? 1 : 0, children: [
12188
- /* @__PURE__ */ jsx(Text, { color: THEME.text.muted, children: "Health: " }),
12382
+ /* @__PURE__ */ jsx(Text, { color: THEME.gray, children: "Health: " }),
12189
12383
  /* @__PURE__ */ jsx(Text, { color: healthColor, bold: true, children: health.toUpperCase() })
12190
12384
  ] })
12191
12385
  ] });
@@ -12221,9 +12415,76 @@ var MessageList = memo(({ messages }) => {
12221
12415
  }
12222
12416
  ) }, msg.id);
12223
12417
  }
12224
- }
12225
- return /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { color: MESSAGE_STYLES.colors[msg.type], dimColor: msg.type === "result", children: [
12226
- MESSAGE_STYLES.prefixes[msg.type],
12418
+ return /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { color: THEME.gray, children: [
12419
+ "\u2022 ",
12420
+ msg.content
12421
+ ] }) }, msg.id);
12422
+ }
12423
+ if (msg.type === "thinking") {
12424
+ const lines = msg.content.split("\n");
12425
+ const charCount = msg.content.length;
12426
+ const firstLine = lines[0]?.slice(0, TUI_DISPLAY_LIMITS.thinkingSummaryChars) || "";
12427
+ const isMultiLine = lines.length > 1 || charCount > TUI_DISPLAY_LIMITS.thinkingSummaryChars;
12428
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: 0, marginBottom: 1, children: [
12429
+ /* @__PURE__ */ jsxs2(Box2, { children: [
12430
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.cyan, children: "\u25D0 " }),
12431
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.cyan, bold: true, children: "Thinking" }),
12432
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: ` (${lines.length} line${lines.length !== 1 ? "s" : ""}, ${charCount} chars)` })
12433
+ ] }),
12434
+ lines.map((line, i) => /* @__PURE__ */ jsxs2(Box2, { children: [
12435
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.cyan, children: "\u2502 " }),
12436
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: line })
12437
+ ] }, i)),
12438
+ /* @__PURE__ */ jsxs2(Box2, { children: [
12439
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.cyan, children: "\u2570\u2500" }),
12440
+ isMultiLine && /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: ` ${firstLine}\u2026` })
12441
+ ] })
12442
+ ] }, msg.id);
12443
+ }
12444
+ if (msg.type === "tool") {
12445
+ return /* @__PURE__ */ jsxs2(Box2, { children: [
12446
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: "\u23BF " }),
12447
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.primary, children: msg.content })
12448
+ ] }, msg.id);
12449
+ }
12450
+ if (msg.type === "result") {
12451
+ const isSuccess = msg.content.startsWith("\u2713");
12452
+ const isFailure = msg.content.startsWith("\u2717");
12453
+ const color = isSuccess ? THEME.primary : isFailure ? THEME.red : THEME.gray;
12454
+ const lines = msg.content.split("\n");
12455
+ const firstLine = lines[0] || "";
12456
+ const restLines = lines.slice(1);
12457
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
12458
+ /* @__PURE__ */ jsxs2(Box2, { children: [
12459
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: "\u21B3 " }),
12460
+ /* @__PURE__ */ jsx2(Text2, { color, children: firstLine })
12461
+ ] }),
12462
+ restLines.map((line, i) => /* @__PURE__ */ jsx2(Box2, { paddingLeft: 2, children: /* @__PURE__ */ jsx2(Text2, { color: THEME.gray, children: line }) }, i))
12463
+ ] }, msg.id);
12464
+ }
12465
+ if (msg.type === "ai" || msg.type === "assistant") {
12466
+ return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginBottom: 0, children: /* @__PURE__ */ jsx2(Text2, { color: THEME.white, children: msg.content }) }, msg.id);
12467
+ }
12468
+ if (msg.type === "error") {
12469
+ return /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { color: THEME.red, children: [
12470
+ "\u2717 ",
12471
+ msg.content
12472
+ ] }) }, msg.id);
12473
+ }
12474
+ if (msg.type === "user") {
12475
+ return /* @__PURE__ */ jsxs2(Box2, { children: [
12476
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.primary, children: "\u276F " }),
12477
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.white, children: msg.content })
12478
+ ] }, msg.id);
12479
+ }
12480
+ if (msg.type === "system") {
12481
+ return /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { color: THEME.gray, children: [
12482
+ "\u2022 ",
12483
+ msg.content
12484
+ ] }) }, msg.id);
12485
+ }
12486
+ return /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { color: MESSAGE_STYLES.colors[msg.type] ?? THEME.gray, children: [
12487
+ MESSAGE_STYLES.prefixes[msg.type] ?? "\u2022",
12227
12488
  " ",
12228
12489
  msg.content
12229
12490
  ] }) }, msg.id);
@@ -12239,7 +12500,7 @@ import { useState as useState3, useEffect as useEffect3, memo as memo2 } from "r
12239
12500
  import { Text as Text3 } from "ink";
12240
12501
  import { jsx as jsx3 } from "react/jsx-runtime";
12241
12502
  var FRAMES = ["\u2669", "\u266A", "\u266B", "\u266C", "\u266B", "\u266A"];
12242
- var INTERVAL = 600;
12503
+ var INTERVAL = 120;
12243
12504
  var MusicSpinner = memo2(({ color }) => {
12244
12505
  const [index, setIndex] = useState3(0);
12245
12506
  useEffect3(() => {
@@ -12264,39 +12525,48 @@ var StatusDisplay = memo3(({
12264
12525
  return err.length > DISPLAY_LIMITS.RETRY_ERROR_PREVIEW ? err.substring(0, DISPLAY_LIMITS.RETRY_ERROR_TRUNCATED) + "..." : err;
12265
12526
  };
12266
12527
  const meta = formatMeta(elapsedTime * 1e3, currentTokens);
12528
+ const statusLines = currentStatus ? currentStatus.split("\n").filter(Boolean) : [];
12529
+ const statusMain = statusLines[0] || "Processing...";
12530
+ const statusSub = statusLines.slice(1).join(" ");
12531
+ const isThinkingStatus = statusMain.startsWith("Thinking");
12267
12532
  return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 0, children: [
12268
12533
  retryState.status === "retrying" && /* @__PURE__ */ jsxs3(Box3, { marginBottom: 1, children: [
12269
- /* @__PURE__ */ jsx4(Text4, { color: THEME.status.warning, children: /* @__PURE__ */ jsx4(MusicSpinner, { color: THEME.status.warning }) }),
12270
- /* @__PURE__ */ jsxs3(Text4, { color: THEME.status.warning, children: [
12534
+ /* @__PURE__ */ jsx4(Text4, { color: THEME.yellow, children: /* @__PURE__ */ jsx4(MusicSpinner, { color: THEME.yellow }) }),
12535
+ /* @__PURE__ */ jsxs3(Text4, { color: THEME.yellow, bold: true, children: [
12271
12536
  " \u27F3 Retry #",
12272
- retryState.attempt
12273
- ] }),
12274
- /* @__PURE__ */ jsxs3(Text4, { color: THEME.text.muted, children: [
12275
- " \xB7 ",
12276
- truncateError(retryState.error)
12537
+ retryState.attempt,
12538
+ "/",
12539
+ retryState.maxRetries
12277
12540
  ] }),
12278
- /* @__PURE__ */ jsxs3(Text4, { color: THEME.primary, bold: true, children: [
12279
- " \xB7 ",
12541
+ /* @__PURE__ */ jsxs3(Text4, { color: THEME.gray, children: [
12542
+ " \u2014 ",
12280
12543
  retryState.countdown,
12281
- "s"
12544
+ "s \xB7 ",
12545
+ truncateError(retryState.error)
12282
12546
  ] })
12283
12547
  ] }),
12284
- isProcessing && retryState.status !== "retrying" && /* @__PURE__ */ jsxs3(Box3, { marginBottom: 1, children: [
12285
- /* @__PURE__ */ jsx4(Text4, { color: THEME.spinner, children: /* @__PURE__ */ jsx4(MusicSpinner, { color: THEME.spinner }) }),
12286
- /* @__PURE__ */ jsxs3(Text4, { color: THEME.text.muted, children: [
12287
- " ",
12288
- currentStatus || "Processing"
12548
+ isProcessing && retryState.status !== "retrying" && /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginBottom: 1, children: [
12549
+ /* @__PURE__ */ jsxs3(Box3, { children: [
12550
+ /* @__PURE__ */ jsx4(Text4, { color: isThinkingStatus ? THEME.cyan : THEME.primary, children: /* @__PURE__ */ jsx4(MusicSpinner, { color: isThinkingStatus ? THEME.cyan : THEME.primary }) }),
12551
+ /* @__PURE__ */ jsxs3(Text4, { color: isThinkingStatus ? THEME.cyan : THEME.primary, bold: true, children: [
12552
+ " ",
12553
+ statusMain
12554
+ ] }),
12555
+ /* @__PURE__ */ jsxs3(Text4, { color: THEME.gray, children: [
12556
+ " ",
12557
+ meta
12558
+ ] })
12289
12559
  ] }),
12290
- /* @__PURE__ */ jsxs3(Text4, { color: THEME.text.muted, children: [
12291
- " ",
12292
- meta
12293
- ] })
12560
+ statusSub ? /* @__PURE__ */ jsx4(Box3, { paddingLeft: 2, children: /* @__PURE__ */ jsxs3(Text4, { color: isThinkingStatus ? THEME.cyan : THEME.gray, children: [
12561
+ "\u2502 ",
12562
+ statusSub
12563
+ ] }) }) : null
12294
12564
  ] })
12295
12565
  ] });
12296
12566
  });
12297
12567
 
12298
12568
  // src/platform/tui/components/ChatInput.tsx
12299
- import { useMemo, useCallback as useCallback3, useRef as useRef3, memo as memo4 } from "react";
12569
+ import { useMemo, useCallback as useCallback3, useRef as useRef4, memo as memo4, useState as useState4 } from "react";
12300
12570
  import { Box as Box4, Text as Text5, useInput } from "ink";
12301
12571
  import TextInput from "ink-text-input";
12302
12572
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -12319,38 +12589,40 @@ var ChatInput = memo4(({
12319
12589
  return getMatchingCommands(partialCmd).slice(0, MAX_SUGGESTIONS);
12320
12590
  }, [isSlashMode, partialCmd, hasArgs]);
12321
12591
  const showPreview = isSlashMode && !hasArgs && suggestions.length > 0;
12322
- const suggestionsRef = useRef3(suggestions);
12592
+ const suggestionsRef = useRef4(suggestions);
12323
12593
  suggestionsRef.current = suggestions;
12324
- const isSlashModeRef = useRef3(isSlashMode);
12594
+ const isSlashModeRef = useRef4(isSlashMode);
12325
12595
  isSlashModeRef.current = isSlashMode;
12326
- const hasArgsRef = useRef3(hasArgs);
12596
+ const hasArgsRef = useRef4(hasArgs);
12327
12597
  hasArgsRef.current = hasArgs;
12328
- const inputRequestRef = useRef3(inputRequest);
12598
+ const inputRequestRef = useRef4(inputRequest);
12329
12599
  inputRequestRef.current = inputRequest;
12330
- const onChangeRef = useRef3(onChange);
12600
+ const onChangeRef = useRef4(onChange);
12331
12601
  onChangeRef.current = onChange;
12602
+ const [inputKey, setInputKey] = useState4(0);
12332
12603
  useInput(useCallback3((_input, key) => {
12333
12604
  if (inputRequestRef.current.status === "active") return;
12334
12605
  if (key.tab && isSlashModeRef.current && !hasArgsRef.current && suggestionsRef.current.length > 0) {
12335
12606
  const best = suggestionsRef.current[0];
12336
12607
  const argsHint = best.args ? " " : "";
12337
12608
  const completed = `/${best.name}${argsHint}`;
12338
- onChangeRef.current("");
12339
- setTimeout(() => onChangeRef.current(completed), 0);
12609
+ onChangeRef.current(completed);
12610
+ setInputKey((k) => k + 1);
12340
12611
  }
12341
12612
  }, []));
12342
12613
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
12343
- showPreview && /* @__PURE__ */ jsx5(
12614
+ /* @__PURE__ */ jsx5(
12344
12615
  Box4,
12345
12616
  {
12346
12617
  flexDirection: "column",
12347
- borderStyle: "single",
12348
- borderColor: THEME.border.default,
12349
- paddingX: 1,
12618
+ borderStyle: showPreview ? "single" : void 0,
12619
+ borderColor: showPreview ? THEME.border.default : void 0,
12620
+ paddingX: showPreview ? 1 : 0,
12350
12621
  marginBottom: 0,
12351
- children: suggestions.map((cmd, i) => {
12622
+ height: showPreview ? void 0 : 0,
12623
+ children: showPreview && suggestions.map((cmd, i) => {
12352
12624
  const isFirst = i === 0;
12353
- const nameColor = isFirst ? THEME.primary : THEME.text.secondary;
12625
+ const nameColor = isFirst ? THEME.white : THEME.gray;
12354
12626
  const aliasText = cmd.alias ? ` /${cmd.alias}` : "";
12355
12627
  const argsText = cmd.args ? ` ${cmd.args}` : "";
12356
12628
  return /* @__PURE__ */ jsxs4(Box4, { children: [
@@ -12358,9 +12630,9 @@ var ChatInput = memo4(({
12358
12630
  "/",
12359
12631
  cmd.name
12360
12632
  ] }),
12361
- /* @__PURE__ */ jsx5(Text5, { color: THEME.text.muted, children: argsText }),
12362
- aliasText && /* @__PURE__ */ jsx5(Text5, { color: THEME.text.muted, children: aliasText }),
12363
- /* @__PURE__ */ jsxs4(Text5, { color: THEME.text.muted, children: [
12633
+ /* @__PURE__ */ jsx5(Text5, { color: THEME.gray, children: argsText }),
12634
+ aliasText && /* @__PURE__ */ jsx5(Text5, { color: THEME.gray, children: aliasText }),
12635
+ /* @__PURE__ */ jsxs4(Text5, { color: THEME.gray, children: [
12364
12636
  " \u2014 ",
12365
12637
  cmd.description
12366
12638
  ] }),
@@ -12373,11 +12645,11 @@ var ChatInput = memo4(({
12373
12645
  Box4,
12374
12646
  {
12375
12647
  borderStyle: "single",
12376
- borderColor: inputRequest.status === "active" ? THEME.status.warning : THEME.border.default,
12648
+ borderColor: inputRequest.status === "active" ? THEME.yellow : THEME.border.default,
12377
12649
  paddingX: 1,
12378
12650
  children: inputRequest.status === "active" ? /* @__PURE__ */ jsxs4(Box4, { children: [
12379
- /* @__PURE__ */ jsx5(Text5, { color: THEME.status.warning, children: "[auth]" }),
12380
- /* @__PURE__ */ jsxs4(Text5, { color: THEME.text.muted, children: [
12651
+ /* @__PURE__ */ jsx5(Text5, { color: THEME.yellow, children: "[auth]" }),
12652
+ /* @__PURE__ */ jsxs4(Text5, { color: THEME.gray, children: [
12381
12653
  " ",
12382
12654
  inputRequest.prompt
12383
12655
  ] }),
@@ -12392,7 +12664,7 @@ var ChatInput = memo4(({
12392
12664
  }
12393
12665
  )
12394
12666
  ] }) : /* @__PURE__ */ jsxs4(Box4, { children: [
12395
- /* @__PURE__ */ jsx5(Text5, { color: THEME.text.secondary, children: "\u25B8" }),
12667
+ /* @__PURE__ */ jsx5(Text5, { color: THEME.primary, children: "\u25B8" }),
12396
12668
  /* @__PURE__ */ jsx5(Text5, { children: " " }),
12397
12669
  /* @__PURE__ */ jsx5(
12398
12670
  TextInput,
@@ -12401,7 +12673,8 @@ var ChatInput = memo4(({
12401
12673
  onChange,
12402
12674
  onSubmit,
12403
12675
  placeholder
12404
- }
12676
+ },
12677
+ inputKey
12405
12678
  )
12406
12679
  ] })
12407
12680
  }
@@ -12432,26 +12705,26 @@ var Footer = memo5(({ phase, targets, findings, todo, elapsedTime, isProcessing
12432
12705
  justifyContent: "space-between",
12433
12706
  children: [
12434
12707
  /* @__PURE__ */ jsxs5(Box5, { gap: 2, children: [
12435
- /* @__PURE__ */ jsxs5(Text6, { color: THEME.text.muted, children: [
12708
+ /* @__PURE__ */ jsxs5(Text6, { color: THEME.gray, children: [
12436
12709
  "Phase: ",
12437
- /* @__PURE__ */ jsx6(Text6, { color: THEME.primary, children: phase })
12710
+ /* @__PURE__ */ jsx6(Text6, { color: THEME.white, children: phase })
12438
12711
  ] }),
12439
- /* @__PURE__ */ jsxs5(Text6, { color: THEME.text.muted, children: [
12712
+ /* @__PURE__ */ jsxs5(Text6, { color: THEME.gray, children: [
12440
12713
  "Targets: ",
12441
- /* @__PURE__ */ jsx6(Text6, { color: THEME.text.secondary, children: targets })
12714
+ /* @__PURE__ */ jsx6(Text6, { color: THEME.white, children: targets })
12442
12715
  ] }),
12443
- /* @__PURE__ */ jsxs5(Text6, { color: THEME.text.muted, children: [
12716
+ /* @__PURE__ */ jsxs5(Text6, { color: THEME.gray, children: [
12444
12717
  "Findings: ",
12445
- /* @__PURE__ */ jsx6(Text6, { color: THEME.status.warning, children: findings })
12718
+ /* @__PURE__ */ jsx6(Text6, { color: THEME.white, children: findings })
12446
12719
  ] }),
12447
- /* @__PURE__ */ jsxs5(Text6, { color: THEME.text.muted, children: [
12720
+ /* @__PURE__ */ jsxs5(Text6, { color: THEME.gray, children: [
12448
12721
  "Tasks: ",
12449
- /* @__PURE__ */ jsx6(Text6, { color: THEME.text.secondary, children: todo })
12722
+ /* @__PURE__ */ jsx6(Text6, { color: THEME.white, children: todo })
12450
12723
  ] })
12451
12724
  ] }),
12452
12725
  /* @__PURE__ */ jsxs5(Box5, { children: [
12453
- /* @__PURE__ */ jsx6(Text6, { color: isProcessing ? THEME.status.running : THEME.text.muted, children: isProcessing ? "Running " : "Idle " }),
12454
- /* @__PURE__ */ jsx6(Text6, { color: THEME.text.secondary, children: formatElapsed(elapsedTime) })
12726
+ /* @__PURE__ */ jsx6(Text6, { color: isProcessing ? THEME.primary : THEME.gray, children: isProcessing ? "Running " : "Idle " }),
12727
+ /* @__PURE__ */ jsx6(Text6, { color: THEME.white, children: formatElapsed(elapsedTime) })
12455
12728
  ] })
12456
12729
  ]
12457
12730
  }
@@ -12463,9 +12736,9 @@ var footer_default = Footer;
12463
12736
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
12464
12737
  var App = ({ autoApprove = false, target }) => {
12465
12738
  const { exit } = useApp();
12466
- const [input, setInput] = useState4("");
12467
- const [secretInput, setSecretInput] = useState4("");
12468
- const [autoApproveMode, setAutoApproveMode] = useState4(autoApprove);
12739
+ const [input, setInput] = useState5("");
12740
+ const [secretInput, setSecretInput] = useState5("");
12741
+ const [autoApproveMode, setAutoApproveMode] = useState5(autoApprove);
12469
12742
  const {
12470
12743
  agent,
12471
12744
  messages,
@@ -12484,11 +12757,11 @@ var App = ({ autoApprove = false, target }) => {
12484
12757
  addMessage,
12485
12758
  refreshStats
12486
12759
  } = useAgent(autoApproveMode, target);
12487
- const isProcessingRef = useRef4(isProcessing);
12760
+ const isProcessingRef = useRef5(isProcessing);
12488
12761
  isProcessingRef.current = isProcessing;
12489
- const autoApproveModeRef = useRef4(autoApproveMode);
12762
+ const autoApproveModeRef = useRef5(autoApproveMode);
12490
12763
  autoApproveModeRef.current = autoApproveMode;
12491
- const inputRequestRef = useRef4(inputRequest);
12764
+ const inputRequestRef = useRef5(inputRequest);
12492
12765
  inputRequestRef.current = inputRequest;
12493
12766
  const handleExit = useCallback4(() => {
12494
12767
  const ir = inputRequestRef.current;
@@ -12731,6 +13004,7 @@ var CLI_SCAN_TYPES = Object.freeze([
12731
13004
  ]);
12732
13005
 
12733
13006
  // src/platform/tui/main.tsx
13007
+ import gradient from "gradient-string";
12734
13008
  import { jsx as jsx8 } from "react/jsx-runtime";
12735
13009
  initDebugLogger();
12736
13010
  var program = new Command();
@@ -12739,13 +13013,13 @@ program.command("interactive", { isDefault: true }).alias("i").description("Star
12739
13013
  const opts = program.opts();
12740
13014
  const skipPermissions = opts.dangerouslySkipPermissions || false;
12741
13015
  console.clear();
12742
- console.log(chalk.hex(THEME.primary)(ASCII_BANNER));
13016
+ console.log(gradient([HEX.primary, HEX.cyan, HEX.teal]).multiline(ASCII_BANNER));
12743
13017
  console.log(
12744
- " " + chalk.hex(THEME.text.secondary)(`v${APP_VERSION}`) + chalk.hex(THEME.text.muted)(" \u2502 ") + chalk.hex(THEME.primary)("Type /help for commands") + "\n"
13018
+ " " + chalk.hex(HEX.gray)(`v${APP_VERSION}`) + chalk.hex(HEX.gray)(" \u2502 ") + chalk.hex(HEX.primary)("Type /help for commands") + "\n"
12745
13019
  );
12746
13020
  if (skipPermissions) {
12747
- console.log(chalk.hex(THEME.status.error)("[!] WARNING: Running with --dangerously-skip-permissions"));
12748
- console.log(chalk.hex(THEME.status.error)("[!] All tool executions will be auto-approved!\n"));
13021
+ console.log(chalk.hex(HEX.red)("[!] WARNING: Running with --dangerously-skip-permissions"));
13022
+ console.log(chalk.hex(HEX.red)("[!] All tool executions will be auto-approved!\n"));
12749
13023
  }
12750
13024
  const { waitUntilExit } = render(
12751
13025
  /* @__PURE__ */ jsx8(
@@ -12761,11 +13035,11 @@ program.command("interactive", { isDefault: true }).alias("i").description("Star
12761
13035
  program.command("run <objective>").alias("r").description("Run a single objective and exit").option("-o, --output <file>", "Output file for results").option("--max-steps <n>", "Maximum number of steps", String(CLI_DEFAULT.MAX_STEPS)).action(async (objective, options) => {
12762
13036
  const opts = program.opts();
12763
13037
  const skipPermissions = opts.dangerouslySkipPermissions || false;
12764
- console.log(chalk.hex(THEME.primary)(ASCII_BANNER));
13038
+ console.log(gradient([HEX.primary, HEX.cyan, HEX.teal]).multiline(ASCII_BANNER));
12765
13039
  if (skipPermissions) {
12766
- console.log(chalk.hex(THEME.status.error)("[!] WARNING: Running with --dangerously-skip-permissions\n"));
13040
+ console.log(chalk.hex(HEX.red)("[!] WARNING: Running with --dangerously-skip-permissions\n"));
12767
13041
  }
12768
- console.log(chalk.hex(THEME.primary)(`[target] Objective: ${objective}
13042
+ console.log(chalk.hex(HEX.primary)(`[target] Objective: ${objective}
12769
13043
  `));
12770
13044
  const agent = AgentFactory.createMainAgent(skipPermissions);
12771
13045
  if (skipPermissions) {
@@ -12782,18 +13056,18 @@ program.command("run <objective>").alias("r").description("Run a single objectiv
12782
13056
  process.on("SIGTERM", () => shutdown(EXIT_CODES.SIGTERM));
12783
13057
  try {
12784
13058
  const result2 = await agent.execute(objective);
12785
- console.log(chalk.hex(THEME.status.success)("\n[+] Assessment complete!\n"));
13059
+ console.log(chalk.hex(HEX.gray)("\n[+] Assessment complete!\n"));
12786
13060
  console.log(result2);
12787
13061
  if (options.output) {
12788
13062
  const fs = await import("fs/promises");
12789
13063
  await fs.writeFile(options.output, JSON.stringify({ result: result2 }, null, 2));
12790
- console.log(chalk.hex(THEME.primary)(`
13064
+ console.log(chalk.hex(HEX.primary)(`
12791
13065
  [+] Report saved to: ${options.output}`));
12792
13066
  }
12793
13067
  await shutdown(0);
12794
13068
  } catch (error) {
12795
13069
  const errorMessage = error instanceof Error ? error.message : String(error);
12796
- console.error(chalk.hex(THEME.status.error)(`
13070
+ console.error(chalk.hex(HEX.red)(`
12797
13071
  [-] Failed: ${errorMessage}`));
12798
13072
  await shutdown(1);
12799
13073
  }
@@ -12801,8 +13075,8 @@ program.command("run <objective>").alias("r").description("Run a single objectiv
12801
13075
  program.command("scan <target>").description("Quick scan a target").option("-s, --scan-type <type>", `Scan type (${CLI_SCAN_TYPES.join("|")})`, CLI_DEFAULT.SCAN_TYPE).option("-p, --ports <ports>", "Specific ports to scan").action(async (target, options) => {
12802
13076
  const opts = program.opts();
12803
13077
  const skipPermissions = opts.dangerouslySkipPermissions || false;
12804
- console.log(chalk.hex(THEME.primary)(ASCII_BANNER));
12805
- console.log(chalk.hex(THEME.primary)(`
13078
+ console.log(gradient([HEX.primary, HEX.cyan, HEX.teal]).multiline(ASCII_BANNER));
13079
+ console.log(chalk.hex(HEX.primary)(`
12806
13080
  [scan] Target: ${target} (${options.scanType})
12807
13081
  `));
12808
13082
  const agent = AgentFactory.createMainAgent(skipPermissions);
@@ -12815,62 +13089,61 @@ program.command("scan <target>").description("Quick scan a target").option("-s,
12815
13089
  process.on("SIGTERM", () => shutdown(EXIT_CODES.SIGTERM));
12816
13090
  try {
12817
13091
  await agent.execute(`Perform a ${options.scanType} scan on ${target}${options.ports ? ` focusing on ports ${options.ports}` : ""}. Analyze the results and identify potential vulnerabilities.`);
12818
- console.log(chalk.hex(THEME.status.success)("[+] Scan complete!"));
13092
+ console.log(chalk.hex(HEX.gray)("[+] Scan complete!"));
12819
13093
  await shutdown(0);
12820
13094
  } catch (error) {
12821
13095
  const errorMessage = error instanceof Error ? error.message : String(error);
12822
- console.error(chalk.hex(THEME.status.error)(`[-] Scan failed: ${errorMessage}`));
13096
+ console.error(chalk.hex(HEX.red)(`[-] Scan failed: ${errorMessage}`));
12823
13097
  await shutdown(1);
12824
13098
  }
12825
13099
  });
12826
13100
  program.command("help-extended").description("Show extended help with examples").action(() => {
12827
- console.log(chalk.hex(THEME.primary)(ASCII_BANNER));
13101
+ console.log(gradient([HEX.primary, HEX.cyan, HEX.teal]).multiline(ASCII_BANNER));
12828
13102
  console.log(`
12829
- ${chalk.hex(THEME.primary)(APP_NAME + " - Autonomous Penetration Testing AI")}
13103
+ ${chalk.hex(HEX.primary)(APP_NAME + " - Autonomous Penetration Testing AI")}
12830
13104
 
12831
- ${chalk.hex(THEME.status.warning)("Usage:")}
13105
+ ${chalk.hex(HEX.yellow)("Usage:")}
12832
13106
 
12833
- ${chalk.hex(THEME.status.success)("$ pentesting")} Start interactive mode
12834
- ${chalk.hex(THEME.status.success)("$ pentesting -t 192.168.1.1")} Start with target
12835
- ${chalk.hex(THEME.status.success)("$ pentesting --dangerously-skip-permissions")} Auto-approve all tools
13107
+ ${chalk.hex(HEX.gray)("$ pentesting")} Start interactive mode
13108
+ ${chalk.hex(HEX.gray)("$ pentesting -t 192.168.1.1")} Start with target
13109
+ ${chalk.hex(HEX.gray)("$ pentesting --dangerously-skip-permissions")} Auto-approve all tools
12836
13110
 
12837
- ${chalk.hex(THEME.status.warning)("Commands:")}
13111
+ ${chalk.hex(HEX.yellow)("Commands:")}
12838
13112
 
12839
- ${chalk.hex(THEME.primary)("pentesting")} Interactive TUI mode
12840
- ${chalk.hex(THEME.primary)("pentesting run <objective>")} Run single objective
12841
- ${chalk.hex(THEME.primary)("pentesting scan <target>")} Quick scan target
13113
+ ${chalk.hex(HEX.primary)("pentesting")} Interactive TUI mode
13114
+ ${chalk.hex(HEX.primary)("pentesting run <objective>")} Run single objective
13115
+ ${chalk.hex(HEX.primary)("pentesting scan <target>")} Quick scan target
12842
13116
 
12843
- ${chalk.hex(THEME.status.warning)("Options:")}
13117
+ ${chalk.hex(HEX.yellow)("Options:")}
12844
13118
 
12845
- ${chalk.hex(THEME.primary)("--dangerously-skip-permissions")} Skip all permission prompts
12846
- ${chalk.hex(THEME.primary)("-t, --target <ip>")} Set target
12847
- ${chalk.hex(THEME.primary)("-o, --output <file>")} Save results to file
13119
+ ${chalk.hex(HEX.primary)("--dangerously-skip-permissions")} Skip all permission prompts
13120
+ ${chalk.hex(HEX.primary)("-t, --target <ip>")} Set target
13121
+ ${chalk.hex(HEX.primary)("-o, --output <file>")} Save results to file
12848
13122
 
12849
- ${chalk.hex(THEME.status.warning)("Interactive Commands:")}
13123
+ ${chalk.hex(HEX.yellow)("Interactive Commands:")}
12850
13124
 
12851
- ${chalk.hex(THEME.primary)("/target <ip>")} Set target
12852
- ${chalk.hex(THEME.primary)("/start")} Start autonomous mode
12853
- ${chalk.hex(THEME.primary)("/config")} Manage configuration
12854
- ${chalk.hex(THEME.primary)("/hint <text>")} Provide hint
12855
- ${chalk.hex(THEME.primary)("/findings")} Show findings
12856
- ${chalk.hex(THEME.primary)("/reset")} Reset session
13125
+ ${chalk.hex(HEX.primary)("/target <ip>")} Set target
13126
+ ${chalk.hex(HEX.primary)("/start")} Start autonomous mode
13127
+ ${chalk.hex(HEX.primary)("/hint <text>")} Provide hint
13128
+ ${chalk.hex(HEX.primary)("/findings")} Show findings
13129
+ ${chalk.hex(HEX.primary)("/clear")} Reset session
12857
13130
 
12858
- ${chalk.hex(THEME.status.warning)("Examples:")}
13131
+ ${chalk.hex(HEX.yellow)("Examples:")}
12859
13132
 
12860
- ${chalk.hex(THEME.text.muted)("# Full autonomous mode")}
13133
+ ${chalk.hex(HEX.gray)("# Full autonomous mode")}
12861
13134
  $ pentesting --dangerously-skip-permissions -t 10.10.10.5
12862
13135
 
12863
- ${chalk.hex(THEME.text.muted)("# Run specific objective")}
13136
+ ${chalk.hex(HEX.gray)("# Run specific objective")}
12864
13137
  $ pentesting run "Find SQL injection" -t http://target.com -o report.json
12865
13138
 
12866
- ${chalk.hex(THEME.text.muted)("# Quick vulnerability scan")}
13139
+ ${chalk.hex(HEX.gray)("# Quick vulnerability scan")}
12867
13140
  $ pentesting scan 192.168.1.1 -s vuln
12868
13141
 
12869
- ${chalk.hex(THEME.status.warning)("Environment:")}
13142
+ ${chalk.hex(HEX.yellow)("Environment:")}
12870
13143
 
12871
- ${chalk.hex(THEME.primary)("PENTEST_API_KEY")} Required - LLM API key
12872
- ${chalk.hex(THEME.primary)("PENTEST_BASE_URL")} Optional - AI API base URL
12873
- ${chalk.hex(THEME.primary)("PENTEST_MODEL")} Optional - Model override
13144
+ ${chalk.hex(HEX.primary)("PENTEST_API_KEY")} Required - LLM API key
13145
+ ${chalk.hex(HEX.primary)("PENTEST_BASE_URL")} Optional - AI API base URL
13146
+ ${chalk.hex(HEX.primary)("PENTEST_MODEL")} Optional - Model override
12874
13147
  `);
12875
13148
  });
12876
13149
  program.parse();