Skip to content

fix(cli): prevent paste detection from destroying multi-line input - #84

Merged
teknium1 merged 1 commit into
NousResearch:mainfrom
0xbyt4:fix/cli-paste-detection-false-positive
Feb 27, 2026
Merged

fix(cli): prevent paste detection from destroying multi-line input#84
teknium1 merged 1 commit into
NousResearch:mainfrom
0xbyt4:fix/cli-paste-detection-false-positive

Conversation

@0xbyt4

@0xbyt4 0xbyt4 commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • The paste detection heuristic in _on_text_changed triggers whenever the buffer has 5+ newlines, regardless of how those lines were entered
  • Typing manually with Alt+Enter (one newline at a time) eventually reaches the threshold and silently replaces the user's input with a file reference — causing data loss
  • Fix: track previous buffer length and only treat a change as a paste when more than one character is added in a single event

Reproduction

  1. Start the CLI (python cli.py)
  2. Type a line, press Alt+Enter, type another line, repeat 6 times
  3. Before fix: On the 6th line, the entire input is silently replaced with [Pasted text #1: 6 lines → ~/.hermes/pastes/...]
  4. After fix: Multi-line input is preserved; only actual pastes (many characters at once) are collapsed

The _on_text_changed handler collapsed buffer contents into a file
reference whenever the buffer had 5+ newlines, regardless of how
those lines were entered. This meant manually typing with Alt+Enter
would trigger the paste heuristic and silently replace the user's
carefully typed input.

Track the previous buffer length and only treat a change as a paste
when more than one character is added at once (real pastes insert many
characters in a single event, while typing adds one at a time).
@teknium1
teknium1 merged commit 9061c03 into NousResearch:main Feb 27, 2026
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 27, 2026
…n-false-positive

fix(cli): prevent paste detection from destroying multi-line input
dizhaky referenced this pull request in dizhaky/hermes-agent Jun 23, 2026
…AN-1385) (#26)

baileys 7.0.0-rc.9->rc13 (clears #43 critical) + protobufjs 7.6.4 (#59,#58) in whatsapp-bridge; esbuild+tsx (#46,#61) in ui-tui; @babel/core (#84) in web; joi+http-proxy-middleware (#51,#89) in website. js-yaml #86 accepted (no in-range fix via gray-matter). Bridge startup verified. #93/#94 (code fixes) separate.

Co-Authored-By: Claude <noreply@anthropic.com>
Meraniya pushed a commit to Meraniya/hermes-agent that referenced this pull request Aug 6, 2026
sijav added a commit to sijav/sijav-agent that referenced this pull request Aug 7, 2026
…n region 2401-3999 (rc-slice-B) + revert 2 defeated pragmas

Slice B: 52 tests, 0 missing lines / 0 missing branches across the assigned
region. Independent roast NOT-PASSed the first cut (8.9/8.5/9.2) and defeated
two of the pragmas with empirical receipts; this commit fixes all of it.

Reverted pragmas (the guards are REACHABLE, now covered by real tests):
  * 3576 api_messages re-sanitize — _sync_failover_system_message (988-992)
    rewrites api_messages[0] from the still-dirty _cached_system_prompt/
    ephemeral_system_prompt INSIDE the retry loop (2146), which never re-runs
    the proactive walk at ~1832 (that walk belongs to the OUTER loop, 1415).
  * 3584 api_kwargs re-sanitize — nothing sanitizes agent.tools and build_kwargs
    stores it BY REFERENCE, so a surrogate in a tool-schema description reaches
    api_kwargs (MCP descriptions come from json.loads, which materializes
    \ud800 escapes as real lone surrogates).
Both replaced with source comments explaining the reachability, plus a third
vector found while closing the region: prefill_messages are spliced as shallow
copies (1776) so the SOURCE list stays dirty. Product gap filed (NousResearch#85).

Strengthened three line-hit-only tests exposed by surviving mutants:
  * MoA reference-usage fold — now asserts the enqueued totals (110/55) via
    queue_token_counts.call_args, so gutting the fold fails.
  * content-filter rollback — now asserts the partial continuation text
    (part1/part2) does not survive into the fallback's history.
  * codex incomplete — the mapping at 2766-2774 is dead-in-effect (filed NousResearch#84);
    the docstring now states that honestly and a new test drives the real
    continuation via the transport's normalize result.
Corrected two false docstrings that claimed arcs which do not fire.

Bugs filed from this pass: NousResearch#83 (mixed return arity landmine), NousResearch#84 (codex
incomplete mapping overwritten before its only consumer), NousResearch#85 (three
un-sanitized surrogate surfaces costing a wasted API call per turn).

Full tests/run_agent suite: 1704 passed, 4 skipped.
sijav added a commit to sijav/sijav-agent that referenced this pull request Aug 7, 2026
…esearch#84)

The comment claimed this assignment routes Codex incomplete turns away from the
generic chat-completions length rollback and into the Codex continuation. It
does neither.

Re-traced independently: the value set here governs only the window ending at
the unconditional `finish_reason = normalized.finish_reason`, and inside that
window finish_reason is compared ONLY against "content_filter" and "length".
"incomplete" matches neither, making this arm behaviourally identical to the
`else: "stop"` beneath it. What actually keeps Codex out of the length rollback
is that this block never produces "length" at all. The continuation that
consumes "incomplete" runs AFTER the overwrite and is driven by the transport's
own normalize result (the Responses adapter derives it from response.status).

Independently corroborated by a surviving mutation: removing "length" from the
trigger set changes no observable behaviour — a true equivalent mutant rather
than a weak test, which is why it went unnoticed.

Kept rather than deleted: it is a correct, harmless pre-set that keeps the
branch's intent legible and stays right if the overwrite is ever narrowed. The
comment now states the honest scope and warns to verify against the overwrite
before changing anything here.

Comment-only, no behaviour change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants