Commit Graph

180 Commits

Author SHA1 Message Date
Xubin Ren
728d4e88a9 fix(providers): lazy-load provider exports 2026-03-18 22:01:29 +08:00
Xubin Ren
5bd1c9ab8f fix(cron): preserve exact intervals in list output 2026-03-18 12:39:06 +08:00
PJ Hoberman
12aa7d7aca test(cron): add unit tests for _format_timing and _format_state helpers
Tests the helpers directly without needing CronService, covering all
schedule kinds, edge cases (missing fields, unknown status), and
combined state output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:39:06 +08:00
PJ Hoberman
5d8c5d2d25 style(test): fix import sorting and remove unused imports
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:39:06 +08:00
PJ Hoberman
787e667dc9 test(cron): add tests for _list_jobs() schedule and state formatting
Covers all three schedule kinds (cron/every/at), human-readable interval
formatting, run state display (last run, status, errors, next run),
and disabled job filtering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:39:06 +08:00
Xubin Ren
8cf11a0291 fix: preserve image paths in fallback and session history 2026-03-17 22:37:09 +08:00
Xubin Ren
7086f57d05 test(feishu): cover media msg_type mapping 2026-03-17 17:05:13 +08:00
Xubin Ren
41d59c3b89 test(feishu): cover heading and table markdown rendering 2026-03-17 16:51:02 +08:00
Xubin Ren
91ca82035a feat(slack): add default done reaction on completion 2026-03-17 16:19:08 +08:00
Xubin Ren
49fc50b1e6 test(custom): cover empty choices response handling 2026-03-17 14:24:55 +08:00
Xubin Ren
b2a550176e feat(onboard): align setup with config and workspace flags 2026-03-17 05:42:49 +00:00
Xubin Ren
40a022afd9 fix(onboard): use configured workspace path on setup 2026-03-17 05:01:34 +00:00
Xubin Ren
db37ecbfd2 fix(custom): support extraHeaders for OpenAI-compatible endpoints 2026-03-17 04:28:24 +00:00
Xubin Ren
2eceb6ce8a fix(cli): pause spinner cleanly before printing progress output 2026-03-16 22:17:29 +08:00
Xubin Ren
92f3d5a8b3 fix: keep truncated session history tool-call consistent 2026-03-16 17:25:30 +08:00
rise
db276bdf2b Fix orphan tool results in truncated session history 2026-03-16 17:25:30 +08:00
Xubin Ren
46b19b15e1 perf: background post-response memory consolidation for faster replies 2026-03-16 09:01:11 +00:00
Xubin Ren
6d63e22e86 Merge remote-tracking branch 'origin/main' into pr-1961
Made-with: Cursor

# Conflicts:
#	.gitignore
2026-03-16 08:47:28 +00:00
Xubin Ren
b29275a1d2 refactor(/new): background archival with guaranteed persistence
Replace fire-and-forget consolidation with archive_messages(), which
retries until the raw-dump fallback triggers — making it effectively
infallible. /new now clears the session immediately and archives in
the background. Pending archive tasks are drained on shutdown via
close_mcp() so no data is lost on process exit.
2026-03-16 16:40:09 +08:00
chengyongru
9820c87537 fix(loop): restore /new immediate return with safe background consolidation
PR #881 (commit 755e424) fixed the race condition between normal consolidation
and /new consolidation, but did so by making /new wait for consolidation to
complete before returning. This hurts user experience - /new should be instant.

This PR restores the original immediate-return behavior while keeping safety:

1. **Immediate return**: Session clears and user sees "New session started" right away
2. **Background archival**: Consolidation runs in background via asyncio.create_task
3. **Serialized consolidation**: Uses the same lock as normal consolidation via
   `memory_consolidator.get_lock()` to prevent concurrent writes

