Commit Graph

87 Commits

Author SHA1 Message Date
NCBM 1fa41c9fde core/agent: run a hosted search as the surface's own tool
DeepSeek's Anthropic compat runs a hosted ``web_search`` itself and answers with
the blocks that search produced — ``thinking``, ``server_tool_use`` (the query)
and ``web_search_tool_result`` — so the content union that knew only text and
tool_use could not decode a live search turn. It carries them now, ``tools``
accepts the opaque server-tool dicts the surface declares, and
``web_search_tool_result.content`` stays loose on purpose: its
``web_search_result`` entries hold an ``encrypted_content`` the API demands back
unchanged (a trimmed result is answered with 422 "missing field
``encrypted_content``").

``provider_tools`` reached only the Responses surface, and the Anthropic one
wants its own definition of the same intent: a bare ``web_search`` becomes
``{type="web_search_20250305", name="web_search"}`` (the server tool Claude
declares and DeepSeek's compat reads, keeping a ``max_uses`` cap or any other
key), merged after the local function tools.

Such a tool is the server's: it streams ``input_json_delta`` fragments like a
call, and reading them as one asked the registry for a tool the server had
already run. Block types are now tracked, so only a ``tool_use`` block becomes a
tool call; the search blocks and ``thinking`` are skipped by the response
mapping (the answer the model wrote already used them) and never executed.
2026-10-06 23:35:46 +08:00
NCBM c06fb57e72 core/agent: return each round's reasoning in the Responses input
A request carrying `tools` must return every round's chain-of-thought — "必须完整
回传 `reasoning_content` … 即使该轮模型未实际进行工具调用" — and the API merges a
`reasoning` item into the assistant message its round forms: a missing item and
an empty `reasoning_text` are both answered with "The `reasoning_text` in the
thinking mode must be passed back to the API". Each round now goes back as its
reasoning, its text, then its calls, with a blank line standing in when the
round kept none (a `rollback_tail` carrier, a forged todo call, the seed a
compacted session starts with) — never words of the bridge's own for a round
that may genuinely have reasoned nothing. A round's calls stay contiguous ahead
of their outputs: an interleaved batch reads as a second round without
reasoning and is rejected the same way, and an output recorded after another
item moves up beside its own call.

The reasoning is read back from the item's `content` parts, the only part the
API documents for `reasoning` items (`summary` and `encrypted_content` are not
supported).
2026-10-06 23:23:18 +08:00
NCBM 932b4f0a7f core/agent: keep a rolled-back turn's reasoning with its calls
A failed turn keeps the calls that already ran as a bare pairing carrier, and
clipping the chain-of-thought off that carrier sent the call back to the API
with no reasoning at all — thinking mode refuses a call whose reasoning never
came back. The carrier keeps the reasoning and drops only the text.
2026-10-06 23:23:12 +08:00
NCBM ec5340bdce config: rename the DeepSeek flash model to deepseek-flash
DeepSeek dropped the `v4` prefix from its flash model, and the old id stays
valid only as a compatibility alias. Seed the default catalog with the current
name so a provider that omits `models` no longer offers a deprecated id, and
follow the rename in the wire fixtures and the minimal config template. An
explicit `deepseek-v4-flash` in TOML still passes through unchanged.
2026-10-06 21:22:35 +08:00
NCBM fb8ef88d9f core/agent: send the resolved reasoning effort with each request 2026-10-06 21:11:28 +08:00
NCBM 7d9b979604 core/agent: record every tool result before yielding them
A caller that goes away mid-batch (cancel, display error) left the results of
tools that had already run out of history, so the retry ran them again. Append
the collected results first, then emit the events.
2026-10-06 20:33:30 +08:00
NCBM cecd5e5ae3 core/agent: keep executed tool results when a failed turn is rolled back
A tool batch counted as committed only once every call had its result, so a
batch cut short was dropped whole and the retry ran tools that had already
had effects. Keep the calls that did report a result: their assistant row
stays as the pairing carrier (a request must answer every tool_calls id),
without the text of the unfinished turn, and the calls without a result are
absent so the retry re-issues them instead of assuming they ran. The kept
rows go to the store right away, and a failed rollback write is not allowed
to mask the failure being rolled back.
2026-10-06 20:32:09 +08:00
NCBM de03e5932b core/tools: rename grep_files to regex_files (regex pattern) 2026-09-22 23:22:13 +08:00
NCBM f94d9a6f49 agent/tools: report missing required arguments before running 2026-09-19 09:50:13 +08:00
NCBM 8b9233090f cli/btw: tell the model side questions are unsaved and tool-scoped 2026-09-19 09:24:38 +08:00
NCBM bd18a88370 agent/notices: host notices as trailing developer messages 2026-09-19 09:15:13 +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 28a191cd79 core/agent: full reasoning_text.done replaces streamed fragments 2026-08-11 20:08:52 +08:00
NCBM 6fdfb8398e core/agent: token-ify generic tool-result cap and compact shrinks 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 3fbf2dc388 core/agent: fix deepseek responses reasoning_content for tool calls 2026-08-11 15:27:01 +08:00
NCBM 8cd456171c core/agent: drop increase-limit hint in favor of truncate tokens 2026-08-11 14:53:49 +08:00
NCBM 3449f3a77d lint: drop mypy-style type ignore comments 2026-08-03 23:38:32 +08:00
NCBM f6072ce2a6 core/agent: interleave responses tool outputs after their calls 2026-08-01 02:16:48 +08:00
NCBM bfafe74a6f core/agent: handle incomplete/failed Responses stream terminals 2026-08-01 02:03:02 +08:00
NCBM 3fe1c4cf91 core/agent: add model-friendly hint to truncated tool results 2026-08-01 01:42:17 +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 3a671f73ea core/agent: wire anthropic messages bridge and dispatch 2026-08-01 00:34:32 +08:00
NCBM de7cae83e4 core/agent: restore OpenAI responses dispatch and provider_tools 2026-08-01 00:34:15 +08:00
NCBM ad58d6cdc6 lint: drop dead code that blocks basedpyright (unused helper and import) 2026-08-01 00:33:25 +08:00
NCBM 904ac3d982 core/agent: remove turn-start todo nag -- nag only fires after complete turn 2026-07-29 01:07:59 +08:00
NCBM f60fd876c6 test: update for kind-based dispatch and remove ResponsesChatClient references 2026-07-29 00:46:08 +08:00
NCBM 0ce9ed84a0 core/agent: suppress end-of-turn todo nag on retry when turn-start pair survived 2026-07-28 23:52:06 +08:00
NCBM a83c67ba6d test/agent: cover synthetic_tool todo nag retry detection
Adds 7 unit tests for _synthetic_todo_pair_after and committed_prefix_end
with synthetic todo nag pairs: survival across rollback, detection at
correct index, immunity to real tool calls, and multiple rollbacks.

These directly verify the guard that prevents duplicate turn-start
nag injection on /retry when a synthetic pair from a previous failed
attempt survived rollback (committed tool batch).
2026-07-28 23:45:27 +08:00
NCBM e3e0cf2080 core/agent: append-only directive checkpoints on token bands 2026-07-24 19:40:37 +08:00
NCBM 908e68665b core/agent: run_aside side turns; CLI /btw with --tools 2026-07-24 17:42:34 +08:00
NCBM ac3230647a test/agent: bind todo tools via SessionState instead of process global 2026-07-24 16:00:17 +08:00
NCBM 12c8adda3a test/tools: catalog, grants, and async tool helpers 2026-07-24 14:57:03 +08:00
NCBM b51d4780ab core/agent: refresh synthetic_tool todo nags to live stack 2026-07-21 22:42:27 +08:00
NCBM 879e28ea4c core/agent: synthetic_tool review always when stack non-empty
needs_review is true for any non-empty stack so end-of-turn inject
keeps firing under synthetic_tool. Message history keeps only the last
todo-nag tool pair (dedupe by todo-nag- tool_call_id).
2026-07-20 16:20:01 +08:00
NCBM 59017fd61b core/agent: synthetic_tool nag uses real todo_list render body
developer/user keep OPEN WORK prose; synthetic_tool injects forged
todo_list call with stack.render() only so the result matches a real
tool output.
2026-07-20 04:10:21 +08:00
NCBM 2e6cb3834a core/agent: drop system todo nag; emit events for synthetic_tool
Remove system strategy (legacy maps to developer). synthetic_tool still
forges the call but uses real stack text as the tool result, and now
yields ToolCall/Result events so the CLI flushes and does not glue nag
text to the next assistant stream.
2026-07-20 03:55:50 +08:00
NCBM f6d14ed549 core/agent: configurable todo nag strategies
Add [agent] todo_nag_strategy: developer (default), system, user,
synthetic_tool (forged todo_list pair), or none. Shared inject helper
used for turn-start and end-of-turn nags; CLI wires agent config.
2026-07-20 03:33:02 +08:00
NCBM a4ab11c9a2 core/agent: stronger open-work signals in todo stack prompts
Split tags: [TODO OPEN WORK] for pending/in_progress (undone work) vs
[TODO HYGIENE] for all-terminal leftover groups. End-of-turn review lists
open titles; tool docs stress open items as unfinished work.
2026-07-20 03:17:44 +08:00
NCBM e1e4df0f3f core/agent: strengthen todo prompts when stack not empty
Inject turn-start [TODO REMINDER] for non-empty stacks; rewrite end-of-turn
[TODO OPEN] copy so open items read as unfinished work. needs_review now
always true while open items remain (even if todo_* ran this turn); terminal-only
stacks still need review if untouched. Update tool docs and tests.
2026-07-19 20:34:01 +08:00
NCBM 9a9c808ea0 core/agent: agent-facing [TODO OPEN] review nag 2026-07-18 16:48:20 +08:00
NCBM c8a0aeda8d core/agent: reuse todo ids after clear/pop; todo_push titles as array 2026-07-18 16:09:09 +08:00
NCBM a7166d863b core/agent: todo stack is LIFO of task groups, not per-task push
push(titles) creates one group of siblings; pop removes the whole top
group. Matches breakdown: push[T1,T2] → push[T1.1,T1.2] → pop → push[T2.1].
2026-07-18 14:47:38 +08:00
NCBM 9b38a3b333 ci/lint: prek commit gateway (ruff check/format + basedpyright)
Add prek.toml so git commit runs ruff-pre-commit (fix then format) and
pdm-based basedpyright. Document install/install-hook; clear type warnings
that made basedpyright exit non-zero under recommended mode.
2026-07-18 14:10:04 +08:00
NCBM 39f9a7f636 ci/lint: ruff format todo stack and related CLI/agent files 2026-07-18 13:22:42 +08:00
NCBM 7f49c47105 core/agent: todo is a real LIFO stack (not a queue or frame list)
TOP = last element only for pop; multi-push puts first title on top for DFS
breakdown. Dropped nested-frame model; migrate old frames JSON to flat stack.
2026-07-18 13:20:37 +08:00
NCBM c95d1df028 core/agent: nested todo frames for hierarchical push/pop breakdown
push of one or more titles opens a new frame (siblings at one depth);
pop leaves the frame. Supports T1,T2 → T1.1,T1.2 → pop → T2.1 pattern.
Legacy flat session JSON migrates to a single root frame.
2026-07-18 13:15:57 +08:00