Commit Graph

76 Commits

Author SHA1 Message Date
NCBM 2cf66edb60 core/tools: edit results preview the old content
Wrong-target edits (the test_run_aside pass clobber, the edit_replace
mangling) were silent: the success message reported counts only, so the
model had no signal it replaced the wrong thing until later.

edit_lineno now reports the first removed line ("first: 'pass'") and
edit_replace reports the matched pattern ('old' -> 'new'), giving the
model an immediate self-correction signal.
2026-08-15 17:40:26 +08:00
NCBM 38671482f2 core/tools: edit_lineno unread error names the read window
The boundary overguard (read offset=50 shows lines 51+, then editing
line 50 fails) forced blind re-reads. The error now reports the read
window ("this turn read lines 51-86") and advises reading with a margin
around the target range; read_file's description says the same.
2026-08-15 17:38:58 +08:00
NCBM c9815e32bb core/tools: mtime freshness replaces per-write lineno invalidation
edit_lineno now rejects edits when the file changed since the numbered
read (mtime recorded at read time), so stale line numbers are caught
even when the mutation came from run_argv / an external process — the
class the explicit invalidations could never cover.

This lets write_file / edit_replace / edit_lineno drop their explicit
invalidate calls (the write itself changes the mtime, and the error is
now the accurate "changed since it was read" instead of a misleading
"not read"). copy/move keep explicit invalidation because shutil
preserves the source mtime, which the freshness check cannot see.
2026-08-15 17:38:10 +08:00
NCBM d914590677 core/tools: numbered read continuation via get_truncated
Two fixes for the truncated numbered-read flow:

- read_file(with_lineno) tokens were rebased onto numbered-body chars
  (each line carries an N| prefix), so get_truncated over-advanced into
  raw text and silently skipped lines. Tokens now advance by raw chars
  of the complete lines shown and carry a numbered flag.
- get_truncated resumes numbered tokens as numbered lines (via
  read_file with_lineno), marking them readable for edit_lineno, so
  read -> get_truncated -> edit_lineno works end-to-end without gaps.
2026-08-15 17:35:57 +08:00
NCBM 132ac520ec core/tools: mark only displayed lines read on truncated read_file
read_file(with_lineno=true) marked the whole requested slice before
applying the max_chars cap, so a truncated read silently unlocked every
line of the file for edit_lineno even though the model never saw them.
Mark only the complete numbered lines actually returned (excluding the
[Truncated] marker); the unseen tail stays unread.
2026-08-15 17:31:43 +08:00
NCBM 4fa05e2456 core/tools: tree format markdown|flat|decorated, markdown default
The model picks the representation per call via the format param (no
user config). markdown (default) is a nested bullet list: ASCII-only,
cheapest tokens, indentation-based hierarchy the model reads reliably.
flat lists one relative path per line (dirs with trailing /, empty dirs
included) with max_entries capping the total lines, so paths are directly
usable. decorated keeps the classic box-drawing tree for humans.
2026-08-15 17:06:12 +08:00
NCBM ddca6e23d3 core/tools: add READ_ONLY tool attribute
New ToolTag.READ_ONLY marks tools that never mutate host state, plus
ToolRegistry.clone(read_only_only=True) to select just those (for safe
side turns / planning). Builtin read-only set: read_file, get_truncated,
glob_paths, grep_files, listdir, tree, todo_list, wait, ask_user_*,
vcs_* and fetch.

