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 +506 -233
- package/dist/prompts/base.md +38 -8
- package/package.json +1 -1
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
|
|
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
|
|
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.
|
|
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:
|
|
9140
|
+
content: stripped.cleanText,
|
|
9105
9141
|
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
9106
9142
|
rawResponse: null,
|
|
9107
|
-
reasoning:
|
|
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 (
|
|
9141
|
-
|
|
9142
|
-
|
|
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
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
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
|
|
10146
|
-
if (
|
|
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
|
-
|
|
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: () =>
|
|
10164
|
-
|
|
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
|
|
10192
|
-
phase
|
|
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: "
|
|
11465
|
-
//
|
|
11466
|
-
|
|
11467
|
-
//
|
|
11468
|
-
|
|
11469
|
-
//
|
|
11470
|
-
|
|
11471
|
-
//
|
|
11472
|
-
|
|
11473
|
-
//
|
|
11474
|
-
|
|
11475
|
-
//
|
|
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.
|
|
11492
|
-
//
|
|
11617
|
+
success: COLORS.teal,
|
|
11618
|
+
// teal for success
|
|
11493
11619
|
warning: COLORS.yellow,
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
//
|
|
11620
|
+
// amber for warnings
|
|
11621
|
+
error: COLORS.red
|
|
11622
|
+
// red for errors
|
|
11497
11623
|
},
|
|
11498
11624
|
border: {
|
|
11499
|
-
default: "
|
|
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: [
|
|
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
|
|
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
|
-
/**
|
|
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.
|
|
11594
|
-
|
|
11595
|
-
|
|
11596
|
-
|
|
11597
|
-
|
|
11598
|
-
|
|
11599
|
-
|
|
11600
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
|
|
11762
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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", `
|
|
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]: "
|
|
11937
|
-
[COMMAND_EVENT_TYPES.TOOL_INSTALLED]: "
|
|
11938
|
-
[COMMAND_EVENT_TYPES.TOOL_INSTALL_FAILED]: "
|
|
11939
|
-
[COMMAND_EVENT_TYPES.TOOL_RETRY]: "
|
|
11940
|
-
[COMMAND_EVENT_TYPES.COMMAND_START]: "
|
|
11941
|
-
[COMMAND_EVENT_TYPES.COMMAND_SUCCESS]: "
|
|
11942
|
-
[COMMAND_EVENT_TYPES.COMMAND_FAILED]: "
|
|
11943
|
-
[COMMAND_EVENT_TYPES.COMMAND_ERROR]: "
|
|
11944
|
-
[COMMAND_EVENT_TYPES.INPUT_REQUIRED]: "
|
|
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 =
|
|
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 =
|
|
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.
|
|
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.
|
|
12266
|
+
background: THEME.gray
|
|
12073
12267
|
};
|
|
12074
|
-
return roleColors[role] || THEME.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
12118
|
-
/* @__PURE__ */ jsx(Text, { color: THEME.
|
|
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.
|
|
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.
|
|
12135
|
-
warning: THEME.
|
|
12136
|
-
critical: THEME.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
12364
|
+
/* @__PURE__ */ jsxs(Text, { color: THEME.red, children: [
|
|
12171
12365
|
" ",
|
|
12172
12366
|
ICONS.error,
|
|
12173
12367
|
" "
|
|
12174
12368
|
] }),
|
|
12175
|
-
/* @__PURE__ */ jsxs(Text, { color: THEME.
|
|
12369
|
+
/* @__PURE__ */ jsxs(Text, { color: THEME.gray, children: [
|
|
12176
12370
|
"[",
|
|
12177
12371
|
z.processId,
|
|
12178
12372
|
"] "
|
|
12179
12373
|
] }),
|
|
12180
|
-
/* @__PURE__ */ jsxs(Text, { color: THEME.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
12226
|
-
|
|
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 =
|
|
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.
|
|
12270
|
-
/* @__PURE__ */ jsxs3(Text4, { color: THEME.
|
|
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
|
-
|
|
12275
|
-
" \xB7 ",
|
|
12276
|
-
truncateError(retryState.error)
|
|
12537
|
+
retryState.attempt,
|
|
12538
|
+
"/",
|
|
12539
|
+
retryState.maxRetries
|
|
12277
12540
|
] }),
|
|
12278
|
-
/* @__PURE__ */ jsxs3(Text4, { color: THEME.
|
|
12279
|
-
" \
|
|
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__ */
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
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.
|
|
12291
|
-
" ",
|
|
12292
|
-
|
|
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
|
|
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 =
|
|
12592
|
+
const suggestionsRef = useRef4(suggestions);
|
|
12323
12593
|
suggestionsRef.current = suggestions;
|
|
12324
|
-
const isSlashModeRef =
|
|
12594
|
+
const isSlashModeRef = useRef4(isSlashMode);
|
|
12325
12595
|
isSlashModeRef.current = isSlashMode;
|
|
12326
|
-
const hasArgsRef =
|
|
12596
|
+
const hasArgsRef = useRef4(hasArgs);
|
|
12327
12597
|
hasArgsRef.current = hasArgs;
|
|
12328
|
-
const inputRequestRef =
|
|
12598
|
+
const inputRequestRef = useRef4(inputRequest);
|
|
12329
12599
|
inputRequestRef.current = inputRequest;
|
|
12330
|
-
const onChangeRef =
|
|
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
|
-
|
|
12609
|
+
onChangeRef.current(completed);
|
|
12610
|
+
setInputKey((k) => k + 1);
|
|
12340
12611
|
}
|
|
12341
12612
|
}, []));
|
|
12342
12613
|
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
12343
|
-
|
|
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
|
-
|
|
12622
|
+
height: showPreview ? void 0 : 0,
|
|
12623
|
+
children: showPreview && suggestions.map((cmd, i) => {
|
|
12352
12624
|
const isFirst = i === 0;
|
|
12353
|
-
const nameColor = isFirst ? THEME.
|
|
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.
|
|
12362
|
-
aliasText && /* @__PURE__ */ jsx5(Text5, { color: THEME.
|
|
12363
|
-
/* @__PURE__ */ jsxs4(Text5, { color: THEME.
|
|
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.
|
|
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.
|
|
12380
|
-
/* @__PURE__ */ jsxs4(Text5, { color: THEME.
|
|
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.
|
|
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.
|
|
12708
|
+
/* @__PURE__ */ jsxs5(Text6, { color: THEME.gray, children: [
|
|
12436
12709
|
"Phase: ",
|
|
12437
|
-
/* @__PURE__ */ jsx6(Text6, { color: THEME.
|
|
12710
|
+
/* @__PURE__ */ jsx6(Text6, { color: THEME.white, children: phase })
|
|
12438
12711
|
] }),
|
|
12439
|
-
/* @__PURE__ */ jsxs5(Text6, { color: THEME.
|
|
12712
|
+
/* @__PURE__ */ jsxs5(Text6, { color: THEME.gray, children: [
|
|
12440
12713
|
"Targets: ",
|
|
12441
|
-
/* @__PURE__ */ jsx6(Text6, { color: THEME.
|
|
12714
|
+
/* @__PURE__ */ jsx6(Text6, { color: THEME.white, children: targets })
|
|
12442
12715
|
] }),
|
|
12443
|
-
/* @__PURE__ */ jsxs5(Text6, { color: THEME.
|
|
12716
|
+
/* @__PURE__ */ jsxs5(Text6, { color: THEME.gray, children: [
|
|
12444
12717
|
"Findings: ",
|
|
12445
|
-
/* @__PURE__ */ jsx6(Text6, { color: THEME.
|
|
12718
|
+
/* @__PURE__ */ jsx6(Text6, { color: THEME.white, children: findings })
|
|
12446
12719
|
] }),
|
|
12447
|
-
/* @__PURE__ */ jsxs5(Text6, { color: THEME.
|
|
12720
|
+
/* @__PURE__ */ jsxs5(Text6, { color: THEME.gray, children: [
|
|
12448
12721
|
"Tasks: ",
|
|
12449
|
-
/* @__PURE__ */ jsx6(Text6, { color: THEME.
|
|
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.
|
|
12454
|
-
/* @__PURE__ */ jsx6(Text6, { color: THEME.
|
|
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] =
|
|
12467
|
-
const [secretInput, setSecretInput] =
|
|
12468
|
-
const [autoApproveMode, setAutoApproveMode] =
|
|
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 =
|
|
12760
|
+
const isProcessingRef = useRef5(isProcessing);
|
|
12488
12761
|
isProcessingRef.current = isProcessing;
|
|
12489
|
-
const autoApproveModeRef =
|
|
12762
|
+
const autoApproveModeRef = useRef5(autoApproveMode);
|
|
12490
12763
|
autoApproveModeRef.current = autoApproveMode;
|
|
12491
|
-
const inputRequestRef =
|
|
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(
|
|
13016
|
+
console.log(gradient([HEX.primary, HEX.cyan, HEX.teal]).multiline(ASCII_BANNER));
|
|
12743
13017
|
console.log(
|
|
12744
|
-
" " + chalk.hex(
|
|
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(
|
|
12748
|
-
console.log(chalk.hex(
|
|
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(
|
|
13038
|
+
console.log(gradient([HEX.primary, HEX.cyan, HEX.teal]).multiline(ASCII_BANNER));
|
|
12765
13039
|
if (skipPermissions) {
|
|
12766
|
-
console.log(chalk.hex(
|
|
13040
|
+
console.log(chalk.hex(HEX.red)("[!] WARNING: Running with --dangerously-skip-permissions\n"));
|
|
12767
13041
|
}
|
|
12768
|
-
console.log(chalk.hex(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
12805
|
-
console.log(chalk.hex(
|
|
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(
|
|
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(
|
|
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(
|
|
13101
|
+
console.log(gradient([HEX.primary, HEX.cyan, HEX.teal]).multiline(ASCII_BANNER));
|
|
12828
13102
|
console.log(`
|
|
12829
|
-
${chalk.hex(
|
|
13103
|
+
${chalk.hex(HEX.primary)(APP_NAME + " - Autonomous Penetration Testing AI")}
|
|
12830
13104
|
|
|
12831
|
-
${chalk.hex(
|
|
13105
|
+
${chalk.hex(HEX.yellow)("Usage:")}
|
|
12832
13106
|
|
|
12833
|
-
${chalk.hex(
|
|
12834
|
-
${chalk.hex(
|
|
12835
|
-
${chalk.hex(
|
|
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(
|
|
13111
|
+
${chalk.hex(HEX.yellow)("Commands:")}
|
|
12838
13112
|
|
|
12839
|
-
${chalk.hex(
|
|
12840
|
-
${chalk.hex(
|
|
12841
|
-
${chalk.hex(
|
|
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(
|
|
13117
|
+
${chalk.hex(HEX.yellow)("Options:")}
|
|
12844
13118
|
|
|
12845
|
-
${chalk.hex(
|
|
12846
|
-
${chalk.hex(
|
|
12847
|
-
${chalk.hex(
|
|
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(
|
|
13123
|
+
${chalk.hex(HEX.yellow)("Interactive Commands:")}
|
|
12850
13124
|
|
|
12851
|
-
${chalk.hex(
|
|
12852
|
-
${chalk.hex(
|
|
12853
|
-
${chalk.hex(
|
|
12854
|
-
${chalk.hex(
|
|
12855
|
-
${chalk.hex(
|
|
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(
|
|
13131
|
+
${chalk.hex(HEX.yellow)("Examples:")}
|
|
12859
13132
|
|
|
12860
|
-
${chalk.hex(
|
|
13133
|
+
${chalk.hex(HEX.gray)("# Full autonomous mode")}
|
|
12861
13134
|
$ pentesting --dangerously-skip-permissions -t 10.10.10.5
|
|
12862
13135
|
|
|
12863
|
-
${chalk.hex(
|
|
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(
|
|
13139
|
+
${chalk.hex(HEX.gray)("# Quick vulnerability scan")}
|
|
12867
13140
|
$ pentesting scan 192.168.1.1 -s vuln
|
|
12868
13141
|
|
|
12869
|
-
${chalk.hex(
|
|
13142
|
+
${chalk.hex(HEX.yellow)("Environment:")}
|
|
12870
13143
|
|
|
12871
|
-
${chalk.hex(
|
|
12872
|
-
${chalk.hex(
|
|
12873
|
-
${chalk.hex(
|
|
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();
|