Commit Graph

257 Commits

Author SHA1 Message Date
Hua
fd52973751 feat(config): hot reload agent runtime settings
Some checks failed
Test Suite / test (3.11) (push) Failing after 1m7s
Test Suite / test (3.12) (push) Failing after 1m3s
Test Suite / test (3.13) (push) Failing after 1m14s
2026-03-19 14:01:18 +08:00
Hua
cfcfb35f81 feat(mcp): add slash command listing 2026-03-19 13:10:07 +08:00
Hua
49fbd5c15c Merge remote-tracking branch 'origin/main'
Some checks failed
Test Suite / test (3.11) (push) Failing after 1m8s
Test Suite / test (3.12) (push) Failing after 1m8s
Test Suite / test (3.13) (push) Failing after 1m7s
# Conflicts:
#	README.md
#	nanobot/agent/context.py
#	nanobot/agent/loop.py
#	nanobot/channels/telegram.py
2026-03-19 00:42:43 +08:00
Xubin Ren
4b052287cb fix(telegram): validate remote media URLs 2026-03-18 23:12:11 +08:00
Xubin Ren
728d4e88a9 fix(providers): lazy-load provider exports 2026-03-18 22:01:29 +08:00
MiguelPF
4e56481f0b add one-time migration for legacy global cron store
When upgrading, if jobs.json exists at the old global path and not yet
at the workspace path, move it automatically.  Prevents silent loss of
existing cron jobs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:16:06 +01:00
MiguelPF
c33e01ee62 fix(cron): scope cron job store to workspace instead of global directory
Replace `get_cron_dir()` with `config.workspace_path / "cron"` so each
workspace keeps its own `jobs.json`.  This lets users run multiple
nanobot instances with independent cron schedules without cross-talk.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:11:01 +01: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
Hua
61dcdffbbe Merge remote-tracking branch 'origin/main'
Some checks failed
Test Suite / test (3.11) (push) Failing after 1m7s
Test Suite / test (3.12) (push) Failing after 1m5s
Test Suite / test (3.13) (push) Failing after 1m7s
# Conflicts:
#	nanobot/channels/slack.py
#	nanobot/config/schema.py
#	tests/test_feishu_reply.py
2026-03-17 21:13:12 +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
Hua
59b9b54cbc fix(skill): improve clawhub command handling 2026-03-17 15:55:41 +08:00
Hua
d31d6cdbe6 refactor(channels): formalize default config onboarding
Some checks failed
Test Suite / test (3.11) (push) Failing after 1m32s
Test Suite / test (3.12) (push) Failing after 1m19s
Test Suite / test (3.13) (push) Failing after 1m27s
2026-03-17 15:12:15 +08:00
Hua
06ee68d871 Merge remote-tracking branch 'origin/main'
Some checks failed
Test Suite / test (3.11) (push) Failing after 1m2s
Test Suite / test (3.12) (push) Failing after 1m1s
Test Suite / test (3.13) (push) Failing after 59s
2026-03-17 14:47:40 +08:00
Hua
0613b2879f Merge remote-tracking branch 'origin/main'
Some checks failed
Test Suite / test (3.11) (push) Failing after 59s
Test Suite / test (3.12) (push) Failing after 59s
Test Suite / test (3.13) (push) Failing after 58s
# Conflicts:
#	tests/test_commands.py
2026-03-17 14:30:00 +08:00
Xubin Ren
49fc50b1e6 test(custom): cover empty choices response handling 2026-03-17 14:24:55 +08:00
Hua
7a6d60e436 feat(skill): add clawhub slash commands 2026-03-17 14:19:36 +08:00
Xubin Ren
b2a550176e feat(onboard): align setup with config and workspace flags 2026-03-17 05:42:49 +00:00
Hua
6cd8a9eac7 Merge remote-tracking branch 'origin/main'
Some checks failed
Test Suite / test (3.11) (push) Failing after 1m14s
Test Suite / test (3.12) (push) Failing after 1m2s
Test Suite / test (3.13) (push) Failing after 1m0s
# Conflicts:
#	nanobot/cli/commands.py
#	tests/test_config_migration.py
2026-03-17 13:27:45 +08: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
Hua
f65d1a9857 Merge remote-tracking branch 'origin/main'
Some checks failed
Test Suite / test (3.11) (push) Failing after 3m2s
Test Suite / test (3.12) (push) Failing after 3m31s
Test Suite / test (3.13) (push) Failing after 3m56s
2026-03-17 09:34:49 +08:00
Xubin Ren
2eceb6ce8a fix(cli): pause spinner cleanly before printing progress output 2026-03-16 22:17:29 +08:00
Hua
16e87b1b04 Merge remote-tracking branch 'origin/main'
Some checks failed
Test Suite / test (3.12) (push) Has been cancelled
Test Suite / test (3.11) (push) Has been cancelled
Test Suite / test (3.13) (push) Has been cancelled
# Conflicts:
#	.gitignore
#	nanobot/agent/loop.py
#	nanobot/agent/memory.py
2026-03-16 18:52:43 +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
Hua
e0773c4bda Merge remote-tracking branch 'origin/main'
# Conflicts:
#	nanobot/agent/tools/web.py
2026-03-16 16:36:26 +08:00
Xubin Ren
6e2b6396a4 security: add SSRF protection, untrusted content marking, and internal URL blocking 2026-03-16 15:05:26 +08:00
Hua
95e77b41ba Merge remote-tracking branch 'origin/main'
# Conflicts:
#	.github/workflows/ci.yml
#	nanobot/agent/context.py
2026-03-16 14:49:12 +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
Hua
e2bbdb7a4f Merge remote-tracking branch 'origin/main' 2026-03-16 09:43:17 +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
Hua
fc4cc5385a fix(channels): restore plugin discovery after merge 2026-03-15 18:21:02 +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