355 Commits

Author SHA1 Message Date
Xubin Ren
c9d4b7b905 Merge remote-tracking branch 'origin/main' into pr-2449
Made-with: Cursor

# Conflicts:
#	nanobot/utils/evaluator.py
2026-04-06 06:30:11 +00:00
Xubin Ren
897d5a7e58 test: add regression tests for JID suffix classification and LID cache
Made-with: Cursor
2026-04-06 06:19:06 +00:00
Xubin Ren
35dde8a30e refactor: unify voice transcription config across all channels
- Move transcriptionProvider to global channels config (not per-channel)
- ChannelManager auto-resolves API key from matching provider config
- BaseChannel gets transcription_provider attribute, no more getattr hack
- Remove redundant transcription fields from WhatsAppConfig
- Update README: document transcriptionProvider, update provider table

Made-with: Cursor
2026-04-06 06:07:30 +00:00
Xubin Ren
7b7a3e5748 fix: media_paths NameError, import order, add error logging and tests
- Move media_paths assignment before voice message handling to prevent
  NameError at runtime
- Fix broken import layout in transcription.py (httpx/loguru after class)
- Add error logging to OpenAITranscriptionProvider matching Groq style
- Add regression tests for voice transcription and no-media fallback

Made-with: Cursor
2026-04-06 06:01:14 +00:00
Xubin Ren
c88d97c652 fix: fall back to heuristic when bot open_id fetch fails
If _fetch_bot_open_id returns None the exact-match path would silently
disable all @mention detection. Restore the old heuristic as a fallback.
Add 6 unit tests for _is_bot_mentioned covering both paths.

Made-with: Cursor
2026-04-06 13:49:38 +08:00
Ben Lenarts
202938ae73 feat: support ${VAR} env var interpolation in config secrets
Allow config.json to reference environment variables via ${VAR_NAME}
syntax. Variables are resolved at runtime by resolve_config_env_vars(),
keeping the raw templates in the Pydantic model so save_config()
preserves them. This lets secrets live in a separate env file
(e.g. loaded by systemd EnvironmentFile=) instead of plain text
in config.json.
2026-04-06 13:43:26 +08:00
Xubin Ren
7ffd93f48d refactor: move search_usage to utils/searchusage, remove brave stub
- Rename agent/tools/search_usage.py → utils/searchusage.py
  (not an LLM tool, matches utils/ naming convention)
- Remove redundant _fetch_brave_usage — handled by else branch
- Move test to tests/utils/test_searchusage.py

Made-with: Cursor
2026-04-06 13:37:55 +08:00
whs
bc0ff7f214 feat(status): add web search provider usage to /status command 2026-04-06 13:37:55 +08:00
Xubin Ren
28e0a76b80 fix: path_append must not clobber login shell PATH
Seeding PATH in the env before bash -l caused /etc/profile
to skip its default PATH setup, breaking standard commands.
Move path_append to an inline export so the login shell
establishes a proper base PATH first.

Add regression test: ls still works when path_append is set.

Made-with: Cursor
2026-04-06 13:20:53 +08:00
Ben Lenarts
be6063a142 security: prevent exec tool from leaking process env vars to LLM
The exec tool previously passed the full parent process environment to
child processes, which meant LLM-generated commands could access secrets
stored in env vars (e.g. API keys from EnvironmentFile=).

Switch from subprocess_shell with inherited env to bash login shell
with a minimal environment (HOME, LANG, TERM only). The login shell
sources the user's profile for PATH setup, making the pathAppend
config option a fallback rather than the primary PATH mechanism.
2026-04-06 13:20:53 +08:00
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
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
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
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
3003cb8465 test(feishu): add unit tests for reaction add/remove and auto-cleanup 2026-04-05 16:53:05 +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
33bef8d508 Merge remote-tracking branch 'origin/main' into feat/search-tools
Made-with: Cursor
2026-04-04 14:37:59 +00:00
Xubin Ren
1c1eee523d fix: secure whatsapp bridge with automatic local auth token 2026-04-04 14:16:46 +00: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
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
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
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
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
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
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
Xubin Ren
91a9b7db24 Merge origin/main into fix/retry-after-robust
Made-with: Cursor
2026-04-03 19:07:30 +00:00
Xubin Ren
9840270f7f test(tools): cover media dir access under workspace restriction
Made-with: Cursor
2026-04-04 03:03:58 +08:00
imfondof
896d578677 fix(restart): show restart completion with elapsed time across channels 2026-04-04 02:21:42 +08:00
imfondof
ba7c07ccf2 fix(restart): send completion notice after channel is ready and unify runtime keys 2026-04-04 02:21:42 +08:00
Lingao Meng
a05f83da89 test(providers): cover reasoning_content extraction in OpenAI compat provider
Add regression tests for the non-streaming (_parse dict branch) and
streaming (_parse_chunks dict and SDK-object branches) paths that extract
reasoning_content, ensuring the field is populated when present and None
when absent.

Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
2026-04-04 02:09:57 +08:00
Xubin Ren
f409337fcf Merge remote-tracking branch 'origin/main' into pr-2646 2026-04-03 17:53:52 +00:00
daliu858
06989fd65b feat(qq): add configurable instant acknowledgment message (#2561)
Add ack_message config field to QQConfig (default: Processing...). When non-empty, sends an instant text reply before agent processing begins, filling the silence gap for users. Uses existing _send_text_only method; failure is logged but never blocks normal message handling.

Made-with: Cursor
2026-04-04 01:52:39 +08:00
Flo
49c40e6b31 feat(telegram): include author context in reply tags (#2605) (#2606)
* feat(telegram): include author context in reply tags (#2605)

* fix(telegram): handle missing attributes in reply_user safely
2026-04-04 01:52:39 +08:00