Commit Graph
1282 Commits
Author SHA1 Message Date
chengyongruandXubin Ren 3460ca3cb9 fix(agent): gate microcompaction on context pressure
Extract model-facing context governance from AgentRunner.

Only compact in-flight tool results when the model request is over budget, keep compacted IDs stable within a turn, and allow the newest result to be compacted as a last resort when it is the remaining source of overflow.
2026-06-27 11:04:41 +08:00
chengyongruandXubin Ren 9b45fc1172 fix(session): remove message time replay prefixes 2026-06-27 11:04:36 +08:00
chengyongruandXubin Ren 8656549129 test: cover exec login default public path
maintainer edit: add a regression test for the public ExecTool.execute path so omitted login stays non-login by default, and update the Unix environment docstring to match the new explicit login behavior.
2026-06-27 11:04:31 +08:00
axelray-devandXubin Ren 4c1f127549 test: update login-shell assertion for new default=False 2026-06-27 11:04:31 +08:00
chengyongruandXubin Ren 64901be67f test: harden webui and gateway checks 2026-06-27 11:04:11 +08:00
axelray-devandXubin Ren 851a0ff50c fix: make subagent fail_on_tool_error configurable (#4198)
Add fail_on_tool_error to AgentDefaults and wire it through
AgentLoop -> SubagentManager -> AgentRunSpec.

Previously hardcoded to True in SubagentManager._run_subagent.
Now configurable via config.json with default True for backward
compatibility. When set to False, subagents can retry on minor
tool errors instead of immediately failing.

Changes:
- nanobot/config/schema.py: add fail_on_tool_error field (default True)
- nanobot/agent/subagent.py: accept and forward fail_on_tool_error
- nanobot/agent/loop.py: pass config through to SubagentManager
- tests/agent/test_subagent.py: add regression test

Signed-off-by: axelray-dev <110029405+axelray-dev@users.noreply.github.com>
2026-06-25 22:53:36 +08:00
axelray-devandXubin Ren d1ae73a8a8 fix: add clear error message for invalid thinking_style values
Widen thinking_style from Literal to str | None and add a
@field_validator that produces a helpful error message listing
valid options when an invalid value is provided.

Addresses the review feedback on #4482.
2026-06-25 22:53:15 +08:00
axelray-devandXubin Ren c661012754 fix: coalesce None thinking_style to empty string in provider creation
ProviderConfig.thinking_style defaults to None (Optional field), but
create_dynamic_spec expects a string. Coalesce None to "" at all call
sites (factory.py, settings_api.py) and fix the test assertion to
expect None from the config default.
2026-06-25 22:53:15 +08:00
axelray-devandXubin Ren ceae6d7b61 fix: allow custom provider to configure thinking style (#4429) 2026-06-25 22:53:15 +08:00
Xubin Ren 34f776b48b test(cli): lock disabled dream cursor advancement 2026-06-25 22:53:10 +08:00
axelray-devandXubin Ren 6c880a6691 fix: advance dream cursor when Dream is disabled to prevent prompt bloat (#4242)
When dream.enabled is false, the Dream cron job never runs, so the
dream cursor (.dream_cursor) stays at its initial value (0). This
causes read_recent_history_for_prompt() to treat every history entry
as unprocessed, injecting the full chat history into every system
prompt and growing without bound.

Fix: fast-forward the dream cursor to the latest history entry at
gateway startup when Dream is disabled.
2026-06-25 22:53:10 +08:00
9354b80a6e fix(cli): show search engines (incl. Keenable) in onboard wizard
The onboard wizard dispatched field handlers by bare field name, so
WebSearchConfig.provider was hijacked by the LLM-provider handler and
showed LLM providers instead of search engines. Keenable was also never
wired into the CLI wizard when it landed in the WebUI.

- Add a single source of truth for selectable search providers
  (SEARCH_PROVIDER_OPTIONS in web.py); WebUI settings now import it.
- Add a WebSearchConfig-aware search-provider picker to the wizard and
  resolve handlers by (model type, field name) so the LLM and search
  provider fields no longer collide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:52:50 +08:00
Max HsuandXubin Ren 638af123ba fix(dingtalk): preserve richText formatting and set HTTP client timeout
richText messages only kept rich_text_list items whose type was
"text", so bold/italic/inlineCode/pre segments were silently dropped;
a message made entirely of formatted segments produced empty content
and fell through to the "unsupported message type: richText" warning.
Now any item carrying text is kept (matching the SDK's own
get_text_list, which keys off the "text" field) and its type is mapped
to Markdown so the formatting survives into the agent's context.

Text and downloadCode within a rich-text item are handled
independently (the SDK treats them as separate via get_text_list /
get_image_list), so an item carrying both a caption and an attachment
no longer drops the file.

The shared httpx.AsyncClient was created without a timeout, so all
requests (including large file/image downloads) used httpx's 5s
default and hit ConnectTimeout/ReadTimeout on uploads. Set an explicit
httpx.Timeout (connect=10s, read/write=30s).

Adds regression tests for formatted-segment preservation, the
all-formatted no-drop case, the text+downloadCode item, and the client
timeout configuration.

Closes #4497
2026-06-25 22:52:45 +08:00
michaelxerandXubin Ren 246ea8ef61 fix(tools): gate MCP resource and prompt registration behind enabledTools
The enabledTools allowlist was only enforced for MCP tools returned by
session.list_tools(). Resources and prompts from session.list_resources()
and session.list_prompts() were registered unconditionally, allowing a
deny-all or restrictive enabledTools config to leak resource and prompt
capabilities to the model.

Now resources and prompts are only registered when allow_all_tools is
true (default ["*"] wildcard). Any explicit tool restriction — including
enabledTools: [] (deny-all) or a list of specific tool names — also
blocks resource and prompt registration from that server.

Fixes #4435
2026-06-25 16:10:37 +08:00
chengyongruandXubin Ren e92899607a fix: make Telegram rich messages opt in
maintainer edit: Telegram Web cannot render sendRichMessage payloads, so keep the rich path available only for explicit opt-in instead of enabling it by default.
2026-06-25 16:10:33 +08:00
axelray-devandXubin Ren c930aa3713 fix: add rich_messages config to disable sendRichMessage for Telegram Web (#4488) 2026-06-25 16:10:33 +08:00
chengyongruandXubin Ren 4378944459 test: speed up test suite 2026-06-25 16:10:28 +08:00
chengyongruandXubin Ren 943191f0c0 fix(webui): keep multi-file apply_patch edits 2026-06-24 20:04:39 +08:00
Xubin Ren c915e98c15 test: cover archived heartbeat target selection 2026-06-24 15:45:49 +08:00
Heng Wei BinandXubin Ren de4009efbd fix: exclude archived keys in heartbeat & fallback missing session timestamps 2026-06-24 15:45:49 +08:00
hyoukadevandXubin Ren 9c6eaf0bed test: deduplicate proxy value and construct tool via constructor
- Use a local variable for the proxy URL instead of hardcoding it twice
- Pass proxy through the WebSearchTool constructor instead of mutating
  after instantiation (matches real usage path)
- Add assertion that timeout is still forwarded correctly
- Use generic mock data instead of test-specific strings
2026-06-24 15:45:44 +08:00
hyoukadevandXubin Ren c66a0217d2 fix(web): pass proxy to DDGS client
The DuckDuckGo search provider instantiated DDGS(timeout=10) without
passing the configured proxy, making web_search unusable in environments
that require a proxy (e.g. behind GFW). DDGS supports a proxy parameter
and the proxy value is already available as self.proxy — it was simply
not forwarded.

Add a test verifying the proxy kwarg is forwarded to DDGS.
2026-06-24 15:45:44 +08:00
yorkhellenandXubin Ren 319791cd10 fix(config): preserve dream cron when saving config 2026-06-24 15:45:39 +08:00
chengyongruandXubin Ren 98dd883ce8 fix: buffer split reasoning wrapper deltas
maintainer edit: native reasoning streams can split <thinking> wrapper tags across chunks. Buffer the stream and emit only cleaned incremental reasoning so raw partial tags do not reach WebUI.
2026-06-24 15:45:34 +08:00
ZhouandXubin Ren 35bd1be109 fix: ignore non-string reasoning wrappers 2026-06-24 15:45:34 +08:00
ZhouandXubin Ren 596bf5398c test: cover empty thinking marker streaming 2026-06-24 15:45:34 +08:00
ZhouandXubin Ren 523bb928bf fix: normalize thinking tags in reasoning output 2026-06-24 15:45:34 +08:00
Xubin Ren f9afc9389b fix(providers): apply Kimi Coding default headers 2026-06-24 10:43:16 +08:00
chengyongruandXubin Ren c55f7ec5bb style: trim pairing sender-id comments
maintainer edit: remove redundant explanatory comments from the focused sender-id normalization tests and store change without changing behavior.
2026-06-24 10:29:58 +08:00
w.antarandXubin Ren d7f868b832 fix(pairing): also coerce sender_id in approve_code() 2026-06-24 10:29:58 +08:00
w.antarandXubin Ren d481d5fb1a fix(pairing): normalize sender IDs to str in the pairing store 2026-06-24 10:29:58 +08:00
chengyongruandXubin Ren bc1df49201 fix(gateway): handle lifecycle edge cases 2026-06-24 10:29:08 +08:00
chengyongruandXubin Ren 6d989de336 docs: document OpenCode provider setup
Maintainer edit: document OpenCode Zen and Go configuration, keep their registry entries with gateway providers, and add focused provider registration tests.
2026-06-24 10:25:12 +08:00
chengyongruandXubin Ren 0e9861558a fix: keep duplicate id repair in Anthropic provider
maintainer edit: move duplicate tool_use history repair out of AgentRunner and into Anthropic message conversion, reusing the OpenAI-compatible queue-mapping approach locally without broadening the shared runner path.
2026-06-24 10:21:48 +08:00
chengyongruandXubin Ren 853aecdb97 fix: preserve duplicate-id tool calls
maintainer edit: remap duplicate tool_use/tool_call ids instead of dropping later calls, so Anthropic-compatible providers that reuse ids for distinct parallel tool calls keep all requested work while still sending unique ids.
2026-06-24 10:21:48 +08:00
Teddy YanandXubin Ren 6b8e832ba5 fix: address PR review comments - rename _dedup to _dedupe and fix ID storage consistency 2026-06-24 10:21:48 +08:00
6689e2d377 fix(providers): dedupe tool_use ids to prevent Anthropic 400s
Anthropic rejects any request where two tool_use blocks share an id
("messages.N.content.M: tool_use ids must be unique"). A mis-assembled
stream could surface the same tool_use block twice in one assistant turn;
the runner persisted it verbatim, so the malformed message was re-sent on
every subsequent turn and permanently bricked the session — the agent
silently stopped replying.

Fix at two layers:
- AnthropicProvider._parse_response: drop duplicate tool_use ids (keep
  first) as the response enters nanobot, so corruption is never persisted.
- AgentRunner._dedup_tool_calls: a new context-governance pass that dedupes
  assistant tool_calls and tool results by id before each send, healing any
  history that was already corrupted.

Add regression tests covering both the dedup and the no-op fast path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 10:21:48 +08:00
Xubin Ren 90703002c9 fix(gateway): restore tty signal mode for ctrl-c 2026-06-22 23:20:45 +08:00
Xubin Ren e624943bac fix(gateway): tolerate cancelled channel tasks during shutdown 2026-06-22 23:20:45 +08:00
Xubin Ren 747104c9cc fix(gateway): make foreground shutdown responsive 2026-06-22 22:00:07 +08:00
Xubin Ren fbaa85117b fix: close MCP stdio transports from agent task 2026-06-22 18:59:50 +08:00
chengyongruandXubin Ren 0db9fbe250 chore: default context window to 200k 2026-06-22 18:33:49 +08:00
chengyongruandXubin Ren 991422a328 refactor: simplify CLI Apps route await 2026-06-22 17:14:13 +08:00
chengyongruandXubin Ren a67285e6a2 fix: use async CLI Apps catalog refresh
Replace the manual thread-based catalog refresh with an asyncio task and async HTTP catalog fetches so the Settings route stays within the async WebUI model.
2026-06-22 17:14:13 +08:00
chengyongruandXubin Ren dd2cb4ca91 fix: refresh optional CLI Apps catalogs
maintainer edit: CLI Apps settings now treats optional catalog caches as refresh candidates without blocking the initial payload, and pending polling stops when refresh is throttled instead of running indefinitely.
2026-06-22 17:14:13 +08:00
chengyongruandXubin Ren 1cd5a0e029 fix: keep refreshable Codex OAuth configured
maintainer edit: Settings reads local Codex token storage to avoid refresh work, so expired access tokens with refresh credentials still need to count as configured until real provider use refreshes them.
2026-06-22 17:14:13 +08:00
chengyongruandXubin Ren b8abe5542c Avoid blocking settings on CLI Apps catalog refresh 2026-06-22 17:14:13 +08:00
chengyongruandXubin Ren 7b153c5aa9 Avoid refreshing Codex token in settings 2026-06-22 17:14:13 +08:00
Xubin Ren e3c9aff41e feat(gateway): add background and service controls 2026-06-22 14:48:49 +08:00
Xubin Ren 351aabd512 fix: polish onboard wizard keyboard navigation 2026-06-22 13:04:05 +08:00