1661 Commits

Author SHA1 Message Date
Xubin Ren
9f96be6e9b fix(sandbox): mount media directory read-only inside bwrap sandbox 2026-04-05 19:08:38 +00:00
Xubin Ren
cef0f3f988 refactor: replace podman-seccomp.json with minimal cap_add, harden bwrap, add sandbox tests 2026-04-05 19:03:06 +00:00
Xubin Ren
a8707ca8f6 Merge origin/main into feat/best_skill_and_hook (resolve 4 conflicts)
Made-with: Cursor
2026-04-05 18:53:17 +00:00
Jack Lu
bcb8352235 refactor(agent): streamline hook method calls and enhance error logging
- Introduced a helper method `_for_each_hook_safe` to reduce code duplication in hook method implementations.
- Updated error logging to include the method name for better traceability.
- Improved the `SkillsLoader` class by adding a new method `_skill_entries_from_dir` to simplify skill listing logic.
- Enhanced skill loading and filtering logic, ensuring workspace skills take precedence over built-in ones.
- Added comprehensive tests for `SkillsLoader` to validate functionality and edge cases.
2026-04-06 02:51:10 +08:00
Xubin Ren
bb9da29eff test: add regression tests for private DM thread session key derivation
Made-with: Cursor
2026-04-06 02:44:21 +08:00
Ilya Semenov
0d6bc7fc11 fix(telegram): support threads in DMs 2026-04-06 02:44:21 +08:00
Xubin Ren
4b4d8b506d test: add regression test for DuckDuckGo asyncio.wait_for timeout guard
Made-with: Cursor
2026-04-06 02:21:51 +08:00
hoaresky
6bd2950b99 Fix: add asyncio timeout guard for DuckDuckGo search
DDGS's internal `timeout=10` relies on `requests` read-timeout semantics,
which only measure the gap between bytes — not total wall-clock time.
When the underlying HTTP connection enters CLOSE-WAIT or the server
dribbles data slowly, this timeout never fires, causing `ddgs.text` to
hang indefinitely via `asyncio.to_thread`.

Since `asyncio.to_thread` cannot cancel the underlying OS thread, the
agent's session lock is never released, blocking all subsequent messages
on the same session (observed: 8+ hours of unresponsiveness).

Fix:
- Add `timeout` field to `WebSearchConfig` (default: 30s, configurable
  via config.json or NANOBOT_TOOLS__WEB__SEARCH__TIMEOUT env var)
- Wrap `asyncio.to_thread` with `asyncio.wait_for` to enforce a hard
  wall-clock deadline

Closes #2804

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 02:21:51 +08:00
Xubin Ren
90caf5ce51 test: remove duplicate test_jina_422_falls_back_to_duckduckgo
The same test function name appeared twice; Python silently shadows the
first definition so it never ran.  Keep the version that also asserts
the request URL contains "s.jina.ai".

Made-with: Cursor
2026-04-06 02:06:00 +08:00
KimGLee
f422de8084 fix(web-search): fix Jina search format and fallback 2026-04-06 02:06:00 +08:00
Xubin Ren
acf652358c feat(dream): non-blocking /dream with progress feedback 2026-04-05 15:48:00 +00:00
chengyongru
401d1f57fa fix(dream): allow LLM to retry on tool errors instead of failing immediately
Dream Phase 2 uses fail_on_tool_error=True, which terminates the entire
run on the first tool error (e.g. old_text not found in edit_file).
Normal agent runs default to False so the LLM can self-correct and retry.
Dream should behave the same way.
2026-04-05 22:10:34 +08:00
chengyongru
5479a44691 fix: stop leaking reasoning_content to stream output
The streaming path in OpenAICompatProvider.chat_stream() was passing
reasoning_content deltas through on_content_delta(), causing model
internal reasoning to be displayed to the user alongside the actual
response content.

