Commit Graph

378 Commits

Author SHA1 Message Date
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 b5014cd3e7 cli: pretty tree tool summary like read_file
Tool results for tree render as a single line: * Tree 'path' (N dirs,
M files, depth D) for markdown/decorated, dropping the depth for flat.
Counts and depth are parsed from the rendered output per format.
2026-08-15 17:09:57 +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 b16b2547b8 cli: /btw --tools [no|read|full] with read-only default
/btw now defaults to --tools=read: the side turn gets only READ_ONLY
tools under a read-only context (fetch restricted to GET), with the main
session view so read-only reads (todo_list) see real state. --tools=full
keeps the previous whole-registry clone with a fresh session; --tools=no
turns tools off. When tools are off, the default read silently falls back
to no tools, while an explicit --tools read|full errors as before.
2026-08-15 16:52:02 +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 1973ef93bb cli: keep Ctrl+C a plain KeyboardInterrupt under asyncio.run
asyncio.run (Runner) replaces SIGINT with its own handler when the
current one is signal.default_int_handler: the first Ctrl+C silently
cancels the main task (invisible at the REPL prompt, leaving the task
marked cancelled) and the second raises KeyboardInterrupt, so a Ctrl+D
exit after a cancel was cancelled mid-memory.close() (SQLAlchemy
CancelledError traceback) and the CLI died with "Aborted!".

Install a distinct KeyboardInterrupt-raising handler before asyncio.run
so Runner leaves SIGINT alone, and have run_cancellable restore the
previous handler after each turn (remove_signal_handler leaves SIG_DFL,
which would kill the process on a stray Ctrl+C between turns).
2026-08-11 21:13:17 +08:00
NCBM a197a67142 cli: keep REPL alive on stray Ctrl+C outside turn calls
After a turn the run_cancellable SIGINT handler is removed, so a Ctrl+C
landing between turns (echoing user text, expire_yolo_once, gaps between
statements, or re-entering _echo_interrupted) raised KeyboardInterrupt at
an arbitrary bytecode and escaped run_repl, killing the whole REPL. Wrap
the loop body in one try/except KeyboardInterrupt that re-prompts, and
make _echo_interrupted itself suppress a further interrupt.
2026-08-11 20:54:13 +08:00
NCBM 28a191cd79 core/agent: full reasoning_text.done replaces streamed fragments 2026-08-11 20:08:52 +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 6fdfb8398e core/agent: token-ify generic tool-result cap and compact shrinks 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 b5950bdb57 core/agent: drop get_truncated hint from token-less generic truncation 2026-08-11 18:21:45 +08:00
NCBM 65349b3c07 cli: prettier tool call summaries for read_file and todo tools 2026-08-11 15:38:07 +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 3fbf2dc388 core/agent: fix deepseek responses reasoning_content for tool calls 2026-08-11 15:27:01 +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 8cd456171c core/agent: drop increase-limit hint in favor of truncate tokens 2026-08-11 14:53:49 +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 fe7b75aad8 core/prompting: add line input with timeout 2026-08-11 14:44:34 +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 a834984bcc core/memory: merge session schema migrations by version 2026-08-01 02:47:08 +08:00
NCBM a198fa9d41 runtime: route DeepSeek convention=anthropic to Anthropic client 2026-08-01 02:31:21 +08:00
NCBM 439c24a1ce lmproto: add DeepSeek Anthropic client 2026-08-01 02:30:19 +08:00
NCBM 6e4d229f6f config: default deepseek anthropic convention url 2026-08-01 02:27:23 +08:00
NCBM f6072ce2a6 core/agent: interleave responses tool outputs after their calls 2026-08-01 02:16:48 +08:00
NCBM 4b7cc93917 runtime: route DeepSeek convention=responses to Responses client 2026-08-01 02:03:52 +08:00
NCBM bfafe74a6f core/agent: handle incomplete/failed Responses stream terminals 2026-08-01 02:03:02 +08:00
NCBM db6d2a83f4 lmproto: add DeepSeek Responses client 2026-08-01 02:01:06 +08:00
NCBM 8ad33af652 config: add typed DeepSeek convention field for API surface 2026-08-01 01:59:39 +08:00
NCBM a877dba8c1 cli/repl: keep second Ctrl+C inside the REPL 2026-08-01 01:45:10 +08:00
NCBM 3fe1c4cf91 core/agent: add model-friendly hint to truncated tool results 2026-08-01 01:42:17 +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 1d4e48f6f3 core/agent: normalize provider usage structs in token_usage_from_api 2026-08-01 01:09:12 +08:00
NCBM 626012e92f core/agent: unify provider finish_reason mapping 2026-08-01 01:05:26 +08:00
NCBM 5198a8da20 core/agent: align missing-terminal contract in messages dispatch 2026-08-01 01:05:17 +08:00
NCBM e29e66dbc7 core/agent: surface openai responses stream error events 2026-08-01 01:05:09 +08:00
NCBM 06f1b386a0 test/lmproto: cover anthropic messages client HTTP round-trips 2026-08-01 00:41:59 +08:00
NCBM 44a5f047ba core/runtime: plumb anthropic HTTP timeout 2026-08-01 00:34:41 +08:00