If consolidation fails after session clear, archived messages may be lost.
This is acceptable because:
- User already sees the new session and can continue working
- Failure is logged for debugging
- The alternative (blocking /new on every call) hurts UX for all users
2026-03-16 16:40:09 +08:00
Xubin Ren
6e2b6396a4 security: add SSRF protection, untrusted content marking, and internal URL blocking 2026-03-16 15:05:26 +08:00
Xubin Ren
5d1528a5f3 fix(heartbeat): inject shared current time context into phase 1 2026-03-16 10:52:26 +08:00
who96
0dda2b23e6 fix(heartbeat): inject current datetime into Phase 1 prompt
Phase 1 _decide() now includes "Current date/time: YYYY-MM-DD HH:MM UTC"
in the user prompt and instructs the LLM to use it for time-aware scheduling.
Without this, the LLM defaults to 'run' for any task description regardless
of whether it is actually due, defeating Phase 1's pre-screening purpose.

Closes #1929
2026-03-16 10:52:26 +08:00
Meng Yuhang
f9ba6197de fix: save DingTalk downloaded files to media dir instead of /tmp 2026-03-15 23:21:22 +08:00
Meng Yuhang
34358eabc9 feat: support file/image/richText message receiving for DingTalk 2026-03-15 23:21:22 +08:00
Xubin Ren
d684fec27a Replace load_skill tool with read_file extra_allowed_dirs for builtin skills access
Instead of adding a separate load_skill tool to bypass workspace restrictions,
extend ReadFileTool with extra_allowed_dirs so it can read builtin skill paths
while keeping write/edit tools locked to the workspace. Fixes the original issue
for both main agent and subagents.

Made-with: Cursor
2026-03-15 23:21:02 +08:00
Xubin Ren
c4628038c6 fix: handle image_url rejection by retrying without images
Replace the static provider-level supports_vision check with a
reactive fallback: when a model returns an image-unsupported error,
strip image_url blocks from messages and retry once. This avoids
maintaining an inaccurate vision capability table and correctly
handles gateway/unknown model scenarios.