fetch is tagged READ_ONLY but can mutate via method; a new
read_only_context ContextVar makes it accept GET only while set.
2026-08-15 16:46:27 +08:00
NCBM bd1053a3bc core/config: document default truncate_token everywhere 2026-08-11 19:42:10 +08:00
NCBM b5a30190f6 core/tools: default read_file truncation with token (no hint when uncut) 2026-08-11 19:42:10 +08:00
NCBM 26472776fb core/tools: token-ify per-stream caps and resume memory remainders 2026-08-11 19:41:54 +08:00
NCBM ec1ae59a28 core/tools: unified truncate marker with memory remainder store 2026-08-11 19:41:54 +08:00
NCBM e4ed89b391 core/tools: distinguish missing files from non-files on read 2026-08-11 15:37:56 +08:00
NCBM 25e6ec3d44 core/tools: show 1-based line range on read_file results 2026-08-11 15:33:12 +08:00
NCBM 6458a4ad31 core/tools: embed truncate tokens in read_file (max_chars) 2026-08-11 15:02:37 +08:00
NCBM 00db7cdc7f core/tools: add get_truncated tool for chained resume 2026-08-11 14:59:39 +08:00
NCBM c96f669bcb core/tools: embed truncate tokens in fetch (offset param) 2026-08-11 14:55:55 +08:00
NCBM cb137c1dee core/tools: add truncate token module (chainable cursors) 2026-08-11 14:53:15 +08:00
NCBM d3a5200e0f core/tools: add wait tool (Enter to disturb) 2026-08-11 14:46:58 +08:00
NCBM df8f6bf959 core/tools: rename run_command_batch to run_argv_batch (steps/argv keys) 2026-08-04 21:40:25 +08:00
NCBM d698fbf06f core/tools: rename run_command to run_argv (argv param) 2026-08-04 21:38:20 +08:00
NCBM 23f7b4e299 core/tools: clear argv error when run_command gets a string 2026-08-04 20:35:22 +08:00
NCBM 3449f3a77d lint: drop mypy-style type ignore comments 2026-08-03 23:38:32 +08:00
NCBM 19ac4533d4 core/tools: invalidate lineno read state on file mutation 2026-08-01 01:22:30 +08:00
NCBM 56ac8d17d7 core/tools: restrict edit_lineno to lines read with line numbers 2026-08-01 01:21:00 +08:00
NCBM ef3594ad62 core/tools: change ask_user_choice and ask_user_form params from JSON strings to typed lists 2026-07-29 01:42:00 +08:00
NCBM f5b566b371 core/tools: add per-turn guard requiring lineno read before edit_lineno 2026-07-29 01:40:31 +08:00
NCBM 60f9c9b56d core/agent: danger classification overrides YOLO tag in confirm pipeline 2026-07-29 01:37:17 +08:00
NCBM 0ca92dfd7e core/config: networking ssrf_assume_public_cidrs for fetch Fake-IP 2026-07-24 20:20:30 +08:00
NCBM f5a667567d test/tools: cover fetch SSRF, methods, and user-agent 2026-07-24 19:08:10 +08:00
NCBM 03e04f9a38 core/cli: plugins list/enable/disable commands and /plugins slash 2026-07-24 16:44:44 +08:00
NCBM 1d718582ac core/tools: drop process workspace/todo globals; require bound state 2026-07-24 16:32:33 +08:00
NCBM 8baaa3f2e1 core/tools: hang workspace policy on InstanceState 2026-07-24 15:58:55 +08:00
NCBM 6c6cec05c4 core/cli: bind todo persist via session state, not process global 2026-07-24 15:49:57 +08:00
NCBM 7a3704edc1 core/tools: resolve_path accepts instance workspace root 2026-07-24 15:41:59 +08:00
NCBM 90c07061f3 core/tools: persist soft-confirm grants under session.data 2026-07-24 15:41:39 +08:00
NCBM 3d5380a3d4 core/tools: todo tools commit via session.data transactions 2026-07-24 15:31:26 +08:00
NCBM e82a226f91 core/tools: serialize domain objects on PersistentDataView commit 2026-07-24 15:31:06 +08:00
NCBM 96518974be core/tools: allowlisted entry-point plugin loader 2026-07-24 15:09:11 +08:00
NCBM 7253ca84dd core/tools: prefer instance workspace and session todo views 2026-07-24 15:02:52 +08:00
NCBM 12c8adda3a test/tools: catalog, grants, and async tool helpers 2026-07-24 14:57:03 +08:00
NCBM 7bdd9ff8b7 chore: pin ruff and basedpyright for prek and lockfile
Match prek additional_dependencies and pyproject dev pins to pdm.lock
(ruff==0.15.22, basedpyright==1.39.9). Format fix for ruff 0.15.22.
2026-07-20 04:35:26 +08:00
NCBM d6616d0da3 core/tools: timed human allow for denylisted commands
Denylist hits ask the user (default deny, timeout) instead of only hard
rejecting when a policy hook is installed. Independent of YOLO soft-confirm;
session grants skip re-prompt for the same basename. CLI installs the hook
via install_cli_limit_hooks.
2026-07-20 03:02:34 +08:00
NCBM a677e06af4 core/tools: add ask_into_pty for human-local PTY input
Prompt the human (optional no-echo secret) and write only to the PTY.
Tool results never include the answer so secrets stay off external APIs.
Empty/Ctrl-C cancel without writing; submit defaults to trailing newline.
2026-07-20 02:47:19 +08:00
NCBM d528f65c4c core/tools: edit_replace max_replaces and richer match messages
Default still replaces first match only. Report how many matches were
found, how many replaced, and remaining hits so agents can raise
max_replaces or narrow old_string.
2026-07-19 21:55:16 +08:00
NCBM a54fa534f3 test/tools: clean shell confirm format test 2026-07-19 13:05:43 +08:00
NCBM fa9f28687f test/tools: fix shell confirm format test syntax 2026-07-19 13:02:24 +08:00
NCBM 95f277eda7 core/tools: shell confirm argv uses $(command); full -c body indented 2026-07-19 13:01:06 +08:00
NCBM f13ea9f316 core/tools: soft-confirm file overwrite only, not partial edits 2026-07-19 03:05:01 +08:00
NCBM f51d11d46f core/tools/process: add run_command_batch with pipe_out and mix_stderr 2026-07-19 02:46:21 +08:00
NCBM 020e9215bf tools: new_temporary_workspace with cross-platform allowlist
Create scratch dirs under system temp (tempfile), allow absolute paths
under them without rebinding the project workspace or session. Cleanup
owned temps on chat exit. Cap 16 concurrent temps; sanitize prefix.
2026-07-18 18:16:06 +08:00