fix(repl): throttle tool-activity feed so line editing isn't janky during a run

While a run streams, every printed line makes rustyline redraw the input line.
The high-volume tool echoes (exec/net/read — the ⌘/🌐/📄 lines, dozens/sec during
recon/curl bursts) flooded the terminal so arrow keys and backspace felt stuck
while typing. Those lines are now rate-limited to ~1/200ms in the live feed (they
remain in full via /logs); findings, phase changes, votes and notices still print
immediately. Editing stays responsive during a run.

(Note: the /model-rewrite the user hit was the OLD binary — v4.2.2 keeps the exact
models typed; verified anthropic:claude-opus-4-8 + openai:gpt-5.6-sol are kept.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
CyberSecurityUPandClaude Opus 4.8 committed 2026-10-04 00:56:45 -03:00
1 parent 35bf7ea1a6
commit 0446bc4b5d
1 file changed
+21 -1
+21 -1
View File
@@ -1851,6 +1851,7 @@ async fn start_background(base: &Path, s: &Session, reader: &mut Reader,
let crate::Spawned { task, mut rx, workdir, .. } = sp;
let mut last_saved = 0usize;
let mut last_activity = Instant::now(); // last sign of PROGRESS (any activity)
let mut last_tool_print = Instant::now() - std::time::Duration::from_secs(1); // throttle gate for ⌘/🌐/📄 lines
let mut idle_fired = false;
let mut tool_events = 0usize; // exec/net/read/browser activity seen
let mut exploiting = false; // guardrail only arms once exploitation starts
@@ -1873,7 +1874,26 @@ async fn start_background(base: &Path, s: &Session, reader: &mut Reader,
// open (it would corrupt the picker); the line is still in the
// feed for /logs once the picker closes.
if !quiet_task.load(Ordering::Relaxed) {
if let Some(out) = crate::render_compact(&line) { let _ = printer.print(out); }
// Throttle the high-volume tool-activity lines (exec/net/read —
// the ⌘/🌐/📄 flood). Each printed line makes rustyline REDRAW
// the input line, so dozens/sec of recon/curl echoes make the
// arrow keys and backspace feel stuck while you type. Rate-limit
// just these (they stay in the feed for /logs); findings, phase,
// votes and notices always print immediately.
let is_tool = {
let t = line.split_once(": ").map(|(k, _)| k).unwrap_or("");
let t = t.rsplit(' ').next().unwrap_or(t); // strip @label prefix
matches!(t, "exec" | "danger" | "net" | "read")
};
let show = if is_tool {
if last_tool_print.elapsed() >= std::time::Duration::from_millis(200) {
last_tool_print = Instant::now();
true
} else { false }
} else { true };
if show {
if let Some(out) = crate::render_compact(&line) { let _ = printer.print(out); }
}
}
// Checkpoint on each new finding.
let snap = {