Also extract _safe_chat() to deduplicate try/except boilerplate
in chat_with_retry().
2026-03-15 22:32:34 +08:00
Xubin Ren
196e0ddbb6 fix(openrouter): revert custom_llm_provider, always apply gateway prefix 2026-03-15 10:52:36 +08:00
Xubin Ren
350d110fb9 fix(openrouter): remove litellm_prefix to prevent double-prefixed model names
With custom_llm_provider kwarg handling routing, the openrouter/ prefix
caused model names like anthropic/claude-sonnet-4-6 to become
openrouter/anthropic/claude-sonnet-4-6, which OpenRouter API rejects.
2026-03-15 10:52:36 +08:00
Xubin Ren
5ccf350db1 test(litellm_kwargs): add regression tests for PR #2026 OpenRouter kwargs injection 2026-03-15 10:52:36 +08:00
Xubin Ren
19ae7a167e fix(feishu): avoid breaking tool hint formatting and think stripping 2026-03-14 15:40:53 +00:00
Xubin Ren
44af7eca3f merge: resolve PR #1966 conflicts with main 2026-03-14 15:32:19 +00:00
Xubin Ren
a4f6b7d978 merge: resolve PR #1963 conflicts with main 2026-03-14 14:00:00 +00:00
Xubin Ren
86cfbce077 Merge remote-tracking branch 'origin/main' into pr-1796 2026-03-14 13:11:56 +00:00
Xubin Ren
61f0923c66 fix(telegram): include restart in help text 2026-03-14 10:45:37 +00:00
Xubin Ren
a1241ee68c fix(mcp): clarify enabledTools filtering semantics
- support both raw and wrapped MCP tool names
- treat [\"*\"] as all tools and [] as no tools
- add warnings, tests, and README docs for enabledTools
2026-03-14 18:33:48 +08:00
Xubin Ren
411b059dd2 refactor: replace <SILENT_OK> with structured post-run evaluation
- Add nanobot/utils/evaluator.py: lightweight LLM tool-call to decide notify/silent after background task execution
- Remove magic token injection from heartbeat and cron prompts
- Clean session history (no more <SILENT_OK> pollution)
- Add tests for evaluator and updated heartbeat three-phase flow
2026-03-14 17:41:08 +08:00
Protocol Zero
c9cc160600 merge: resolve PR #1796 conflicts with main
Merge the latest main branch into the Telegram media filename fix and keep the file_unique_id-based download path on top of the refactored media handling and newer Telegram tests.

Made-with: Cursor
2026-03-14 08:33:56 +00:00
Xubin Ren
af65145bc8 fix(qq): add configurable message format and onboard backfill 2026-03-14 08:25:44 +00:00
chengyongru
91d95f139e fix: cross-platform test compatibility
- test_channel_plugins: fix assertion logic for discoverable channels
- test_filesystem_tools: normalize path separators for Windows
- test_tool_validation: use python to generate output, avoid cmd line limits
2026-03-14 16:13:38 +08:00
Xubin Ren
dbdb43faff feat: channel plugin architecture with decoupled configs
- Add plugin discovery via Python entry_points (group: nanobot.channels)
- Move 11 channel Config classes from schema.py into their own channel modules
- ChannelsConfig now only keeps send_progress + send_tool_hints (extra=allow)
- Each built-in channel parses dict->Pydantic in __init__, zero internal changes
- All channels implement default_config() for onboard auto-population
- nanobot onboard injects defaults for all discovered channels (built-in + plugins)
- Add nanobot plugins list CLI command
- Add Channel Plugin Guide (docs/CHANNEL_PLUGIN_GUIDE.md)
- Fully backward compatible: existing config.json and sessions work as-is
- 340 tests pass, zero regressions
2026-03-14 16:13:38 +08:00
mru4913
670d2a6ff8 feat(feishu): implement message reply/quote support
- Add `reply_to_message: bool = False` config to `FeishuConfig`
- Parse `parent_id` and `root_id` from incoming events into metadata
- Fetch quoted message content via `im.v1.message.get` and prepend
  `[Reply to: ...]` context for the LLM when a user quotes a message
- Add `_reply_message_sync` using `im.v1.message.reply` API so the
  bot's response appears as a threaded quote in Feishu
- First outbound message uses reply API; subsequent chunks fall back
  to `create` to avoid duplicate quote bubbles; progress messages
  always use `create`
- Add 19 unit tests covering all new code paths
2026-03-13 15:02:57 +08:00
Tony
87ab980bd1 refactor(feishu): extract tool hint card sending into dedicated method
- Extract card creation logic into _send_tool_hint_card() helper
- Improves code organization and testability
- Update tests to use pytest.mark.asyncio for cleaner async testing
- Remove redundant asyncio.run() calls in favor of native async test functions
2026-03-13 14:52:15 +08:00
Tony
82064efe51 feat(feishu): improve tool call card formatting for multiple tools
- Format multiple tool calls each on their own line
- Change title from 'Tool Call' to 'Tool Calls' (plural)
- Add explicit 'text' language for code block
- Improves readability and supports displaying longer content
- Update tests to match new formatting
2026-03-13 14:48:36 +08:00
Tony
7261bd8c3f feat(feishu): display tool calls in code block messages
- Tool hint messages with _tool_hint metadata now render as formatted code blocks
- Uses Feishu interactive card message type with markdown code fences
- Shows "Tool Call" header followed by code in a monospace block
- Adds comprehensive unit tests for the new functionality

Co-Authorship-Bot: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:43:47 +08:00
Tony
df89bd2dfa feat(feishu): display tool calls in code block messages
- Add special handling for tool hint messages (_tool_hint metadata)
- Send tool calls using Feishu's "code" message type with formatting
- Tool calls now appear as formatted code snippets in Feishu chat
- Add unit tests for the new functionality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:41:54 +08:00
Tony
da740c871d test 2026-03-13 14:06:22 +08:00
Xubin Ren
ca5047b602 feat(web): multi-provider web search + Jina Reader fetch 2026-03-13 05:44:16 +00:00
Xubin Ren
84b107cf6c fix(ci): upgrade setup-python, add system deps, simplify test assertions 2026-03-13 04:05:08 +00:00
Xubin Ren
4b50a7b6c0 Merge branch 'main' into pr-1916 2026-03-13 03:57:09 +00:00