reasoning_content is already collected separately in _parse_chunks()
and stored in LLMResponse.reasoning_content for session history.
It should never be forwarded to the user-facing stream.
2026-04-05 17:27:14 +08:00
chengyongru
2cecaf0d5d fix(feishu): support video (media) download by converting type to 'file'
Feishu's GetMessageResource API only accepts 'image' or 'file' as the
type parameter. Video messages have msg_type='media', which was passed
through unchanged, causing error 234001 (Invalid request param). Now
both 'audio' and 'media' are converted to 'file' for download.
2026-04-05 16:53:05 +08:00
chengyongru
3003cb8465 test(feishu): add unit tests for reaction add/remove and auto-cleanup 2026-04-05 16:53:05 +08:00
Jiajun Xie
bb70b6158c feat: auto-remove reaction after message processing complete
- _add_reaction now returns reaction_id on success
- Add _remove_reaction_sync and _remove_reaction methods
- Remove reaction when stream ends to clear processing indicator
- Store reaction_id in metadata for later removal
2026-04-05 16:53:05 +08:00
Jiajun
7e1ae3eab4 feat(provider): add Qianfan provider support (#2699) 2026-04-05 16:52:37 +08:00
Flo
fce1e333b9 feat(telegram): render tool hints as expandable blockquotes (#2752) 2026-04-05 16:52:08 +08:00
Jiajun Xie
f86f226c17 fix(cli): prevent spinner ANSI escape codes from being printed verbatim
Fixes #2591

The "nanobot is thinking..." spinner was printing ANSI escape codes
literally in some terminals, causing garbled output like:
  ?[2K?[32m⠧?[0m ?[2mnanobot is thinking...?[0m

Root causes:
1. Console created without force_terminal=True, so Rich couldn't
   reliably detect terminal capabilities
2. Spinner continued running during user input prompt, conflicting
   with prompt_toolkit

Changes:
- Set force_terminal=True in _make_console() for proper ANSI handling
- Add stop_for_input() method to StreamRenderer
- Call stop_for_input() before reading user input in interactive mode
- Add tests for the new functionality
2026-04-05 16:50:49 +08:00
Xubin Ren
04a41e31ac
Merge PR #2754: feat(agent): add built-in grep and glob search tools
feat(agent): add built-in grep and glob search tools
2026-04-04 23:30:18 +08:00
Xubin Ren
33bef8d508 Merge remote-tracking branch 'origin/main' into feat/search-tools
Made-with: Cursor
2026-04-04 14:37:59 +00:00
Xubin Ren
f4983329c6 fix(docker): preserve both github ssh rewrite rules for npm install 2026-04-04 22:33:46 +08:00
Wenzhang-Chen
c9d6491814 fix(docker): rewrite github ssh git deps to https for npm build 2026-04-04 22:33:46 +08:00
Xubin Ren
1c1eee523d fix: secure whatsapp bridge with automatic local auth token 2026-04-04 14:16:46 +00:00
Xubin Ren
cf56d15bdf
Merge PR #2722: perf(cache): stabilize tool prefix caching under MCP tool churn
perf(cache): stabilize tool prefix caching under MCP tool churn
2026-04-04 21:57:15 +08:00
Xubin Ren
77a88446fb Merge remote-tracking branch 'origin/main' into pr-2722 2026-04-04 13:51:59 +00:00
Xubin Ren
17d9d74ccc fix(provider): omit temperature for GPT-5 models 2026-04-04 20:18:22 +08:00
Ubuntu
7dc8c9409c feat(providers): add GPT-5 model family support for OpenAI provider
Enable GPT-5 models (gpt-5, gpt-5.4, gpt-5.4-mini, etc.) to work
correctly with the OpenAI-compatible provider by:

- Setting `supports_max_completion_tokens=True` on the OpenAI provider
  spec so `max_completion_tokens` is sent instead of the deprecated
  `max_tokens` parameter that GPT-5 rejects.
- Adding `_supports_temperature()` to conditionally omit the
  `temperature` parameter for reasoning models (o1/o3/o4) and when
  `reasoning_effort` is active, matching the existing Azure provider
  behaviour.

Both changes are backward-compatible: older GPT-4 models continue to
work as before since `max_completion_tokens` is accepted by all recent
OpenAI models and temperature is only omitted when reasoning is active.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 20:18:22 +08:00
Xubin Ren
11c84f21a6 test(session): preserve reasoning_content in session history 2026-04-04 20:08:44 +08:00
Lingao Meng
519911456a test(provider): fix incorrect assertion in reasoning_content sanitize test
The test test_openai_compat_strips_message_level_reasoning_fields was
added in fbedf7a and incorrectly asserted that reasoning_content and
extra_content should be stripped from messages. This contradicts the
intent of b5302b6 which explicitly added these fields to _ALLOWED_MSG_KEYS
to preserve them through sanitization.

Rename the test and fix assertions to match the original design intent:
reasoning_content and extra_content at message level should be preserved,
and extra_content inside tool_calls should also be preserved.

Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
2026-04-04 20:08:44 +08:00
Lingao Meng
3f8eafc89a fix(provider): restore reasoning_content and extra_content in message sanitization
reasoning_content and extra_content were accidentally dropped from
_ALLOWED_MSG_KEYS.

Also fix session/manager.py to include reasoning_content when building
LLM messages from session history, so the field is not lost across
turns.

Without this fix, providers such as Kimi, emit reasoning_content in
assistant messages will have it stripped on the next request, breaking
multi-turn thinking mode.

Fixes: https://github.com/HKUDS/nanobot/issues/2777
Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
2026-04-04 20:08:44 +08:00
Xubin Ren
05fe7d4fb1 fix(tools): isolate decorated tool schemas and add regression tests 2026-04-04 19:58:44 +08:00
Jack Lu
e7798a28ee refactor(tools): streamline Tool class and add JSON Schema for parameters
Refactor Tool methods and type handling; introduce JSON Schema support for tool parameters (schema module, validation tests).

Made-with: Cursor
2026-04-04 19:58:44 +08:00
Xubin Ren
9ef5b1e145 fix: reset ssrf whitelist on config reload and document config refresh 2026-04-04 19:43:18 +08:00
04cb
5f08d61d8f fix(security): add ssrfWhitelist config to unblock Tailscale/CGNAT (#2669) 2026-04-04 19:43:18 +08:00
Xubin Ren
193eccdac7
Merge PR #2779: feat: integrate Jinja2 templating for agent responses and memory
feat: integrate Jinja2 templating for agent responses and memory
2026-04-04 19:17:56 +08:00
Xubin Ren
c3b4ebae53 refactor(agent): move internal prompts into packaged templates 2026-04-04 11:09:37 +00:00
Xubin Ren
7b852506ff fix(telegram): register Dream menu commands with Telegram-safe aliases
Use dream_log and dream_restore in Telegram's bot command menu so command registration succeeds, while still accepting the original dream-log and dream-restore forms in chat. Keep the internal command routing unchanged and add coverage for the alias normalization path.
2026-04-04 10:31:26 +00:00
Xubin Ren
549e5ea8e2 fix(telegram): shorten polling network errors 2026-04-04 10:26:58 +00:00
Xubin Ren
b9ee236ca1
Merge PR #2717: feat(memory): two-stage memory system with Dream consolidation
feat(memory): two-stage memory system with Dream consolidation
2026-04-04 18:18:43 +08:00
Xubin Ren
04419326ad fix(memory): migrate legacy HISTORY.md even when history.jsonl is empty 2026-04-04 10:11:53 +00:00
Xubin Ren
0a3a60a7a4 refactor(memory): simplify Dream config naming and rename gitstore module 2026-04-04 10:01:45 +00:00
Xubin Ren
a166fe8fc2 docs: clarify memory design and source-vs-release features 2026-04-04 09:34:37 +00:00
Xubin Ren
408a61b0e1 feat(memory): protect Dream cron and polish migration UX 2026-04-04 09:01:42 +00:00
Xubin Ren
6e896249c8 feat(memory): harden legacy history migration and Dream UX 2026-04-04 08:41:46 +00:00
Jack Lu
d436a1d678 feat: integrate Jinja2 templating for agent responses and memory consolidation
- Added Jinja2 template support for various agent responses, including identity, skills, and memory consolidation.
- Introduced new templates for evaluating notifications, handling subagent announcements, and managing platform policies.
- Updated the agent context and memory modules to utilize the new templating system for improved readability and maintainability.
- Added a new dependency on Jinja2 in pyproject.toml.
2026-04-04 14:18:22 +08:00
Xubin Ren
7e0c196797 fix(memory): repair Dream follow-up paths and move GitStore to utils
Made-with: Cursor
2026-04-04 04:49:42 +00:00
Xubin Ren
30ea048f19 Merge remote-tracking branch 'origin/main' into pr-2717-review 2026-04-04 04:42:52 +00:00
Xubin Ren
7229a81594 fix(providers): disable Azure SDK retries by default
Made-with: Cursor
2026-04-04 12:36:45 +08:00
pikaxinge
dbdf7e5955 fix: prevent retry amplification by disabling SDK retries 2026-04-04 12:36:45 +08:00