pentesting 0.73.11 → 0.73.13

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.
@@ -5,7 +5,7 @@ import {
5
5
  createContextExtractor,
6
6
  getLLMClient,
7
7
  getShellSupervisorLifecycleSnapshot
8
- } from "./chunk-WEEPTBTF.js";
8
+ } from "./chunk-GILD75OT.js";
9
9
  import {
10
10
  AGENT_ROLES,
11
11
  EVENT_TYPES,
@@ -13,7 +13,7 @@ import {
13
13
  TOOL_NAMES,
14
14
  getProcessOutput,
15
15
  listBackgroundProcesses
16
- } from "./chunk-U2NIVQ2O.js";
16
+ } from "./chunk-4UNNRHYY.js";
17
17
  import {
18
18
  DETECTION_PATTERNS,
19
19
  PROCESS_EVENTS,
@@ -348,7 +348,7 @@ var INPUT_PROMPT_PATTERNS = [
348
348
  ];
349
349
 
350
350
  // src/shared/constants/agent.ts
351
- var APP_VERSION = "0.73.11";
351
+ var APP_VERSION = "0.73.13";
352
352
  var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
353
353
  var LLM_ROLES = {
354
354
  SYSTEM: "system",
@@ -2323,6 +2323,93 @@ function setupTimeout(child, timeoutMs, onTimeout) {
2323
2323
  }
2324
2324
  }, timeoutMs);
2325
2325
  }
2326
+ function emitCommandStart(safeCommand, eventEmitter) {
2327
+ const preview = safeCommand.slice(0, DISPLAY_LIMITS.COMMAND_PREVIEW);
2328
+ const suffix = safeCommand.length > DISPLAY_LIMITS.COMMAND_PREVIEW ? "..." : "";
2329
+ eventEmitter?.({
2330
+ type: COMMAND_EVENT_TYPES.COMMAND_START,
2331
+ message: `Executing: ${preview}${suffix}`
2332
+ });
2333
+ }
2334
+ function createChildProcess(execCommand, options) {
2335
+ return spawn3("sh", ["-c", execCommand], {
2336
+ detached: true,
2337
+ env: { ...process.env, ...options.env },
2338
+ cwd: options.cwd
2339
+ });
2340
+ }
2341
+ function createExecutionState() {
2342
+ return { terminated: false, timedOut: false };
2343
+ }
2344
+ function createTimeoutError(timeoutMs, ioHandler) {
2345
+ const timeoutSeconds = Math.round(timeoutMs / 1e3);
2346
+ const outputTail = (ioHandler.stdout + ioHandler.stderr).trim().slice(-500);
2347
+ return `Command timed out after ${timeoutSeconds}s. Output so far:
2348
+ ${outputTail}`;
2349
+ }
2350
+ function resolveTimeout(timeoutMs, ioHandler, eventEmitter, resolve) {
2351
+ const timeoutSeconds = Math.round(timeoutMs / 1e3);
2352
+ eventEmitter?.({
2353
+ type: COMMAND_EVENT_TYPES.COMMAND_FAILED,
2354
+ message: `Command timed out after ${timeoutSeconds}s`
2355
+ });
2356
+ resolve({
2357
+ success: false,
2358
+ output: ioHandler.stdout.trim(),
2359
+ error: createTimeoutError(timeoutMs, ioHandler)
2360
+ });
2361
+ }
2362
+ function resolveSuccess(ioHandler, eventEmitter, resolve) {
2363
+ const stdout = ioHandler.stdout.trim();
2364
+ const stderr = ioHandler.stderr.trim();
2365
+ eventEmitter?.({
2366
+ type: COMMAND_EVENT_TYPES.COMMAND_SUCCESS,
2367
+ message: "Command completed"
2368
+ });
2369
+ resolve({ success: true, output: stdout || stderr });
2370
+ }
2371
+ function resolveFailure(code, ioHandler, eventEmitter, resolve) {
2372
+ const stdout = ioHandler.stdout.trim();
2373
+ const stderr = ioHandler.stderr.trim();
2374
+ eventEmitter?.({
2375
+ type: COMMAND_EVENT_TYPES.COMMAND_FAILED,
2376
+ message: `Command failed (exit ${code})`,
2377
+ detail: stderr.slice(0, SYSTEM_LIMITS.MAX_INPUT_SLICE)
2378
+ });
2379
+ resolve({
2380
+ success: false,
2381
+ output: stdout,
2382
+ error: stderr || `Process exited with code ${code}`
2383
+ });
2384
+ }
2385
+ function attachProcessStreams(child, ioHandler) {
2386
+ child.stdout?.on("data", (data) => ioHandler.handleStdout(data));
2387
+ child.stderr?.on("data", (data) => ioHandler.handleStderr(data));
2388
+ }
2389
+ function attachProcessLifecycleHandlers(child, ioHandler, processState, killTimer, timeoutMs, eventEmitter, resolve) {
2390
+ child.on("close", (code) => {
2391
+ clearTimeout(killTimer);
2392
+ processState.terminated = true;
2393
+ if (processState.timedOut) {
2394
+ resolveTimeout(timeoutMs, ioHandler, eventEmitter, resolve);
2395
+ return;
2396
+ }
2397
+ if (code === 0) {
2398
+ resolveSuccess(ioHandler, eventEmitter, resolve);
2399
+ return;
2400
+ }
2401
+ resolveFailure(code, ioHandler, eventEmitter, resolve);
2402
+ });
2403
+ child.on("error", (err) => {
2404
+ clearTimeout(killTimer);
2405
+ processState.terminated = true;
2406
+ eventEmitter?.({
2407
+ type: COMMAND_EVENT_TYPES.COMMAND_ERROR,
2408
+ message: `Command error: ${err.message}`
2409
+ });
2410
+ resolve({ success: false, output: "", error: err.message || String(err) });
2411
+ });
2412
+ }
2326
2413
  async function executeCommandOnce(command, options = {}) {
2327
2414
  return new Promise((resolve) => {
2328
2415
  const eventEmitter = getEventEmitter();
@@ -2330,16 +2417,9 @@ async function executeCommandOnce(command, options = {}) {
2330
2417
  if (error) {
2331
2418
  return resolve({ success: false, output: "", error });
2332
2419
  }
2333
- eventEmitter?.({
2334
- type: COMMAND_EVENT_TYPES.COMMAND_START,
2335
- message: `Executing: ${safeCommand.slice(0, DISPLAY_LIMITS.COMMAND_PREVIEW)}${safeCommand.length > DISPLAY_LIMITS.COMMAND_PREVIEW ? "..." : ""}`
2336
- });
2337
- const child = spawn3("sh", ["-c", execCommand], {
2338
- detached: true,
2339
- env: { ...process.env, ...options.env },
2340
- cwd: options.cwd
2341
- });
2342
- const processState = { terminated: false, timedOut: false };
2420
+ emitCommandStart(safeCommand, eventEmitter);
2421
+ const child = createChildProcess(execCommand, options);
2422
+ const processState = createExecutionState();
2343
2423
  const timeoutMs = options.timeout ?? TOOL_TIMEOUTS.DEFAULT_COMMAND;
2344
2424
  const killTimer = setupTimeout(child, timeoutMs, () => {
2345
2425
  processState.timedOut = true;
@@ -2351,42 +2431,16 @@ async function executeCommandOnce(command, options = {}) {
2351
2431
  eventEmitter,
2352
2432
  inputHandler: getInputHandler()
2353
2433
  });
2354
- child.stdout.on("data", (d) => ioHandler.handleStdout(d));
2355
- child.stderr.on("data", (d) => ioHandler.handleStderr(d));
2356
- child.on("close", (code) => {
2357
- clearTimeout(killTimer);
2358
- processState.terminated = true;
2359
- const outTrimmed = ioHandler.stdout.trim();
2360
- const errTrimmed = ioHandler.stderr.trim();
2361
- if (processState.timedOut) {
2362
- eventEmitter?.({
2363
- type: COMMAND_EVENT_TYPES.COMMAND_FAILED,
2364
- message: `Command timed out after ${Math.round(timeoutMs / 1e3)}s`
2365
- });
2366
- return resolve({
2367
- success: false,
2368
- output: outTrimmed,
2369
- error: `Command timed out after ${Math.round(timeoutMs / 1e3)}s. Output so far:
2370
- ${(ioHandler.stdout + ioHandler.stderr).trim().slice(-500)}`
2371
- });
2372
- }
2373
- if (code === 0) {
2374
- eventEmitter?.({ type: COMMAND_EVENT_TYPES.COMMAND_SUCCESS, message: `Command completed` });
2375
- return resolve({ success: true, output: outTrimmed || errTrimmed });
2376
- }
2377
- eventEmitter?.({
2378
- type: COMMAND_EVENT_TYPES.COMMAND_FAILED,
2379
- message: `Command failed (exit ${code})`,
2380
- detail: errTrimmed.slice(0, SYSTEM_LIMITS.MAX_INPUT_SLICE)
2381
- });
2382
- return resolve({ success: false, output: outTrimmed, error: errTrimmed || `Process exited with code ${code}` });
2383
- });
2384
- child.on("error", (err) => {
2385
- clearTimeout(killTimer);
2386
- processState.terminated = true;
2387
- eventEmitter?.({ type: COMMAND_EVENT_TYPES.COMMAND_ERROR, message: `Command error: ${err.message}` });
2388
- resolve({ success: false, output: "", error: err.message || String(err) });
2389
- });
2434
+ attachProcessStreams(child, ioHandler);
2435
+ attachProcessLifecycleHandlers(
2436
+ child,
2437
+ ioHandler,
2438
+ processState,
2439
+ killTimer,
2440
+ timeoutMs,
2441
+ eventEmitter,
2442
+ resolve
2443
+ );
2390
2444
  });
2391
2445
  }
2392
2446
 
@@ -69,7 +69,7 @@ import {
69
69
  startBackgroundProcess,
70
70
  stopBackgroundProcess,
71
71
  writeFileContent
72
- } from "./chunk-U2NIVQ2O.js";
72
+ } from "./chunk-4UNNRHYY.js";
73
73
  import {
74
74
  DETECTION_PATTERNS,
75
75
  HEALTH_CONFIG,
@@ -11084,7 +11084,7 @@ After completion: record key loot/findings from the sub-agent output to canonica
11084
11084
  rootTaskId: activeExecution.rootTaskId
11085
11085
  }
11086
11086
  });
