pentesting 0.56.1 → 0.56.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +164 -49
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -711,7 +711,7 @@ var INPUT_PROMPT_PATTERNS = [
|
|
|
711
711
|
|
|
712
712
|
// src/shared/constants/agent.ts
|
|
713
713
|
var APP_NAME = "Pentest AI";
|
|
714
|
-
var APP_VERSION = "0.56.
|
|
714
|
+
var APP_VERSION = "0.56.3";
|
|
715
715
|
var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
|
|
716
716
|
var LLM_ROLES = {
|
|
717
717
|
SYSTEM: "system",
|
|
@@ -768,7 +768,7 @@ import gradient from "gradient-string";
|
|
|
768
768
|
|
|
769
769
|
// src/platform/tui/app.tsx
|
|
770
770
|
import { useState as useState8, useCallback as useCallback11, useRef as useRef10 } from "react";
|
|
771
|
-
import { Box as Box18, useApp, useStdout as
|
|
771
|
+
import { Box as Box18, useApp, useStdout as useStdout4 } from "ink";
|
|
772
772
|
|
|
773
773
|
// src/platform/tui/hooks/useAgent.ts
|
|
774
774
|
import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2, useRef as useRef3 } from "react";
|
|
@@ -14911,7 +14911,10 @@ var formatFlags = (flags) => {
|
|
|
14911
14911
|
if (!flags.length) return "";
|
|
14912
14912
|
const lines = [];
|
|
14913
14913
|
const total = flags.length;
|
|
14914
|
-
|
|
14914
|
+
const label = `\u2500\u2500\u2500 Captured (${total}) `;
|
|
14915
|
+
const cols = process.stdout?.columns ?? 80;
|
|
14916
|
+
const fillWidth = Math.max(3, cols - 2 - label.length);
|
|
14917
|
+
lines.push(`${label}${"\u2500".repeat(fillWidth)}`);
|
|
14915
14918
|
lines.push("");
|
|
14916
14919
|
flags.forEach((flag, i) => {
|
|
14917
14920
|
lines.push(` ${(i + 1).toString().padStart(2, " ")}. ${flag}`);
|
|
@@ -14920,6 +14923,21 @@ var formatFlags = (flags) => {
|
|
|
14920
14923
|
};
|
|
14921
14924
|
|
|
14922
14925
|
// src/platform/tui/hooks/commands/formatters/graph-summary.ts
|
|
14926
|
+
var getBoxWidth = () => Math.max(30, (process.stdout?.columns ?? 80) - 2);
|
|
14927
|
+
var boxLine = (content, width) => {
|
|
14928
|
+
const inner = width - 2;
|
|
14929
|
+
const truncated = content.length > inner ? content.slice(0, inner - 1) + "\u2026" : content;
|
|
14930
|
+
return `\u2502 ${truncated.padEnd(inner - 1)}`;
|
|
14931
|
+
};
|
|
14932
|
+
var formatTargetLine = (target) => {
|
|
14933
|
+
if (target.ports.length === 0) return target.ip;
|
|
14934
|
+
const portList = target.ports.map((p) => `${p.port}`).join(", ");
|
|
14935
|
+
return `${target.ip} \u2192 ${target.ip}:${portList}`;
|
|
14936
|
+
};
|
|
14937
|
+
var formatServiceLabel = (target, port) => {
|
|
14938
|
+
const svc = port.version ? `${port.service}/${port.version}` : port.service;
|
|
14939
|
+
return `${target.ip}:${port.port} (${svc})`;
|
|
14940
|
+
};
|
|
14923
14941
|
var formatFindingsWithFlags = (findings, flags) => {
|
|
14924
14942
|
const findingsOutput = formatFindings(findings);
|
|
14925
14943
|
const flagsOutput = formatFlags(flags);
|
|
@@ -14929,40 +14947,109 @@ ${flagsOutput}`;
|
|
|
14929
14947
|
}
|
|
14930
14948
|
return findingsOutput;
|
|
14931
14949
|
};
|
|
14932
|
-
var formatGraphWithSummary = (
|
|
14950
|
+
var formatGraphWithSummary = (state, findings, flags) => {
|
|
14933
14951
|
const lines = [];
|
|
14934
|
-
|
|
14935
|
-
|
|
14936
|
-
|
|
14937
|
-
|
|
14938
|
-
|
|
14939
|
-
|
|
14940
|
-
|
|
14941
|
-
const
|
|
14942
|
-
|
|
14943
|
-
|
|
14944
|
-
|
|
14945
|
-
|
|
14946
|
-
|
|
14952
|
+
const w = getBoxWidth();
|
|
14953
|
+
const innerDash = w - 2;
|
|
14954
|
+
const targets = state.getAllTargets();
|
|
14955
|
+
const graphStats = state.attackGraph.getStats();
|
|
14956
|
+
const allNodes = state.attackGraph.getAllNodes();
|
|
14957
|
+
const hostNodes = allNodes.filter((n) => n.type === NODE_TYPE.HOST);
|
|
14958
|
+
const serviceNodes = allNodes.filter((n) => n.type === NODE_TYPE.SERVICE);
|
|
14959
|
+
const vulnNodes = allNodes.filter((n) => n.type === NODE_TYPE.VULNERABILITY);
|
|
14960
|
+
const hostCount = hostNodes.length || targets.length;
|
|
14961
|
+
const serviceCount = serviceNodes.length || targets.reduce((sum, t) => sum + t.ports.length, 0);
|
|
14962
|
+
const vulnCount = findings.length;
|
|
14963
|
+
const topTitle = "\u2500\u2500\u2500 Attack Graph ";
|
|
14964
|
+
lines.push(`\u250C${topTitle}${"\u2500".repeat(Math.max(0, innerDash - topTitle.length))}\u2510`);
|
|
14965
|
+
lines.push(boxLine(`\u{1F5A5} ${hostCount} \u26A0 ${vulnCount} \u2699 ${serviceCount}`, w));
|
|
14966
|
+
lines.push(boxLine("", w));
|
|
14967
|
+
lines.push(boxLine(`\u{1F5A5} HOST (${hostCount})`, w));
|
|
14968
|
+
if (targets.length > 0) {
|
|
14969
|
+
for (const t of targets.slice(0, 5)) {
|
|
14970
|
+
lines.push(boxLine(` \u25CB ${formatTargetLine(t)}`, w));
|
|
14971
|
+
}
|
|
14972
|
+
if (targets.length > 5) {
|
|
14973
|
+
lines.push(boxLine(` ... and ${targets.length - 5} more hosts`, w));
|
|
14974
|
+
}
|
|
14975
|
+
} else if (hostNodes.length > 0) {
|
|
14976
|
+
for (const node of hostNodes.slice(0, 5)) {
|
|
14977
|
+
lines.push(boxLine(` \u25CB ${node.label}`, w));
|
|
14978
|
+
}
|
|
14979
|
+
if (hostNodes.length > 5) {
|
|
14980
|
+
lines.push(boxLine(` ... and ${hostNodes.length - 5} more hosts`, w));
|
|
14981
|
+
}
|
|
14982
|
+
} else {
|
|
14983
|
+
lines.push(boxLine(" (no hosts discovered)", w));
|
|
14947
14984
|
}
|
|
14948
|
-
|
|
14949
|
-
|
|
14985
|
+
lines.push(boxLine("", w));
|
|
14986
|
+
lines.push(boxLine(`\u26A0 VULNERABILITY (${vulnCount})`, w));
|
|
14987
|
+
if (findings.length > 0) {
|
|
14988
|
+
const sortedFindings = [...findings].sort((a, b) => b.confidence - a.confidence).slice(0, 5);
|
|
14989
|
+
for (const f of sortedFindings) {
|
|
14990
|
+
const icon = confIcon(f.confidence);
|
|
14991
|
+
const cat = f.category ? ` \u2502 ${f.category}` : "";
|
|
14992
|
+
lines.push(boxLine(` \u25CB ${icon} ${f.title.slice(0, 60)}${f.title.length > 60 ? "..." : ""}`, w));
|
|
14993
|
+
lines.push(boxLine(` ${confLabel(f.confidence).toUpperCase()} \u2502 ${f.severity.toUpperCase()}${cat}`, w));
|
|
14994
|
+
}
|
|
14995
|
+
if (findings.length > 5) {
|
|
14996
|
+
lines.push(boxLine(` ... and ${findings.length - 5} more findings`, w));
|
|
14997
|
+
}
|
|
14998
|
+
} else if (vulnNodes.length > 0) {
|
|
14999
|
+
for (const node of vulnNodes.slice(0, 5)) {
|
|
15000
|
+
lines.push(boxLine(` \u25CB ${node.label}`, w));
|
|
15001
|
+
}
|
|
15002
|
+
if (vulnNodes.length > 5) {
|
|
15003
|
+
lines.push(boxLine(` ... and ${vulnNodes.length - 5} more`, w));
|
|
15004
|
+
}
|
|
15005
|
+
} else {
|
|
15006
|
+
lines.push(boxLine(" (no vulnerabilities found)", w));
|
|
14950
15007
|
}
|
|
14951
15008
|
const cveFindings = findings.filter((f) => f.title.includes("CVE"));
|
|
14952
15009
|
if (cveFindings.length > 0) {
|
|
14953
|
-
|
|
15010
|
+
const cveList = cveFindings.slice(0, 3).map((f) => f.title.match(/CVE-\d{4}-\d+/)?.[0] ?? f.title).join(", ");
|
|
15011
|
+
const suffix = cveFindings.length > 3 ? ` (+${cveFindings.length - 3} more)` : "";
|
|
15012
|
+
lines.push(boxLine(` \u25CB CVE found: ${cveList}${suffix}`, w));
|
|
15013
|
+
}
|
|
15014
|
+
lines.push(boxLine("", w));
|
|
15015
|
+
lines.push(boxLine(`\u2699 SERVICE (${serviceCount})`, w));
|
|
15016
|
+
if (targets.length > 0) {
|
|
15017
|
+
let shownServices = 0;
|
|
15018
|
+
const maxShow = 5;
|
|
15019
|
+
for (const t of targets) {
|
|
15020
|
+
for (const p of t.ports) {
|
|
15021
|
+
if (shownServices >= maxShow) break;
|
|
15022
|
+
lines.push(boxLine(` \u25CB ${formatServiceLabel(t, p)}`, w));
|
|
15023
|
+
shownServices++;
|
|
15024
|
+
}
|
|
15025
|
+
if (shownServices >= maxShow) break;
|
|
15026
|
+
}
|
|
15027
|
+
const totalServices = targets.reduce((sum, t) => sum + t.ports.length, 0);
|
|
15028
|
+
if (totalServices > maxShow) {
|
|
15029
|
+
lines.push(boxLine(` ... and ${totalServices - maxShow} more services`, w));
|
|
15030
|
+
}
|
|
15031
|
+
} else if (serviceNodes.length > 0) {
|
|
15032
|
+
for (const node of serviceNodes.slice(0, 5)) {
|
|
15033
|
+
lines.push(boxLine(` \u25CB ${node.label}`, w));
|
|
15034
|
+
}
|
|
15035
|
+
if (serviceNodes.length > 5) {
|
|
15036
|
+
lines.push(boxLine(` ... and ${serviceNodes.length - 5} more`, w));
|
|
15037
|
+
}
|
|
15038
|
+
} else {
|
|
15039
|
+
lines.push(boxLine(" (no services discovered)", w));
|
|
14954
15040
|
}
|
|
14955
|
-
lines.push("\u2502");
|
|
14956
|
-
lines.push("\u2502 \u2699 SERVICE (1)");
|
|
14957
|
-
lines.push(`\u2502 \u25CB 138.2.89.94:443 (nginx/1.24.0 (Ubuntu) -> Apache CouchDB 3.5.1) \u2192 CVE search: https nginx/1.24.0 (Ubuntu) -> Apache CouchDB 3.5.1`);
|
|
14958
15041
|
if (flags.length > 0) {
|
|
14959
|
-
lines.push("
|
|
14960
|
-
lines.push(`\
|
|
14961
|
-
}
|
|
14962
|
-
lines.push("
|
|
14963
|
-
|
|
14964
|
-
lines.push(`\
|
|
14965
|
-
lines.push(
|
|
15042
|
+
lines.push(boxLine("", w));
|
|
15043
|
+
lines.push(boxLine(`\u{1F3F4} Captured: ${flags.length}`, w));
|
|
15044
|
+
}
|
|
15045
|
+
lines.push(boxLine("", w));
|
|
15046
|
+
const midTitle = "\u2500\u2500\u2500 Summary ";
|
|
15047
|
+
lines.push(`\u251C${midTitle}${"\u2500".repeat(Math.max(0, innerDash - midTitle.length))}\u2524`);
|
|
15048
|
+
lines.push(boxLine(
|
|
15049
|
+
`Nodes: ${graphStats.nodes} | Edges: ${graphStats.edges} | Succeeded: ${graphStats.succeeded} | Failed: ${graphStats.failed} | Chains: ${graphStats.chains}`,
|
|
15050
|
+
w
|
|
15051
|
+
));
|
|
15052
|
+
lines.push(`\u2514${"\u2500".repeat(innerDash)}\u2518`);
|
|
14966
15053
|
return lines.join("\n");
|
|
14967
15054
|
};
|
|
14968
15055
|
|
|
@@ -15020,7 +15107,7 @@ ${procData.stdout || "(no output)"}
|
|
|
15020
15107
|
const flags = state.getFlags();
|
|
15021
15108
|
const graphASCII = state.attackGraph.toASCII();
|
|
15022
15109
|
if (state.attackGraph.isEmpty() && (findings.length > 0 || flags.length > 0)) {
|
|
15023
|
-
ctx.showModal("graph", formatGraphWithSummary(
|
|
15110
|
+
ctx.showModal("graph", formatGraphWithSummary(state, findings, flags));
|
|
15024
15111
|
} else {
|
|
15025
15112
|
let output = graphASCII;
|
|
15026
15113
|
if (flags.length > 0) {
|
|
@@ -15035,7 +15122,7 @@ ${procData.stdout || "(no output)"}
|
|
|
15035
15122
|
const flags = state.getFlags();
|
|
15036
15123
|
const graphASCII = state.attackGraph.toASCII();
|
|
15037
15124
|
if (state.attackGraph.isEmpty() && (findings.length > 0 || flags.length > 0)) {
|
|
15038
|
-
ctx.showModal("graph", formatGraphWithSummary(
|
|
15125
|
+
ctx.showModal("graph", formatGraphWithSummary(state, findings, flags));
|
|
15039
15126
|
} else {
|
|
15040
15127
|
let output = graphASCII;
|
|
15041
15128
|
if (flags.length > 0) {
|
|
@@ -16160,17 +16247,21 @@ var AutocompletePreview = ({
|
|
|
16160
16247
|
};
|
|
16161
16248
|
|
|
16162
16249
|
// src/platform/tui/components/input/SecretInputArea.tsx
|
|
16163
|
-
import { Box as Box12, Text as Text14 } from "ink";
|
|
16250
|
+
import { Box as Box12, Text as Text14, useStdout } from "ink";
|
|
16164
16251
|
import TextInput from "ink-text-input";
|
|
16165
16252
|
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
16253
|
+
var OUTER_PADDING = 2;
|
|
16166
16254
|
var SecretInputArea = ({
|
|
16167
16255
|
inputRequest,
|
|
16168
16256
|
secretInput,
|
|
16169
16257
|
setSecretInput,
|
|
16170
16258
|
onSecretSubmit
|
|
16171
16259
|
}) => {
|
|
16260
|
+
const { stdout } = useStdout();
|
|
16261
|
+
const borderWidth = Math.max(10, (stdout?.columns ?? 80) - OUTER_PADDING);
|
|
16262
|
+
const borderLine = "\u2501".repeat(borderWidth);
|
|
16172
16263
|
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
|
|
16173
|
-
/* @__PURE__ */ jsx14(Box12, { children: /* @__PURE__ */ jsx14(Text14, { color: THEME.yellow, children:
|
|
16264
|
+
/* @__PURE__ */ jsx14(Box12, { children: /* @__PURE__ */ jsx14(Text14, { color: THEME.yellow, children: borderLine }) }),
|
|
16174
16265
|
/* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 1, children: [
|
|
16175
16266
|
/* @__PURE__ */ jsxs12(Box12, { children: [
|
|
16176
16267
|
/* @__PURE__ */ jsx14(Text14, { color: THEME.yellow, bold: true, children: "\u{1F512} " }),
|
|
@@ -16190,14 +16281,15 @@ var SecretInputArea = ({
|
|
|
16190
16281
|
)
|
|
16191
16282
|
] })
|
|
16192
16283
|
] }),
|
|
16193
|
-
/* @__PURE__ */ jsx14(Box12, { children: /* @__PURE__ */ jsx14(Text14, { color: THEME.yellow, children:
|
|
16284
|
+
/* @__PURE__ */ jsx14(Box12, { children: /* @__PURE__ */ jsx14(Text14, { color: THEME.yellow, children: borderLine }) })
|
|
16194
16285
|
] });
|
|
16195
16286
|
};
|
|
16196
16287
|
|
|
16197
16288
|
// src/platform/tui/components/input/NormalInputArea.tsx
|
|
16198
|
-
import { Box as Box13, Text as Text15 } from "ink";
|
|
16289
|
+
import { Box as Box13, Text as Text15, useStdout as useStdout2 } from "ink";
|
|
16199
16290
|
import TextInput2 from "ink-text-input";
|
|
16200
16291
|
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
16292
|
+
var OUTER_PADDING2 = 2;
|
|
16201
16293
|
var NormalInputArea = ({
|
|
16202
16294
|
inputKey,
|
|
16203
16295
|
value,
|
|
@@ -16205,8 +16297,11 @@ var NormalInputArea = ({
|
|
|
16205
16297
|
onSubmit,
|
|
16206
16298
|
placeholder
|
|
16207
16299
|
}) => {
|
|
16300
|
+
const { stdout } = useStdout2();
|
|
16301
|
+
const borderWidth = Math.max(10, (stdout?.columns ?? 80) - OUTER_PADDING2);
|
|
16302
|
+
const borderLine = "\u2500".repeat(borderWidth);
|
|
16208
16303
|
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
|
|
16209
|
-
/* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, color: THEME.dimGray, children:
|
|
16304
|
+
/* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, color: THEME.dimGray, children: borderLine }) }),
|
|
16210
16305
|
/* @__PURE__ */ jsxs13(Box13, { paddingX: 1, children: [
|
|
16211
16306
|
/* @__PURE__ */ jsx15(Text15, { color: THEME.primary, children: "\u276F " }),
|
|
16212
16307
|
/* @__PURE__ */ jsx15(
|
|
@@ -16220,7 +16315,7 @@ var NormalInputArea = ({
|
|
|
16220
16315
|
inputKey
|
|
16221
16316
|
)
|
|
16222
16317
|
] }),
|
|
16223
|
-
/* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, color: THEME.dimGray, children:
|
|
16318
|
+
/* @__PURE__ */ jsx15(Box13, { children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, color: THEME.dimGray, children: borderLine }) })
|
|
16224
16319
|
] });
|
|
16225
16320
|
};
|
|
16226
16321
|
|
|
@@ -16287,6 +16382,27 @@ var ChatInput = memo10(({
|
|
|
16287
16382
|
setSelectedIdx(0);
|
|
16288
16383
|
setInputKey((k) => k + 1);
|
|
16289
16384
|
}, []);
|
|
16385
|
+
const onSubmitRef = useRef8(onSubmit);
|
|
16386
|
+
onSubmitRef.current = onSubmit;
|
|
16387
|
+
const wrappedOnSubmit = useCallback9((val) => {
|
|
16388
|
+
if (showPreviewRef.current) {
|
|
16389
|
+
const sug = suggestionsRef.current;
|
|
16390
|
+
if (!sug.length) {
|
|
16391
|
+
onSubmitRef.current(val);
|
|
16392
|
+
return;
|
|
16393
|
+
}
|
|
16394
|
+
const best = sug[Math.min(selectedIdxRef.current, sug.length - 1)];
|
|
16395
|
+
if (best.args) {
|
|
16396
|
+
completeCommand(selectedIdxRef.current);
|
|
16397
|
+
} else {
|
|
16398
|
+
const completed = `/${best.name}`;
|
|
16399
|
+
onChangeRef.current(completed);
|
|
16400
|
+
onSubmitRef.current(completed);
|
|
16401
|
+
}
|
|
16402
|
+
return;
|
|
16403
|
+
}
|
|
16404
|
+
onSubmitRef.current(val);
|
|
16405
|
+
}, [completeCommand]);
|
|
16290
16406
|
useInput3(useCallback9((_input, key) => {
|
|
16291
16407
|
if (inputRequestRef.current.status === "active") return;
|
|
16292
16408
|
const sug = suggestionsRef.current;
|
|
@@ -16330,7 +16446,7 @@ var ChatInput = memo10(({
|
|
|
16330
16446
|
inputKey,
|
|
16331
16447
|
value,
|
|
16332
16448
|
onChange,
|
|
16333
|
-
onSubmit,
|
|
16449
|
+
onSubmit: wrappedOnSubmit,
|
|
16334
16450
|
placeholder
|
|
16335
16451
|
}
|
|
16336
16452
|
)
|
|
@@ -16361,6 +16477,7 @@ var Footer = memo11(({ phase, targets, findings, todo, elapsedTime, isProcessing
|
|
|
16361
16477
|
return /* @__PURE__ */ jsxs15(
|
|
16362
16478
|
Box15,
|
|
16363
16479
|
{
|
|
16480
|
+
width: "100%",
|
|
16364
16481
|
paddingX: 1,
|
|
16365
16482
|
justifyContent: "space-between",
|
|
16366
16483
|
overflow: "hidden",
|
|
@@ -16412,7 +16529,7 @@ var footer_default = Footer;
|
|
|
16412
16529
|
|
|
16413
16530
|
// src/platform/tui/components/Modal.tsx
|
|
16414
16531
|
import { useMemo as useMemo2, memo as memo12, useCallback as useCallback10, useRef as useRef9 } from "react";
|
|
16415
|
-
import { Box as Box16, Text as Text18, useStdout, useInput as useInput4 } from "ink";
|
|
16532
|
+
import { Box as Box16, Text as Text18, useStdout as useStdout3, useInput as useInput4 } from "ink";
|
|
16416
16533
|
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
16417
16534
|
var MODAL_TITLES = {
|
|
16418
16535
|
findings: "\u25C8 FINDINGS \u25C8",
|
|
@@ -16430,7 +16547,7 @@ var Modal = memo12(({
|
|
|
16430
16547
|
onScrollRef.current = onScroll;
|
|
16431
16548
|
const onCloseRef = useRef9(onClose);
|
|
16432
16549
|
onCloseRef.current = onClose;
|
|
16433
|
-
const { stdout } =
|
|
16550
|
+
const { stdout } = useStdout3();
|
|
16434
16551
|
const terminalHeight = stdout?.rows ?? 24;
|
|
16435
16552
|
const terminalWidth = (stdout?.columns ?? 80) - 4;
|
|
16436
16553
|
const maxHeight = Math.max(1, terminalHeight - 6);
|
|
@@ -16464,13 +16581,11 @@ var Modal = memo12(({
|
|
|
16464
16581
|
width: terminalWidth,
|
|
16465
16582
|
height: terminalHeight,
|
|
16466
16583
|
children: [
|
|
16467
|
-
/* @__PURE__ */ jsx18(Box16, { justifyContent: "center", marginBottom: 0, children: /* @__PURE__ */
|
|
16468
|
-
|
|
16469
|
-
|
|
16470
|
-
|
|
16471
|
-
|
|
16472
|
-
"\u2500".repeat(10)
|
|
16473
|
-
] }) }),
|
|
16584
|
+
/* @__PURE__ */ jsx18(Box16, { justifyContent: "center", marginBottom: 0, children: /* @__PURE__ */ jsx18(Text18, { color: THEME.cyan, bold: true, children: (() => {
|
|
16585
|
+
const title = MODAL_TITLES[type];
|
|
16586
|
+
const sideWidth = Math.max(3, Math.floor((terminalWidth - title.length - 2) / 2));
|
|
16587
|
+
return `${"\u2500".repeat(sideWidth)} ${title} ${"\u2500".repeat(sideWidth)}`;
|
|
16588
|
+
})() }) }),
|
|
16474
16589
|
/* @__PURE__ */ jsx18(
|
|
16475
16590
|
Box16,
|
|
16476
16591
|
{
|
|
@@ -16575,7 +16690,7 @@ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
|
16575
16690
|
var MODEL_NAME = getModel() || DEFAULT_MODEL;
|
|
16576
16691
|
var App = ({ autoApprove = false, target }) => {
|
|
16577
16692
|
const { exit } = useApp();
|
|
16578
|
-
const { stdout } =
|
|
16693
|
+
const { stdout } = useStdout4();
|
|
16579
16694
|
const terminalWidth = stdout?.columns ?? 80;
|
|
16580
16695
|
const [input, setInput] = useState8("");
|
|
16581
16696
|
const [secretInput, setSecretInput] = useState8("");
|