hexcli 2.20.1__tar.gz → 2.21.0__tar.gz
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.
- {hexcli-2.20.1 → hexcli-2.21.0}/CHANGELOG.md +29 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/PKG-INFO +1 -1
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/__init__.py +1 -1
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/tools.py +22 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/.gitignore +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/Hex CLI.cmd +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/LICENSE +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/README.md +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/agent.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/assets/hexcli.ico +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/assets/hexcli.png +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/cancel.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/chatlog.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/commands.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/compaction.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/config.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/diffview.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/distribution.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/doctor.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/editing.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/http_client.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/launcher.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/lineedit.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/llm.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/lockfile.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/markdown_stream.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/memory.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/network.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/parsing.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/paths.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/prompts.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/psparse.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/repl.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/safety.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/sessions.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/setup_wizard.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/statusbar.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/stream_render.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/telemetry.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/hexcli/ui.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/install.ps1 +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/launcher.py +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/pyproject.toml +0 -0
- {hexcli-2.20.1 → hexcli-2.21.0}/shellai.example.json +0 -0
|
@@ -4,6 +4,35 @@ Full evidence for every claim below — including the experiments that failed
|
|
|
4
4
|
lives in `docs/V2_PLAN.md` §14. Numbers are pass^k over repeated live runs on
|
|
5
5
|
the Hexagon NPU, not single-run anecdotes.
|
|
6
6
|
|
|
7
|
+
## 2.21.0 — 2026-10-10
|
|
8
|
+
|
|
9
|
+
A minor release: a tool result the model reads changes (`edit_file` when
|
|
10
|
+
`old_string` is not in the file).
|
|
11
|
+
|
|
12
|
+
> **Gate: PASS** on the pinned 24-case set after one recheck:
|
|
13
|
+
> `error-recovery-3` missed one of five runs, and that run never called
|
|
14
|
+
> `edit_file` (it reported a "permission error" after `find_files`); re-run on
|
|
15
|
+
> a fresh server it was 6/6. Own arm, seed 20261010, against 2.20.0's arm:
|
|
16
|
+
> run-level 189/237 vs 192/245, +1.4 %, Fisher p = 0.74; pass^k 32 → 34 of
|
|
17
|
+
> 49, McNemar p = 0.73; 8 invalid runs of 245 (backend timeouts, 2.2 GB
|
|
18
|
+
> free). `claims-2`, one of the three cases behind most of the recorded
|
|
19
|
+
> misses, went 2/5 → 5/5. `self-correct-1` lost one run to the known
|
|
20
|
+
> double-escaped `new_string` (a literal `\n` landed on the first edit,
|
|
21
|
+
> before any miss), and `regression-anchor-1` lost one to the same defect
|
|
22
|
+
> with no miss at all. Smoke 9/9 valid on a fresh server.
|
|
23
|
+
|
|
24
|
+
- A missed `edit_file` on a file of up to 1,500 characters returns the
|
|
25
|
+
file's whole current text instead of the closest region. Of 1,279 recorded
|
|
26
|
+
`edit_file` calls, 786 were made without reading the file that turn and
|
|
27
|
+
failed 45 % of the time against 9 % after a read, and 115 of the 291
|
|
28
|
+
misses came straight after another miss on the same file: the retry was
|
|
29
|
+
rebuilt from memory again. Every fixture behind those misses is under 200
|
|
30
|
+
characters. In the arm the message fired 16 times, in `tests-claim-1`,
|
|
31
|
+
`self-correct-1`, `claims-2` and `agentic-3`, and the next edit landed
|
|
32
|
+
after 7 of them (44 %), against 14 of 39 (36 %) in the three arms before
|
|
33
|
+
it; at that count the recovery rate is not yet a measured effect. A larger
|
|
34
|
+
file keeps the closest-region report.
|
|
35
|
+
|
|
7
36
|
## 2.20.1 — 2026-10-10
|
|
8
37
|
|
|
9
38
|
A patch release: nothing the model reads changes. The turn's return value
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hexcli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.21.0
|
|
4
4
|
Summary: Local Hexagon NPU terminal agent for Snapdragon X Elite Windows ARM64
|
|
5
5
|
Project-URL: Homepage, https://github.com/NathanL15/Hex-CLI
|
|
6
6
|
Project-URL: Repository, https://github.com/NathanL15/Hex-CLI
|
|
@@ -441,6 +441,8 @@ def edit_file_tool(path_text: str, old_string: str, new_string: str) -> str:
|
|
|
441
441
|
else:
|
|
442
442
|
new_content, err = apply_search_replace(content, [(old_string, new_string)])
|
|
443
443
|
if err:
|
|
444
|
+
if err.startswith("SEARCH block 1 was not found") and len(content) <= _WHOLE_FILE_ON_MISS:
|
|
445
|
+
raise RuntimeError(_not_found_with_content(path, content))
|
|
444
446
|
raise RuntimeError(err.replace("SEARCH block 1", "old_string"))
|
|
445
447
|
tier = p2.LAST_APPLY_TIER
|
|
446
448
|
tmp = path.parent / (path.name + ".tmp")
|
|
@@ -453,6 +455,26 @@ def edit_file_tool(path_text: str, old_string: str, new_string: str) -> str:
|
|
|
453
455
|
return f"Edited {path}"
|
|
454
456
|
|
|
455
457
|
|
|
458
|
+
# A missed edit_file on a small file gets the file's whole text back instead of
|
|
459
|
+
# the closest region. Of 1,279 recorded edit_file calls (2026-09-18), 786 were
|
|
460
|
+
# made without reading or writing the file that turn and failed 45 % of the
|
|
461
|
+
# time against 9 % after a read, and 115 of the 291 misses came straight after
|
|
462
|
+
# another miss on the same file: the retry was rebuilt from memory again. With
|
|
463
|
+
# the text in the error the retry can be copied from the file, at no extra
|
|
464
|
+
# step. Every fixture behind those misses is under 200 characters; a file
|
|
465
|
+
# above the cap keeps the closest-region report.
|
|
466
|
+
_WHOLE_FILE_ON_MISS = 1500
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def _not_found_with_content(path: Path, content: str) -> str:
|
|
470
|
+
body = content if content.strip() else "(the file is empty)"
|
|
471
|
+
return (
|
|
472
|
+
f"old_string was not found in {path}. This is the file's whole current "
|
|
473
|
+
"content; copy the lines to change from it exactly into old_string:\n"
|
|
474
|
+
f"---\n{body.rstrip(chr(10))}\n---"
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
|
|
456
478
|
def write_file_tool(path_text: str, content: str) -> str:
|
|
457
479
|
from . import editing as p2
|
|
458
480
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|