11087
- const { AgentTool } = await import("./agent-tool-WLGPVDX6.js");
11087
+ const { AgentTool } = await import("./agent-tool-KHXXTHGS.js");
11088
11088
  const executor = new AgentTool(state, events, scopeGuard, approvalGate);
11089
11089
  try {
11090
11090
  const result = await executor.execute(input);
package/dist/main.js CHANGED
@@ -39,7 +39,7 @@ import {
39
39
  rotateTurnRecords,
40
40
  setCurrentTurn,
41
41
  writePolicyDocument
42
- } from "./chunk-WEEPTBTF.js";
42
+ } from "./chunk-GILD75OT.js";
43
43
  import {
44
44
  AGENT_ROLES,
45
45
  APP_DESCRIPTION,
@@ -88,7 +88,7 @@ import {
88
88
  setActiveSessionRuntime,
89
89
  setTorEnabled,
90
90
  snapshotToPrompt
91
- } from "./chunk-U2NIVQ2O.js";
91
+ } from "./chunk-4UNNRHYY.js";
92
92
  import {
93
93
  EXIT_CODES,
94
94
  getOptionalRuntimeSection,
@@ -2497,6 +2497,17 @@ var MainAgentInteractionCoordinator = class {
2497
2497
  emitMainAgentQueueUpdated(this.options.events, this.userInputQueue);
2498
2498
  return normalized;
2499
2499
  }
2500
+ async processStandalonePolicyInput(rawInput) {
2501
+ const result = await this.options.inputProcessor.execute({
2502
+ rawInput,
2503
+ existingPolicy: readPolicyDocument(),
2504
+ hasActiveEngagement: this.options.state.hasActiveEngagement(),
2505
+ currentObjective: this.options.state.currentObjective || ""
2506
+ });
2507
+ const normalized = normalizeInputProcessorResult(result, rawInput);
2508
+ this.updatePolicyFromInputProcessor(normalized);
2509
+ return normalized;
2510
+ }
2500
2511
  getUserInputQueue() {
2501
2512
  return this.userInputQueue;
2502
2513
  }
@@ -3274,7 +3285,7 @@ var makeRotateTurns = (_llm, _opts) => async (_ctx) => {
3274
3285
  };
3275
3286
  var makeSaveSession = (_llm, _opts) => async (ctx) => {
3276
3287
  try {
3277
- const { saveState: saveState2 } = await import("./persistence-WP43KX7N.js");
3288
+ const { saveState: saveState2 } = await import("./persistence-U2N3KWFH.js");
3278
3289
  saveState2(ctx.state);
3279
3290
  } catch {
3280
3291
  }
@@ -4144,6 +4155,9 @@ var MainAgent = class extends CoreAgent {
4144
4155
  }
4145
4156
  return result;
4146
4157
  }
4158
+ async applyStandalonePolicyInput(rawInput) {
4159
+ return this.interactionCoordinator.processStandalonePolicyInput(rawInput);
4160
+ }
4147
4161
  async buildDynamicPrompt(memory) {
4148
4162
  return this.promptState.buildDynamicPrompt(memory);
4149
4163
  }
@@ -4259,11 +4273,11 @@ async function writeJsonReport(outputPath, result) {
4259
4273
  }
4260
4274
 
4261
4275
  // src/platform/tui/cli/interactive-runtime.tsx
4262
- import React17 from "react";
4276
+ import React18 from "react";
4263
4277
  import { render } from "ink";
4264
4278
 
4265
4279
  // src/platform/tui/app.tsx
4266
- import { Box as Box19 } from "ink";
4280
+ import { Box as Box20 } from "ink";
4267
4281
 
4268
4282
  // src/platform/tui/hooks/useAgent.ts
4269
4283
  import { useState as useState6, useEffect as useEffect2, useCallback as useCallback7, useRef as useRef7 } from "react";
@@ -4828,6 +4842,12 @@ var UI_STATUS_MESSAGES = {
4828
4842
  STARTING_PENTEST: "Starting penetration test...",
4829
4843
  /** Start cancelled from policy composer */
4830
4844
  START_CANCELLED: "Start cancelled before execution.",
4845
+ /** Policy bootstrap was saved before autonomous execution */
4846
+ POLICY_BOOTSTRAP_SAVED: "Competition policy saved for this run.",
4847
+ /** Policy bootstrap did not produce a durable update */
4848
+ POLICY_BOOTSTRAP_NO_CHANGE: "Competition policy was reviewed, but no durable policy change was recorded.",
4849
+ /** No extra bootstrap policy was provided */
4850
+ POLICY_BOOTSTRAP_SKIPPED: "No additional policy provided. Starting with existing policy memory.",
4831
4851
  /** Pentest task prefix */
4832
4852
  PENTEST_TASK_PREFIX: "Perform comprehensive penetration testing",
4833
4853
  /** Against prefix */
@@ -6733,8 +6753,21 @@ var POLICY_COMPOSER_GUIDE = [
6733
6753
  "Before autonomous execution, add any competition rules or durable engagement constraints here.",
6734
6754
  "Use /policy to view the current policy memory at any time.",
6735
6755
  "You can also tell the agent to remember a rule or put something into policy memory in normal chat, and it will merge it automatically.",
6756
+ "Use Ctrl+J to insert a newline inside this policy editor.",
6736
6757
  "Tip: paste a compact summary of the most important rules if the source text is long."
6737
6758
  ].join("\n");
6759
+ var POLICY_COMPOSER_TITLE = "\u25C8 COMPETITION POLICY \u25C8";
6760
+ var POLICY_COMPOSER_FOOTER_BREAKPOINT = 72;
6761
+ function formatPolicyComposerTitle(terminalWidth) {
6762
+ if (terminalWidth <= POLICY_COMPOSER_TITLE.length + 2) {
6763
+ return POLICY_COMPOSER_TITLE;
6764
+ }
6765
+ const sideWidth = Math.floor((terminalWidth - POLICY_COMPOSER_TITLE.length - 2) / 2);
6766
+ return `${"\u2500".repeat(sideWidth)} ${POLICY_COMPOSER_TITLE} ${"\u2500".repeat(sideWidth)}`;
6767
+ }
6768
+ function shouldStackPolicyComposerFooter(terminalWidth) {
6769
+ return terminalWidth < POLICY_COMPOSER_FOOTER_BREAKPOINT;
6770
+ }
6738
6771
  function buildPolicyBootstrapInput(rawPolicy) {
6739
6772
  const trimmed = rawPolicy.trim();
6740
6773
  if (!trimmed) return "";
@@ -6825,7 +6858,13 @@ var useAppLogic = ({ autoApprove = false, target }) => {
6825
6858
  const policyInput = buildPolicyBootstrapInput(policyComposer.value);
6826
6859
  setPolicyComposer({ isOpen: false, value: "", pendingTask: "" });
6827
6860
  if (policyInput) {
6828
- agent.enqueueUserInput(policyInput);
6861
+ const policyResult = await agent.applyStandalonePolicyInput(policyInput);
6862
+ addMessage(
6863
+ "system",
6864
+ policyResult.shouldWritePolicy ? policyResult.policyUpdateSummary || UI_STATUS_MESSAGES.POLICY_BOOTSTRAP_SAVED : UI_STATUS_MESSAGES.POLICY_BOOTSTRAP_NO_CHANGE
6865
+ );
6866
+ } else {
6867
+ addMessage("system", UI_STATUS_MESSAGES.POLICY_BOOTSTRAP_SKIPPED);
6829
6868
  }
6830
6869
  setAutoApproveMode(true);
6831
6870
  agent.setToolAutoApprove(true);
@@ -7358,7 +7397,30 @@ function computeResultDisplay(content) {
7358
7397
  return { firstLine, visibleRest, hasMore, hiddenCount, summary };
7359
7398
  }
7360
7399
 
7400
+ // src/platform/tui/components/messages/markdown-detection.ts
7401
+ var MARKDOWN_PATTERNS = [
7402
+ /^#{1,3}\s/m,
7403
+ /^[-*]\s/m,
7404
+ /^\d+\.\s/m,
7405
+ /```/,
7406
+ /`[^`]+`/,
7407
+ /(\*\*|__)[^*_]+(\*\*|__)/
7408
+ ];
7409
+ function shouldUseMarkdownRenderer(content) {
7410
+ const trimmed = content.trim();
7411
+ if (!trimmed) return false;
7412
+ return MARKDOWN_PATTERNS.some((pattern) => pattern.test(trimmed));
7413
+ }
7414
+
7361
7415
  // src/platform/tui/utils/chrome.ts
7416
+ function normalizePlaceholderText(text) {
7417
+ return text.replace(/\s+/g, " ").trim();
7418
+ }
7419
+ function resolveActiveInputPlaceholder(inputRequest) {
7420
+ const candidate = inputRequest.placeholder || inputRequest.prompt;
7421
+ const normalized = normalizePlaceholderText(candidate);
7422
+ return normalized || "Answer the active prompt";
7423
+ }
7362
7424
  function buildLeftAlignedLabelBorder({
7363
7425
  icon,
7364
7426
  label,
@@ -7377,6 +7439,18 @@ function resolveInputSeparatorColor({
7377
7439
  if (isProcessing) return THEME.dimGray;
7378
7440
  return THEME.primary;
7379
7441
  }
7442
+ function resolveInputPlaceholder({
7443
+ isProcessing,
7444
+ inputRequest
7445
+ }) {
7446
+ if (inputRequest.status === "active") {
7447
+ return resolveActiveInputPlaceholder(inputRequest);
7448
+ }
7449
+ if (isProcessing) {
7450
+ return "Send a note for the next turn, or type /help";
7451
+ }
7452
+ return "Describe the target or type /help";
7453
+ }
7380
7454
 
7381
7455
  // src/platform/tui/components/messages/MessageRow.tsx
7382
7456
  import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -7463,7 +7537,8 @@ var MessageRow = memo4(({ msg }) => {
7463
7537
  ] }), 0);
7464
7538
  }
7465
7539
  if (msg.type === "ai" || msg.type === "assistant") {
7466
- return renderBox("\u2022", "ai", THEME.messages.ai, /* @__PURE__ */ jsx6(MarkdownText, { content: msg.content }), 0);
7540
+ const useMarkdown = shouldUseMarkdownRenderer(msg.content);
7541
+ return renderBox("\u2022", "ai", THEME.messages.ai, useMarkdown ? /* @__PURE__ */ jsx6(MarkdownText, { content: msg.content }) : /* @__PURE__ */ jsx6(Text5, { color: THEME.white, wrap: "wrap", children: msg.content }), 0);
7467
7542
  }
7468
7543
  if (msg.type === "error") {
7469
7544
  const lines = msg.content.split("\n");
@@ -7585,11 +7660,11 @@ import { memo as memo7 } from "react";
7585
7660
  import { Text as Text7 } from "ink";
7586
7661
 
7587
7662
  // src/platform/tui/utils/animation-style.ts
7588
- var PRIMARY_BLUE = "#2496ED";
7589
7663
  var BLINKING_CIRCLE_PHASE_LENGTH = 8;
7590
7664
  var BLINKING_CIRCLE_SOLID_PHASE = 4;
7591
7665
  var SHIMMER_COLOR_STEPS = 64;
7592
7666
  var READY_SHIMMER_COLOR_COUNT = 12;
7667
+ var READY_SHIMMER_SWEEP_SPEED = 1.15;
7593
7668
  function getBlinkingCircleFrame(tick, activeColor = THEME.primary) {
7594
7669
  const phase = tick % BLINKING_CIRCLE_PHASE_LENGTH;
7595
7670
  const isSolid = phase < BLINKING_CIRCLE_SOLID_PHASE;
@@ -7625,18 +7700,6 @@ function buildNeutralShimmerPalette() {
7625
7700
  ]);
7626
7701
  });
7627
7702
  }
7628
- function buildAccentShimmerPalette() {
7629
- const start = hexToRgb(PRIMARY_BLUE);
7630
- const peak = hexToRgb(THEME.white);
7631
- return Array.from({ length: SHIMMER_COLOR_STEPS }, (_, i) => {
7632
- const t = i / (SHIMMER_COLOR_STEPS - 1);
7633
- return rgbToHex([
7634
- lerp(start[0], peak[0], t),
7635
- lerp(start[1], peak[1], t),
7636
- lerp(start[2], peak[2], t)
7637
- ]);
7638
- });
7639
- }
7640
7703
  var READY_SHIMMER_BASE_COLORS = [
7641
7704
  "#2496ED",
7642
7705
  "#38BDF8",
@@ -7697,11 +7760,9 @@ import { memo as memo8, useMemo as useMemo2 } from "react";
7697
7760
  import { Text as Text9 } from "ink";
7698
7761
  import { jsx as jsx11 } from "react/jsx-runtime";
7699
7762
  var SPOT_WIDTH = 6;
7700
- var SWEEP_SPEED = 1.5;
7701
7763
  var LOOP_PAD = SPOT_WIDTH * 2;
7702
7764
  var TICK_WRAP = 1e6;
7703
7765
  var NEUTRAL_PALETTE = buildNeutralShimmerPalette();
7704
- var ACCENT_PALETTE = buildAccentShimmerPalette();
7705
7766
  var READY_PALETTES = buildReadyShimmerPalettes();
7706
7767
  function gaussian(x, sigma) {
7707
7768
  return Math.exp(-(x * x) / (2 * sigma * sigma));
@@ -7714,10 +7775,11 @@ var ShimmerText = memo8(({
7714
7775
  }) => {
7715
7776
  const tick = useAnimationTick() % TICK_WRAP;
7716
7777
  const len = children.length;
7717
- const palette = variant === "accent" ? ACCENT_PALETTE : variant === "ready" ? READY_PALETTES[tick % READY_SHIMMER_COLOR_COUNT] : NEUTRAL_PALETTE;
7778
+ const palette = variant === "ready" ? READY_PALETTES[tick % READY_SHIMMER_COLOR_COUNT] : NEUTRAL_PALETTE;
7718
7779
  const chars = useMemo2(() => Array.from(children), [children]);
7780
+ const sweepSpeed = READY_SHIMMER_SWEEP_SPEED;
7719
7781
  const loopLen = len + LOOP_PAD;
7720
- const rawPos = (tick * SWEEP_SPEED + phase * loopLen) % loopLen;
7782
+ const rawPos = (tick * sweepSpeed + phase * loopLen) % loopLen;
7721
7783
  const spotPos = rawPos - SPOT_WIDTH;
7722
7784
  const sigma = SPOT_WIDTH / 2.5;
7723
7785
  return /* @__PURE__ */ jsx11(Text9, { bold, children: chars.map((char, i) => {
@@ -7743,6 +7805,20 @@ function fmtElapsed(secs) {
7743
7805
  const s = secs % 60;
7744
7806
  return `${h}h ${String(m).padStart(2, "0")}m ${String(s).padStart(2, "0")}s`;
7745
7807
  }
7808
+ var STATUS_META_STACK_BREAKPOINT = 76;
7809
+ function shouldStackProcessingMeta(columns) {
7810
+ return columns < STATUS_META_STACK_BREAKPOINT;
7811
+ }
7812
+ function buildProcessingMetaSuffix(isActive, elapsedSeconds, totalTokens, compact) {
7813
+ const elapsedStr = elapsedSeconds > 0 ? fmtElapsed(elapsedSeconds) : "0s";
7814
+ if (compact) {
7815
+ const compactPrefix = isActive ? "esc" : "done";
7816
+ const compactTokens = totalTokens > 0 ? ` \xB7 \u2191 ${formatTokens(totalTokens)}` : "";
7817
+ return `${compactPrefix} \xB7 ${elapsedStr}${compactTokens}`;
7818
+ }
7819
+ const tokenStr = totalTokens > 0 ? `\u2191 ${formatTokens(totalTokens)}` : "";
7820
+ return isActive ? `esc to interrupt \xB7 ${elapsedStr}${tokenStr ? ` \xB7 ${tokenStr}` : ""}` : `done \xB7 ${elapsedStr}${tokenStr ? ` \xB7 ${tokenStr}` : ""}`;
7821
+ }
7746
7822
  var ProcessingView = ({
7747
7823
  statusMain,
7748
7824
  detailText,
@@ -7751,25 +7827,30 @@ var ProcessingView = ({
7751
7827
  liveProgress,
7752
7828
  isActive = true
7753
7829
  }) => {
7830
+ const { columns } = useTerminalSize();
7754
7831
  const safe = liveProgress ?? DEFAULT_LIVE_PROGRESS;
7832
+ const compactMeta = shouldStackProcessingMeta(columns);
7755
7833
  const stage = safe.stage || statusMain;
7756
- const elapsedStr = statusElapsed > 0 ? fmtElapsed(statusElapsed) : "0s";
7757
- const tokenStr = totalTokens > 0 ? `\u2191 ${formatTokens(totalTokens)}` : "";
7758
- const metaSuffix = isActive ? `esc to interrupt \xB7 ${elapsedStr}${tokenStr ? ` \xB7 ${tokenStr}` : ""}` : `done \xB7 ${elapsedStr}${tokenStr ? ` \xB7 ${tokenStr}` : ""}`;
7834
+ const metaSuffix = buildProcessingMetaSuffix(isActive, statusElapsed, totalTokens, compactMeta);
7759
7835
  const detailContent = safe.activeTool ? `tool: ${safe.activeTool}` : safe.reasoningPreview ? `thought: ${truncate(safe.reasoningPreview, 80)}` : safe.responsePreview ? `output: ${truncate(safe.responsePreview, 80)}` : safe.detail || detailText || "";
7760
- const stageText = truncate(stage, 72);
7761
- return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", children: [
7762
- /* @__PURE__ */ jsxs7(Box9, { children: [
7836
+ const stageWidth = compactMeta ? Math.max(12, columns - 6) : Math.max(12, columns - Math.min(metaSuffix.length + 8, 32) - 6);
7837
+ const stageText = truncate(stage, Math.min(72, stageWidth));
7838
+ return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", width: "100%", children: [
7839
+ /* @__PURE__ */ jsxs7(Box9, { width: "100%", children: [
7763
7840
  /* @__PURE__ */ jsx12(Box9, { width: 2, flexShrink: 0, children: /* @__PURE__ */ jsx12(BlinkingCircle, { color: THEME.primary }) }),
7764
- /* @__PURE__ */ jsx12(ShimmerText, { bold: true, variant: isActive ? "accent" : "ready", children: stageText }),
7765
- /* @__PURE__ */ jsxs7(Text10, { color: THEME.dimGray, wrap: "truncate", children: [
7841
+ /* @__PURE__ */ jsx12(Box9, { flexGrow: 1, minWidth: 0, children: isActive ? /* @__PURE__ */ jsx12(Text10, { color: THEME.primary, bold: true, wrap: "truncate-end", children: stageText }) : /* @__PURE__ */ jsx12(ShimmerText, { bold: true, variant: "ready", children: stageText }) }),
7842
+ !compactMeta && /* @__PURE__ */ jsx12(Box9, { flexShrink: 0, children: /* @__PURE__ */ jsxs7(Text10, { color: THEME.dimGray, wrap: "truncate", children: [
7766
7843
  " ",
7767
7844
  metaSuffix
7768
- ] })
7845
+ ] }) })
7769
7846
  ] }),
7770
- detailContent.length > 0 && /* @__PURE__ */ jsxs7(Box9, { children: [
7847
+ compactMeta && /* @__PURE__ */ jsxs7(Box9, { width: "100%", children: [
7771
7848
  /* @__PURE__ */ jsx12(Box9, { width: 2, flexShrink: 0 }),
7772
- /* @__PURE__ */ jsx12(Text10, { color: THEME.dimGray, wrap: "truncate", children: truncate(detailContent, TUI_DISPLAY_LIMITS.DETAIL_TEXT_WIDTH) })
7849
+ /* @__PURE__ */ jsx12(Text10, { color: THEME.dimGray, wrap: "truncate-end", children: metaSuffix })
7850
+ ] }),
7851
+ detailContent.length > 0 && /* @__PURE__ */ jsxs7(Box9, { width: "100%", children: [
7852
+ /* @__PURE__ */ jsx12(Box9, { width: 2, flexShrink: 0 }),
7853
+ /* @__PURE__ */ jsx12(Text10, { color: THEME.dimGray, wrap: "truncate-end", children: truncate(detailContent, TUI_DISPLAY_LIMITS.DETAIL_TEXT_WIDTH) })
7773
7854
  ] })
7774
7855
  ] });
7775
7856
  };
@@ -7784,6 +7865,10 @@ function parseStatusLines(status) {
7784
7865
  detail: isThinking && lines.length > 1 ? lines[lines.length - 1].slice(0, 120) : ""
7785
7866
  };
7786
7867
  }
7868
+ function shouldShowActiveStatus(isProcessing, liveProgress) {
7869
+ if (isProcessing) return true;
7870
+ return liveProgress.mode === "tool" || liveProgress.activeTool.length > 0;
7871
+ }
7787
7872
  var StatusDisplay = memo9(({
7788
7873
  retryState,
7789
7874
  isProcessing,
@@ -7794,7 +7879,8 @@ var StatusDisplay = memo9(({
7794
7879
  }) => {
7795
7880
  const safe = liveProgress ?? DEFAULT_LIVE_PROGRESS;
7796
7881
  const isWaitingForInput = inputRequest?.status === "active";
7797
- const statusElapsed = useStatusTimer(currentStatus, isProcessing && !isWaitingForInput);
7882
+ const showActiveStatus = shouldShowActiveStatus(isProcessing, safe);
7883
+ const statusElapsed = useStatusTimer(currentStatus, showActiveStatus && !isWaitingForInput);
7798
7884
  if (retryState?.status === "retrying") {
7799
7885
  return /* @__PURE__ */ jsx13(RetryView, { retryState });
7800
7886
  }
@@ -7827,7 +7913,7 @@ var StatusDisplay = memo9(({
7827
7913
  statusElapsed,
7828
7914
  totalTokens,
7829
7915
  liveProgress: safe,
7830
- isActive: false
7916
+ isActive: showActiveStatus
7831
7917
  }
7832
7918
  );
7833
7919
  }
@@ -7835,8 +7921,8 @@ var StatusDisplay = memo9(({
7835
7921
  });
7836
7922
 
7837
7923
  // src/platform/tui/components/ChatInput.tsx
7838
- import { useMemo as useMemo4, useCallback as useCallback14, useRef as useRef12, memo as memo10, useState as useState12 } from "react";
7839
- import { Box as Box14, Text as Text15 } from "ink";
7924
+ import { useMemo as useMemo5, useCallback as useCallback14, useRef as useRef13, memo as memo10, useState as useState12 } from "react";
7925
+ import { Box as Box15, Text as Text16 } from "ink";
7840
7926
 
7841
7927
  // src/platform/tui/components/input/AutocompletePreview.tsx
7842
7928
  import { Box as Box10, Text as Text11 } from "ink";
@@ -7903,6 +7989,7 @@ var SimpleTextInput = ({
7903
7989
  onSubmit,
7904
7990
  placeholder,
7905
7991
  isPassword,
7992
+ placeholderColor = THEME.dimGray,
7906
7993
  onSpecialKey
7907
7994
  }) => {
7908
7995
  const chars = useMemo3(() => Array.from(value || ""), [value]);
@@ -7992,7 +8079,7 @@ var SimpleTextInput = ({
7992
8079
  if (displayChars.length === 0) {
7993
8080
  return /* @__PURE__ */ jsxs9(Box11, { width: "100%", children: [
7994
8081
  /* @__PURE__ */ jsx15(Text12, { inverse: true, children: " " }),
7995
- placeholder ? /* @__PURE__ */ jsx15(Box11, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx15(Text12, { color: THEME.dimGray, wrap: "truncate-end", children: placeholder }) }) : null
8082
+ placeholder ? /* @__PURE__ */ jsx15(Box11, { flexGrow: 1, flexShrink: 1, minWidth: 0, children: /* @__PURE__ */ jsx15(Text12, { color: placeholderColor, wrap: "truncate-end", children: placeholder }) }) : null
7996
8083
  ] });
7997
8084
  }
7998
8085
  const c = Math.min(cursorRef.current, displayChars.length);
@@ -8015,6 +8102,7 @@ var SecretInputArea = ({
8015
8102
  setSecretInput,
8016
8103
  onSecretSubmit
8017
8104
  }) => {
8105
+ const placeholder = resolveActiveInputPlaceholder(inputRequest);
8018
8106
  return /* @__PURE__ */ jsxs10(
8019
8107
  Box12,
8020
8108
  {
@@ -8034,7 +8122,8 @@ var SecretInputArea = ({
8034
8122
  value: secretInput,
8035
8123
  onChange: setSecretInput,
8036
8124
  onSubmit: onSecretSubmit,
8037
- placeholder: inputRequest.isPassword ? "hidden input" : "type answer",
8125
+ placeholder,
8126
+ placeholderColor: THEME.primary,
8038
8127
  isPassword: inputRequest.isPassword
8039
8128
  }
8040
8129
  ) })
@@ -8074,6 +8163,7 @@ var NormalInputArea = ({
8074
8163
  onChange,
8075
8164
  onSubmit,
8076
8165
  placeholder: placeholder ?? "Describe the target or type /help",
8166
+ placeholderColor: THEME.primary,
8077
8167
  onSpecialKey
8078
8168
  },
8079
8169
  inputKey
@@ -8084,8 +8174,78 @@ var NormalInputArea = ({
8084
8174
  );
8085
8175
  };
8086
8176
 
8087
- // src/platform/tui/components/ChatInput.tsx
8177
+ // src/platform/tui/components/input/PolicyTextArea.tsx
8178
+ import { useEffect as useEffect9, useMemo as useMemo4, useRef as useRef12 } from "react";
8179
+ import { Box as Box14, Text as Text15, useInput as useInput3, useStdout as useStdout3 } from "ink";
8088
8180
  import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
8181
+ function applyPolicyInputEdit(currentValue, input, key) {
8182
+ if (key.escape) return { kind: "ignore" };
8183
+ if (key.ctrl && (input === "j" || input === "J")) {
8184
+ return { kind: "change", value: `${currentValue}
8185
+ ` };
8186
+ }
8187
+ if (key.return) {
8188
+ return { kind: "submit" };
8189
+ }
8190
+ if (key.backspace || key.delete) {
8191
+ if (currentValue.length === 0) return { kind: "ignore" };
8192
+ return { kind: "change", value: currentValue.slice(0, -1) };
8193
+ }
8194
+ if (!input || key.ctrl || key.meta) {
8195
+ return { kind: "ignore" };
8196
+ }
8197
+ return { kind: "change", value: `${currentValue}${input}` };
8198
+ }
8199
+ var PolicyTextArea = ({
8200
+ value,
8201
+ onChange,
8202
+ onSubmit,
8203
+ placeholder,
8204
+ maxVisibleLines = 8
8205
+ }) => {
8206
+ const { write } = useStdout3();
8207
+ const valueRef = useRef12(value);
8208
+ valueRef.current = value;
8209
+ useEffect9(() => {
8210
+ write?.("\x1B[?25h");
8211
+ return () => {
8212
+ write?.("\x1B[?25l");
8213
+ };
8214
+ }, [write]);
8215
+ useInput3((input, key) => {
8216
+ const result = applyPolicyInputEdit(valueRef.current, input, key);
8217
+ if (result.kind === "submit") {
8218
+ onSubmit();
8219
+ return;
8220
+ }
8221
+ if (result.kind === "change") {
8222
+ onChange(result.value);
8223
+ }
8224
+ }, { isActive: true });
8225
+ const lines = useMemo4(() => {
8226
+ if (!value) return [];
8227
+ return value.split("\n");
8228
+ }, [value]);
8229
+ if (lines.length === 0) {
8230
+ return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", width: "100%", children: [
8231
+ /* @__PURE__ */ jsx18(Text15, { inverse: true, children: " " }),
8232
+ /* @__PURE__ */ jsx18(Box14, { marginTop: 0, children: /* @__PURE__ */ jsx18(Text15, { color: THEME.dimGray, wrap: "wrap", children: placeholder }) })
8233
+ ] });
8234
+ }
8235
+ const visibleLines = lines.slice(Math.max(0, lines.length - maxVisibleLines));
8236
+ const lastIndex = visibleLines.length - 1;
8237
+ return /* @__PURE__ */ jsx18(Box14, { flexDirection: "column", width: "100%", children: visibleLines.map((line, index) => {
8238
+ const isLast = index === lastIndex;
8239
+ return /* @__PURE__ */ jsxs12(Box14, { children: [
8240
+ /* @__PURE__ */ jsx18(Text15, { children: isLast ? line : `${line}
8241
+ ` }),
8242
+ isLast && /* @__PURE__ */ jsx18(Text15, { inverse: true, children: " " })
8243
+ ] }, `${index}:${line}`);
8244
+ }) });
8245
+ };
8246
+
8247
+ // src/platform/tui/components/ChatInput.tsx
8248
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
8089
8249
  var MAX_SUGGESTIONS = 6;
8090
8250
  var ChatInput = memo10(({
8091
8251
  value,
@@ -8104,7 +8264,7 @@ var ChatInput = memo10(({
8104
8264
  const isSlashMode = value.startsWith("/");
8105
8265
  const partialCmd = isSlashMode ? value.slice(1).split(" ")[0] : "";
8106
8266
  const hasArgs = isSlashMode && value.includes(" ");
8107
- const suggestions = useMemo4(() => {
8267
+ const suggestions = useMemo5(() => {
8108
8268
  if (!isSlashMode || hasArgs) return [];
8109
8269
  return getMatchingCommands(partialCmd).slice(0, MAX_SUGGESTIONS);
8110
8270
  }, [isSlashMode, partialCmd, hasArgs]);
@@ -8112,31 +8272,31 @@ var ChatInput = memo10(({
8112
8272
  const showCommandHelp = isSlashMode && !hasArgs && suggestions.length === 0 && value.length > 1;
8113
8273
  const [selectedIdx, setSelectedIdx] = useState12(0);
8114
8274
  const clampedIdx = Math.min(selectedIdx, Math.max(0, suggestions.length - 1));
8115
- const selectedIdxRef = useRef12(clampedIdx);
8275
+ const selectedIdxRef = useRef13(clampedIdx);
8116
8276
  selectedIdxRef.current = clampedIdx;
8117
- const suggestionsRef = useRef12(suggestions);
8277
+ const suggestionsRef = useRef13(suggestions);
8118
8278
  suggestionsRef.current = suggestions;
8119
- const isSlashModeRef = useRef12(isSlashMode);
8279
+ const isSlashModeRef = useRef13(isSlashMode);
8120
8280
  isSlashModeRef.current = isSlashMode;
8121
- const hasArgsRef = useRef12(hasArgs);
8281
+ const hasArgsRef = useRef13(hasArgs);
8122
8282
  hasArgsRef.current = hasArgs;
8123
- const showPreviewRef = useRef12(showPreview);
8283
+ const showPreviewRef = useRef13(showPreview);
8124
8284
  showPreviewRef.current = showPreview;
8125
- const inputRequestRef = useRef12(inputRequest);
8285
+ const inputRequestRef = useRef13(inputRequest);
8126
8286
  inputRequestRef.current = inputRequest;
8127
- const onChangeRef = useRef12(onChange);
8287
+ const onChangeRef = useRef13(onChange);
8128
8288
  onChangeRef.current = onChange;
8129
- const onRecallQueuedInputRef = useRef12(onRecallQueuedInput);
8289
+ const onRecallQueuedInputRef = useRef13(onRecallQueuedInput);
8130
8290
  onRecallQueuedInputRef.current = onRecallQueuedInput;
8131
- const queuedCountRef = useRef12(queuedCount);
8291
+ const queuedCountRef = useRef13(queuedCount);
8132
8292
  queuedCountRef.current = queuedCount;
8133
- const latestValueRef = useRef12(value);
8293
+ const latestValueRef = useRef13(value);
8134
8294
  latestValueRef.current = value;
8135
8295
  const handleLocalChange = useCallback14((newVal) => {
8136
8296
  latestValueRef.current = newVal;
8137
8297
  onChange(newVal);
8138
8298
  }, [onChange]);
8139
- const latestSecretRef = useRef12(secretInput);
8299
+ const latestSecretRef = useRef13(secretInput);
8140
8300
  latestSecretRef.current = secretInput;
8141
8301
  const handleSecretChange = useCallback14((newVal) => {
8142
8302
  latestSecretRef.current = newVal;
@@ -8153,7 +8313,7 @@ var ChatInput = memo10(({
8153
8313
  setSelectedIdx(0);
8154
8314
  setInputKey((k) => k + 1);
8155
8315
  }, []);
8156
- const onSubmitRef = useRef12(onSubmit);
8316
+ const onSubmitRef = useRef13(onSubmit);
8157
8317
  onSubmitRef.current = onSubmit;
8158
8318
  const wrappedOnSubmit = useCallback14((_staleVal) => {
8159
8319
  const finalValue = latestValueRef.current;
@@ -8175,7 +8335,7 @@ var ChatInput = memo10(({
8175
8335
  }
8176
8336
  onSubmitRef.current(finalValue);
8177
8337
  }, [completeCommand]);
8178
- const onSecretSubmitRef = useRef12(onSecretSubmit);
8338
+ const onSecretSubmitRef = useRef13(onSecretSubmit);
8179
8339
  onSecretSubmitRef.current = onSecretSubmit;
8180
8340
  const wrappedSecretSubmit = useCallback14((_staleVal) => {
8181
8341
  onSecretSubmitRef.current(latestSecretRef.current);
@@ -8206,24 +8366,24 @@ var ChatInput = memo10(({
8206
8366
  }
8207
8367
  return false;
8208
8368
  }, [completeCommand]);
8209
- return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", width: "100%", children: [
8210
- showPreview && /* @__PURE__ */ jsx18(
8369
+ return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", width: "100%", children: [
8370
+ showPreview && /* @__PURE__ */ jsx19(
8211
8371
  AutocompletePreview,
8212
8372
  {
8213
8373
  suggestions,
8214
8374
  clampedIdx
8215
8375
  }
8216
8376
  ),
8217
- showCommandHelp && /* @__PURE__ */ jsx18(Box14, { borderStyle: "round", borderColor: THEME.border.default, marginBottom: 1, children: /* @__PURE__ */ jsx18(Text15, { color: THEME.gray, children: "No matching command. Type `/help` to see all commands." }) }),
8218
- inputRequest.status !== "active" && queuedCount > 0 && /* @__PURE__ */ jsxs12(Box14, { marginBottom: 1, width: "100%", children: [
8219
- /* @__PURE__ */ jsx18(Text15, { dimColor: true, children: "queued " }),
8220
- /* @__PURE__ */ jsx18(Text15, { color: THEME.primary, children: queuedCount }),
8221
- queuedPreview && /* @__PURE__ */ jsx18(Text15, { dimColor: true, children: ` next: ${queuedPreview.slice(0, 30)}${queuedPreview.length > 30 ? "..." : ""}` }),
8222
- /* @__PURE__ */ jsx18(Text15, { dimColor: true, children: " \xB7 \u2191 to recall" })
8377
+ showCommandHelp && /* @__PURE__ */ jsx19(Box15, { borderStyle: "round", borderColor: THEME.border.default, marginBottom: 1, children: /* @__PURE__ */ jsx19(Text16, { color: THEME.gray, children: "No matching command. Type `/help` to see all commands." }) }),
8378
+ inputRequest.status !== "active" && queuedCount > 0 && /* @__PURE__ */ jsxs13(Box15, { marginBottom: 1, width: "100%", children: [
8379
+ /* @__PURE__ */ jsx19(Text16, { dimColor: true, children: "queued " }),
8380
+ /* @__PURE__ */ jsx19(Text16, { color: THEME.primary, children: queuedCount }),
8381
+ queuedPreview && /* @__PURE__ */ jsx19(Text16, { dimColor: true, children: ` next: ${queuedPreview.slice(0, 30)}${queuedPreview.length > 30 ? "..." : ""}` }),
8382
+ /* @__PURE__ */ jsx19(Text16, { dimColor: true, children: " \xB7 \u2191 to recall" })
8223
8383
  ] }),
8224
8384
  inputRequest.status === "active" ? (
8225
8385
  /* Active input request — yellow top/bottom border */
8226
- /* @__PURE__ */ jsx18(
8386
+ /* @__PURE__ */ jsx19(
8227
8387
  SecretInputArea,
8228
8388
  {
8229
8389
  inputRequest,
@@ -8235,7 +8395,7 @@ var ChatInput = memo10(({
8235
8395
  )
8236
8396
  ) : (
8237
8397
  /* Normal input — dim top/bottom border */
8238
- /* @__PURE__ */ jsx18(
8398
+ /* @__PURE__ */ jsx19(
8239
8399
  NormalInputArea,
8240
8400
  {
8241
8401
  inputKey,
@@ -8251,9 +8411,9 @@ var ChatInput = memo10(({
8251
8411
  });
8252
8412
 
8253
8413
  // src/platform/tui/components/footer.tsx
8254
- import { memo as memo11, useState as useState13, useEffect as useEffect9 } from "react";
8255
- import { Box as Box15, Text as Text16 } from "ink";
8256
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
8414
+ import { memo as memo11, useState as useState13, useEffect as useEffect10 } from "react";
8415
+ import { Box as Box16, Text as Text17 } from "ink";
8416
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
8257
8417
  var SECS_PER_HOUR = 3600;
8258
8418
  var SECS_PER_MINUTE = 60;
8259
8419
  var SHORTCUTS_HINT_DEBOUNCE_MS = 200;
@@ -8288,7 +8448,7 @@ var Footer = memo11(({
8288
8448
  const ctxPct = totalTokens > 0 ? Math.round(totalTokens / LLM_LIMITS.streamMaxTokens * 100) : 0;
8289
8449
  const canShowHint = !isProcessing && inputText.length === 0;
8290
8450
  const [showHint, setShowHint] = useState13(false);
8291
- useEffect9(() => {
8451
+ useEffect10(() => {
8292
8452
  if (!canShowHint) {
8293
8453
  setShowHint(false);
8294
8454
  return;
@@ -8321,18 +8481,18 @@ var Footer = memo11(({
8321
8481
  const rightWidth = rightText.length;
8322
8482
  const availableLeft = Math.max(0, columns - 4 - rightWidth);
8323
8483
  const renderedLeft = truncateTail(leftText, availableLeft);
8324
- return /* @__PURE__ */ jsxs13(Box15, { width: "100%", marginTop: 1, children: [
8325
- /* @__PURE__ */ jsx19(Box15, { flexShrink: 0, children: /* @__PURE__ */ jsx19(Text16, { color: THEME.dimGray, wrap: "truncate-end", children: renderedLeft }) }),
8326
- /* @__PURE__ */ jsx19(Box15, { flexGrow: 1 }),
8327
- rightText.length > 0 && /* @__PURE__ */ jsx19(Box15, { flexShrink: 0, children: /* @__PURE__ */ jsx19(Text16, { color: THEME.dimGray, wrap: "truncate-end", children: rightText }) })
8484
+ return /* @__PURE__ */ jsxs14(Box16, { width: "100%", marginTop: 1, children: [
8485
+ /* @__PURE__ */ jsx20(Box16, { flexShrink: 0, children: /* @__PURE__ */ jsx20(Text17, { color: THEME.dimGray, wrap: "truncate-end", children: renderedLeft }) }),
8486
+ /* @__PURE__ */ jsx20(Box16, { flexGrow: 1 }),
8487
+ rightText.length > 0 && /* @__PURE__ */ jsx20(Box16, { flexShrink: 0, children: /* @__PURE__ */ jsx20(Text17, { color: THEME.dimGray, wrap: "truncate-end", children: rightText }) })
8328
8488
  ] });
8329
8489
  });
8330
8490
  var footer_default = Footer;
8331
8491
 
8332
8492
  // src/platform/tui/components/Modal.tsx
8333
- import { useMemo as useMemo5, memo as memo12, useCallback as useCallback15, useRef as useRef13 } from "react";
8334
- import { Box as Box16, Text as Text17, useInput as useInput3 } from "ink";
8335
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
8493
+ import { useMemo as useMemo6, memo as memo12, useCallback as useCallback15, useRef as useRef14 } from "react";
8494
+ import { Box as Box17, Text as Text18, useInput as useInput4 } from "ink";
8495
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
8336
8496
  var MODAL_TITLES = {
8337
8497
  findings: "\u25C8 FINDINGS \u25C8",
8338
8498
  report: "\u25C8 OPERATION REPORT \u25C8",
@@ -8347,21 +8507,21 @@ var Modal = memo12(({
8347
8507
  onScroll,
8348
8508
  onClose
8349
8509
  }) => {
8350
- const onScrollRef = useRef13(onScroll);
8510
+ const onScrollRef = useRef14(onScroll);
8351
8511
  onScrollRef.current = onScroll;
8352
- const onCloseRef = useRef13(onClose);
8512
+ const onCloseRef = useRef14(onClose);
8353
8513
  onCloseRef.current = onClose;
8354
8514
  const { columns, rows } = useTerminalSize();
8355
8515
  const terminalHeight = rows;
8356
8516
  const terminalWidth = columns - 4;
8357
8517
  const maxHeight = Math.max(1, terminalHeight - 6);
8358
- const lines = useMemo5(() => content.split("\n"), [content]);
8518
+ const lines = useMemo6(() => content.split("\n"), [content]);
8359
8519
  const totalLines = lines.length;
8360
- const visibleLines = useMemo5(
8520
+ const visibleLines = useMemo6(
8361
8521
  () => lines.slice(scrollOffset, scrollOffset + maxHeight),
8362
8522
  [lines, scrollOffset, maxHeight]
8363
8523
  );
8364
- useInput3(useCallback15((input, key) => {
8524
+ useInput4(useCallback15((input, key) => {
8365
8525
  if (key.escape || input === "q") {
8366
8526
  onCloseRef.current();
8367
8527
  } else if (key.upArrow || input === "k") {
@@ -8378,20 +8538,20 @@ var Modal = memo12(({
8378
8538
  const endLine = Math.min(scrollOffset + maxHeight, totalLines);
8379
8539
  const scrollbarHeight = Math.max(1, Math.floor(maxHeight * (maxHeight / Math.max(totalLines, 1))));
8380
8540
  const scrollbarPosition = totalLines > maxHeight ? Math.floor(scrollOffset / (totalLines - maxHeight) * (maxHeight - scrollbarHeight)) : 0;
8381
- return /* @__PURE__ */ jsxs14(
8382
- Box16,
8541
+ return /* @__PURE__ */ jsxs15(
8542
+ Box17,
8383
8543
  {
8384
8544
  flexDirection: "column",
8385
8545
  width: terminalWidth,
8386
8546
  height: terminalHeight,
8387
8547
  children: [
8388
- /* @__PURE__ */ jsx20(Box16, { justifyContent: "center", marginBottom: 0, children: /* @__PURE__ */ jsx20(Text17, { color: THEME.primary, bold: true, children: (() => {
8548
+ /* @__PURE__ */ jsx21(Box17, { justifyContent: "center", marginBottom: 0, children: /* @__PURE__ */ jsx21(Text18, { color: THEME.primary, bold: true, children: (() => {
8389
8549
  const title = MODAL_TITLES[type];
8390
8550
  const sideWidth = Math.max(3, Math.floor((terminalWidth - title.length - 2) / 2));
8391
8551
  return `${"\u2500".repeat(sideWidth)} ${title} ${"\u2500".repeat(sideWidth)}`;
8392
8552
  })() }) }),
8393
- /* @__PURE__ */ jsx20(
8394
- Box16,
8553
+ /* @__PURE__ */ jsx21(
8554
+ Box17,
8395
8555
  {
8396
8556
  flexDirection: "column",
8397
8557
  borderStyle: "round",
@@ -8400,17 +8560,17 @@ var Modal = memo12(({
8400
8560
  flexGrow: 1,
8401
8561
  children: visibleLines.map((line, i) => {
8402
8562
  const showScrollbar = totalLines > maxHeight && i >= scrollbarPosition && i < scrollbarPosition + scrollbarHeight;
8403
- return /* @__PURE__ */ jsxs14(Box16, { children: [
8404
- /* @__PURE__ */ jsx20(Text17, { color: THEME.white, wrap: "truncate", children: line }),
8405
- /* @__PURE__ */ jsx20(Box16, { flexGrow: 1 }),
8406
- totalLines > maxHeight && /* @__PURE__ */ jsx20(Text17, { color: showScrollbar ? THEME.primary : THEME.dimGray, children: showScrollbar ? "\u2588" : "\u2502" })
8563
+ return /* @__PURE__ */ jsxs15(Box17, { children: [
8564
+ /* @__PURE__ */ jsx21(Text18, { color: THEME.white, wrap: "truncate", children: line }),
8565
+ /* @__PURE__ */ jsx21(Box17, { flexGrow: 1 }),
8566
+ totalLines > maxHeight && /* @__PURE__ */ jsx21(Text18, { color: showScrollbar ? THEME.primary : THEME.dimGray, children: showScrollbar ? "\u2588" : "\u2502" })
8407
8567
  ] }, i);
8408
8568
  })
8409
8569
  }
8410
8570
  ),
8411
- /* @__PURE__ */ jsxs14(Box16, { justifyContent: "space-between", paddingX: 1, children: [
8412
- /* @__PURE__ */ jsx20(Text17, { color: THEME.dimGray, children: "\u2191\u2193/jk: scroll | g/G: top/bottom | ESC/q: close" }),
8413
- /* @__PURE__ */ jsxs14(Text17, { color: THEME.primary, children: [
8571
+ /* @__PURE__ */ jsxs15(Box17, { justifyContent: "space-between", paddingX: 1, children: [
8572
+ /* @__PURE__ */ jsx21(Text18, { color: THEME.dimGray, children: "\u2191\u2193/jk: scroll | g/G: top/bottom | ESC/q: close" }),
8573
+ /* @__PURE__ */ jsxs15(Text18, { color: THEME.primary, children: [
8414
8574
  startLine,
8415
8575
  "-",
8416
8576
  endLine,
@@ -8424,9 +8584,9 @@ var Modal = memo12(({
8424
8584
  });
8425
8585
 
8426
8586
  // src/platform/tui/components/PolicyComposerModal.tsx
8427
- import { memo as memo13, useCallback as useCallback16, useRef as useRef14 } from "react";
8428
- import { Box as Box17, Text as Text18, useInput as useInput4 } from "ink";
8429
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
8587
+ import { memo as memo13, useCallback as useCallback16, useRef as useRef15 } from "react";
8588
+ import { Box as Box18, Text as Text19, useInput as useInput5 } from "ink";
8589
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
8430
8590
  var PolicyComposerModal = memo13(({
8431
8591
  value,
8432
8592
  onChange,
@@ -8435,54 +8595,68 @@ var PolicyComposerModal = memo13(({
8435
8595
  guide,
8436
8596
  placeholder
8437
8597
  }) => {
8438
- const onCloseRef = useRef14(onClose);
8598
+ const onCloseRef = useRef15(onClose);
8439
8599
  onCloseRef.current = onClose;
8440
- const onSubmitRef = useRef14(onSubmit);
8600
+ const onSubmitRef = useRef15(onSubmit);
8441
8601
  onSubmitRef.current = onSubmit;
8442
8602
  const { columns, rows } = useTerminalSize();
8443
- const terminalHeight = rows;
8444
- const terminalWidth = columns - 4;
8445
- useInput4(useCallback16((_input, key) => {
8603
+ const terminalHeight = Math.max(1, rows);
8604
+ const terminalWidth = Math.max(1, columns - 4);
8605
+ const shouldStackFooter = shouldStackPolicyComposerFooter(terminalWidth);
8606
+ useInput5(useCallback16((_input, key) => {
8446
8607
  if (key.escape) {
8447
8608
  onCloseRef.current();
8448
8609
  }
8449
8610
  }, []), { isActive: true });
8450
- return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", width: terminalWidth, height: terminalHeight, children: [
8451
- /* @__PURE__ */ jsx21(Box17, { justifyContent: "center", children: /* @__PURE__ */ jsx21(Text18, { color: THEME.primary, bold: true, children: (() => {
8452
- const title = "\u25C8 COMPETITION POLICY \u25C8";
8453
- const sideWidth = Math.max(3, Math.floor((terminalWidth - title.length - 2) / 2));
8454
- return `${"\u2500".repeat(sideWidth)} ${title} ${"\u2500".repeat(sideWidth)}`;
8455
- })() }) }),
8456
- /* @__PURE__ */ jsxs15(
8457
- Box17,
8611
+ return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", width: terminalWidth, height: terminalHeight, children: [
8612
+ /* @__PURE__ */ jsx22(Box18, { justifyContent: "center", width: "100%", children: /* @__PURE__ */ jsx22(Text19, { color: THEME.primary, bold: true, wrap: "truncate-end", children: formatPolicyComposerTitle(terminalWidth) }) }),
8613
+ /* @__PURE__ */ jsxs16(
8614
+ Box18,
8458
8615
  {
8459
8616
  flexDirection: "column",
8617
+ width: "100%",
8460
8618
  borderStyle: "round",
8461
8619
  borderColor: THEME.primary,
8462
8620
  paddingX: 1,
8463
8621
  paddingY: 1,
8464
8622
  flexGrow: 1,
8465
8623
  children: [
8466
- /* @__PURE__ */ jsx21(Text18, { color: THEME.white, bold: true, children: "Optional bootstrap policy before /start" }),
8467
- /* @__PURE__ */ jsx21(Text18, { color: THEME.dimGray, children: " " }),
8468
- guide.split("\n").map((line, index) => /* @__PURE__ */ jsx21(Text18, { color: THEME.gray, wrap: "wrap", children: line }, index)),
8469
- /* @__PURE__ */ jsx21(Text18, { color: THEME.dimGray, children: " " }),
8470
- /* @__PURE__ */ jsx21(Box17, { borderStyle: "round", borderColor: THEME.primary, paddingX: 1, paddingY: 0, children: /* @__PURE__ */ jsx21(
8471
- NormalInputArea,
8624
+ /* @__PURE__ */ jsx22(Text19, { color: THEME.white, bold: true, children: "Optional bootstrap policy before /start" }),
8625
+ /* @__PURE__ */ jsx22(Text19, { color: THEME.dimGray, children: " " }),
8626
+ guide.split("\n").map((line, index) => /* @__PURE__ */ jsx22(Text19, { color: THEME.gray, wrap: "wrap", children: line }, index)),
8627
+ /* @__PURE__ */ jsx22(Text19, { color: THEME.dimGray, children: " " }),
8628
+ /* @__PURE__ */ jsx22(
8629
+ Box18,
8472
8630
  {
8473
- inputKey: 0,
8474
- value,
8475
- onChange,
8476
- onSubmit: () => onSubmitRef.current(),
8477
- placeholder
8631
+ width: "100%",
8632
+ borderStyle: "round",
8633
+ borderColor: THEME.primary,
8634
+ paddingX: 1,
8635
+ paddingY: 0,
8636
+ flexGrow: 1,
8637
+ children: /* @__PURE__ */ jsx22(
8638
+ PolicyTextArea,
8639
+ {
8640
+ value,
8641
+ onChange,
8642
+ onSubmit: onSubmitRef.current,
8643
+ placeholder
8644
+ }
8645
+ )
8478
8646
  }
8479
- ) })
8647
+ )
8480
8648
  ]
8481
8649
  }
8482
8650
  ),
8483
- /* @__PURE__ */ jsxs15(Box17, { justifyContent: "space-between", paddingX: 1, children: [
8484
- /* @__PURE__ */ jsx21(Text18, { color: THEME.dimGray, children: "Enter: continue | Esc: cancel start" }),
8485
- /* @__PURE__ */ jsxs15(Text18, { color: THEME.primary, children: [
8651
+ shouldStackFooter ? /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", paddingX: 1, width: "100%", children: [
8652
+ /* @__PURE__ */ jsx22(Text19, { color: THEME.dimGray, wrap: "wrap", children: "Enter: continue | Ctrl+J: newline | Esc: cancel start" }),
8653
+ /* @__PURE__ */ jsx22(Box18, { justifyContent: "flex-end", width: "100%", children: /* @__PURE__ */ jsxs16(Text19, { color: THEME.primary, children: [
8654
+ value.trim().length,
8655
+ " chars"
8656
+ ] }) })
8657
+ ] }) : /* @__PURE__ */ jsxs16(Box18, { justifyContent: "space-between", paddingX: 1, width: "100%", children: [
8658
+ /* @__PURE__ */ jsx22(Text19, { color: THEME.dimGray, wrap: "wrap", children: "Enter: continue | Ctrl+J: newline | Esc: cancel start" }),
8659
+ /* @__PURE__ */ jsxs16(Text19, { color: THEME.primary, children: [
8486
8660
  value.trim().length,
8487
8661
  " chars"
8488
8662
  ] })
@@ -8491,8 +8665,8 @@ var PolicyComposerModal = memo13(({
8491
8665
  });
8492
8666
 
8493
8667
  // src/platform/tui/components/app/bottom-region.tsx
8494
- import { Box as Box18, Text as Text19 } from "ink";
8495
- import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
8668
+ import { Box as Box19, Text as Text20 } from "ink";
8669
+ import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
8496
8670
  var BottomRegion = ({
8497
8671
  input,
8498
8672
  setInput,
@@ -8517,8 +8691,9 @@ var BottomRegion = ({
8517
8691
  }) => {
8518
8692
  const { columns } = useTerminalSize();
8519
8693
  const inputSeparatorColor = resolveInputSeparatorColor({ isProcessing, inputRequest });
8520
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", width: "100%", children: [
8521
- /* @__PURE__ */ jsx22(
8694
+ const inputPlaceholder = resolveInputPlaceholder({ isProcessing, inputRequest });
8695
+ return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", width: "100%", children: [
8696
+ /* @__PURE__ */ jsx23(
8522
8697
  StatusDisplay,
8523
8698
  {
8524
8699
  retryState,
@@ -8529,8 +8704,8 @@ var BottomRegion = ({
8529
8704
  inputRequest
8530
8705
  }
8531
8706
  ),
8532
- /* @__PURE__ */ jsx22(Text19, { color: inputSeparatorColor, children: "\u2500".repeat(Math.max(1, columns - 2)) }),
8533
- /* @__PURE__ */ jsx22(Box18, { width: "100%", children: /* @__PURE__ */ jsx22(
8707
+ /* @__PURE__ */ jsx23(Text20, { color: inputSeparatorColor, children: "\u2500".repeat(Math.max(1, columns - 2)) }),
8708
+ /* @__PURE__ */ jsx23(Box19, { width: "100%", children: /* @__PURE__ */ jsx23(
8534
8709
  ChatInput,
8535
8710
  {
8536
8711
  value: input,
@@ -8539,7 +8714,7 @@ var BottomRegion = ({
8539
8714
  onRecallQueuedInput: recallQueuedInput,
8540
8715
  queuedCount: messageQueue.length,
8541
8716
  queuedPreview,
8542
- placeholder: "Describe the target or type /help",
8717
+ placeholder: inputPlaceholder,
8543
8718
  inputRequest,
8544
8719
  pendingInputCount: pendingInputRequests,
8545
8720
  secretInput,
@@ -8547,8 +8722,8 @@ var BottomRegion = ({
8547
8722
  onSecretSubmit: handleSecretSubmit
8548
8723
  }
8549
8724
  ) }),
8550
- /* @__PURE__ */ jsx22(Text19, { color: inputSeparatorColor, children: "\u2500".repeat(Math.max(1, columns - 2)) }),
8551
- /* @__PURE__ */ jsx22(Box18, { width: "100%", children: /* @__PURE__ */ jsx22(
8725
+ /* @__PURE__ */ jsx23(Text20, { color: inputSeparatorColor, children: "\u2500".repeat(Math.max(1, columns - 2)) }),
8726
+ /* @__PURE__ */ jsx23(Box19, { width: "100%", children: /* @__PURE__ */ jsx23(
8552
8727
  footer_default,
8553
8728
  {
8554
8729
  phase: stats.phase,
@@ -8569,8 +8744,8 @@ var BottomRegion = ({
8569
8744
  };
8570
8745
 
8571
8746
  // src/platform/tui/hooks/useModalMouseWheel.ts
8572
- import { useEffect as useEffect10 } from "react";
8573
- import { useStdin, useStdout as useStdout3 } from "ink";
8747
+ import { useEffect as useEffect11 } from "react";
8748
+ import { useStdin, useStdout as useStdout4 } from "ink";
8574
8749
  var ENABLE_MOUSE_REPORTING = "\x1B[?1000h\x1B[?1006h";
8575
8750
  var DISABLE_MOUSE_REPORTING = "\x1B[?1000l\x1B[?1006l";
8576
8751
  var SGR_MOUSE_RE = /\x1b\[<(\d+);(\d+);(\d+)([mM])/g;
@@ -8588,8 +8763,8 @@ function useModalMouseWheel({
8588
8763
  onScroll
8589
8764
  }) {
8590
8765
  const { stdin, setRawMode } = useStdin();
8591
- const { stdout } = useStdout3();
8592
- useEffect10(() => {
8766
+ const { stdout } = useStdout4();
8767
+ useEffect11(() => {
8593
8768
  if (!isActive) return;
8594
8769
  setRawMode?.(true);
8595
8770
  stdout.write?.(ENABLE_MOUSE_REPORTING);
@@ -8607,7 +8782,7 @@ function useModalMouseWheel({
8607
8782
  }
8608
8783
 
8609
8784
  // src/platform/tui/app.tsx
8610
- import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
8785
+ import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
8611
8786
  var MODEL_NAME = getModel() || DEFAULT_MODEL;
8612
8787
  var App = ({ autoApprove = false, target }) => {
8613
8788
  const {
@@ -8650,7 +8825,7 @@ var App = ({ autoApprove = false, target }) => {
8650
8825
  onScroll: handleModalScroll
8651
8826
  });
8652
8827
  if (policyComposer.isOpen) {
8653
- return /* @__PURE__ */ jsx23(Box19, { flexDirection: "column", paddingX: 1, width: terminalWidth, height: terminalHeight - 1, children: /* @__PURE__ */ jsx23(
8828
+ return /* @__PURE__ */ jsx24(Box20, { flexDirection: "column", paddingX: 1, width: terminalWidth, height: terminalHeight - 1, children: /* @__PURE__ */ jsx24(
8654
8829
  PolicyComposerModal,
8655
8830
  {
8656
8831
  value: policyComposer.value,
@@ -8665,7 +8840,7 @@ var App = ({ autoApprove = false, target }) => {
8665
8840
  ) });
8666
8841
  }
8667
8842
  if (modal.type) {
8668
- return /* @__PURE__ */ jsx23(Box19, { flexDirection: "column", paddingX: 1, width: terminalWidth, height: terminalHeight - 1, children: /* @__PURE__ */ jsx23(
8843
+ return /* @__PURE__ */ jsx24(Box20, { flexDirection: "column", paddingX: 1, width: terminalWidth, height: terminalHeight - 1, children: /* @__PURE__ */ jsx24(
8669
8844
  Modal,
8670
8845
  {
8671
8846
  type: modal.type,
@@ -8676,8 +8851,8 @@ var App = ({ autoApprove = false, target }) => {
8676
8851
  }
8677
8852
  ) });
8678
8853
  }
8679
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", paddingX: 1, paddingBottom: 1, width: terminalWidth, children: [
8680
- /* @__PURE__ */ jsx23(Box19, { flexDirection: "column", width: "100%", children: /* @__PURE__ */ jsx23(
8854
+ return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", paddingX: 1, paddingBottom: 1, width: terminalWidth, children: [
8855
+ /* @__PURE__ */ jsx24(Box20, { flexDirection: "column", width: "100%", children: /* @__PURE__ */ jsx24(
8681
8856
  MessageList,
8682
8857
  {
8683
8858
  messages,
@@ -8686,7 +8861,7 @@ var App = ({ autoApprove = false, target }) => {
8686
8861
  version: APP_VERSION
8687
8862
  }
8688
8863
  ) }),
8689
- /* @__PURE__ */ jsx23(Box19, { flexDirection: "column", marginTop: 1, width: "100%", children: /* @__PURE__ */ jsx23(
8864
+ /* @__PURE__ */ jsx24(Box20, { flexDirection: "column", marginTop: 1, width: "100%", children: /* @__PURE__ */ jsx24(
8690
8865
  BottomRegion,
8691
8866
  {
8692
8867
  input,
@@ -8716,8 +8891,8 @@ var App = ({ autoApprove = false, target }) => {
8716
8891
  var app_default = App;
8717
8892
 
8718
8893
  // src/platform/tui/components/SplashScreen.tsx
8719
- import { useEffect as useEffect11, useState as useState14 } from "react";
8720
- import { Box as Box20, Text as Text20 } from "ink";
8894
+ import { useEffect as useEffect12, useState as useState14 } from "react";
8895
+ import { Box as Box21, Text as Text21 } from "ink";
8721
8896
 
8722
8897
  // src/platform/tui/components/CoinFrames.ts
8723
8898
  var COIN_FRAMES = [
@@ -9408,14 +9583,14 @@ var COIN_FRAMES = [
9408
9583
  ];
9409
9584
 
9410
9585
  // src/platform/tui/components/SplashScreen.tsx
9411
- import { jsx as jsx24 } from "react/jsx-runtime";
9586
+ import { jsx as jsx25 } from "react/jsx-runtime";
9412
9587
  var SplashScreen = ({
9413
9588
  onComplete,
9414
9589
  durationMs = 3e3
9415
9590
  }) => {
9416
9591
  const { columns, rows } = useTerminalSize();
9417
9592
  const [frameIdx, setFrameIdx] = useState14(0);
9418
- useEffect11(() => {
9593
+ useEffect12(() => {
9419
9594
  const start = Date.now();
9420
9595
  const interval = setInterval(() => {
9421
9596
  const now = Date.now();
@@ -9430,27 +9605,27 @@ var SplashScreen = ({
9430
9605
  return () => clearInterval(interval);
9431
9606
  }, [durationMs, onComplete]);
9432
9607
  const currentFrame = COIN_FRAMES[frameIdx % COIN_FRAMES.length];
9433
- return /* @__PURE__ */ jsx24(
9434
- Box20,
9608
+ return /* @__PURE__ */ jsx25(
9609
+ Box21,
9435
9610
  {
9436
9611
  width: columns,
9437
9612
  minHeight: rows,
9438
9613
  flexDirection: "column",
9439
9614
  alignItems: "center",
9440
9615
  justifyContent: "center",
9441
- children: /* @__PURE__ */ jsx24(Box20, { flexDirection: "column", alignItems: "center", flexShrink: 0, children: /* @__PURE__ */ jsx24(Box20, { flexDirection: "column", alignItems: "center", children: currentFrame.map((line, i) => /* @__PURE__ */ jsx24(Box20, { flexShrink: 0, height: 1, children: /* @__PURE__ */ jsx24(Text20, { color: THEME.white, bold: true, wrap: "truncate-end", children: line }, `coin-text-${i}`) }, `coin-row-${i}`)) }) })
9616
+ children: /* @__PURE__ */ jsx25(Box21, { flexDirection: "column", alignItems: "center", flexShrink: 0, children: /* @__PURE__ */ jsx25(Box21, { flexDirection: "column", alignItems: "center", children: currentFrame.map((line, i) => /* @__PURE__ */ jsx25(Box21, { flexShrink: 0, height: 1, children: /* @__PURE__ */ jsx25(Text21, { color: THEME.white, bold: true, wrap: "truncate-end", children: line }, `coin-text-${i}`) }, `coin-row-${i}`)) }) })
9442
9617
  }
9443
9618
  );
9444
9619
  };
9445
9620
 
9446
9621
  // src/platform/tui/cli/interactive-runtime.tsx
9447
- import { jsx as jsx25 } from "react/jsx-runtime";
9622
+ import { jsx as jsx26 } from "react/jsx-runtime";
9448
9623
  var InteractiveRoot = ({ autoApprove, target }) => {
9449
- const [showSplash, setShowSplash] = React17.useState(true);
9624
+ const [showSplash, setShowSplash] = React18.useState(true);
9450
9625
  if (showSplash) {
9451
- return /* @__PURE__ */ jsx25(SplashScreen, { durationMs: 3e3, onComplete: () => setShowSplash(false) });
9626
+ return /* @__PURE__ */ jsx26(SplashScreen, { durationMs: 3e3, onComplete: () => setShowSplash(false) });
9452
9627
  }
9453
- return /* @__PURE__ */ jsx25(
9628
+ return /* @__PURE__ */ jsx26(
9454
9629
  app_default,
9455
9630
  {
9456
9631
  autoApprove,
@@ -9460,7 +9635,7 @@ var InteractiveRoot = ({ autoApprove, target }) => {
9460
9635
  };
9461
9636
  async function renderInteractiveApp(props) {
9462
9637
  const { waitUntilExit } = render(
9463
- /* @__PURE__ */ jsx25(AnimationProvider, { children: /* @__PURE__ */ jsx25(InteractiveRoot, { ...props }) })
9638
+ /* @__PURE__ */ jsx26(AnimationProvider, { children: /* @__PURE__ */ jsx26(InteractiveRoot, { ...props }) })
9464
9639
  );
9465
9640
  await waitUntilExit();
9466
9641
  }
@@ -3,7 +3,7 @@ import {
3
3
  clearWorkspace,
4
4
  loadState,
5
5
  saveState
6
- } from "./chunk-U2NIVQ2O.js";
6
+ } from "./chunk-4UNNRHYY.js";
7
7
  import "./chunk-S5ZMXFHR.js";
8
8
  export {
9
9
  StateSerializer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pentesting",
3
- "version": "0.73.11",
3
+ "version": "0.73.13",
4
4
  "description": "Autonomous Penetration Testing AI Agent",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",