Commit Graph
100 Commits
Author SHA1 Message Date
Xubin Ren 6483071485 chore: update version to 0.1.5.post1 2026-04-14 18:51:04 +00:00
Xubin Ren 1a5a16d1f3 chore: update README with recent news entries 2026-04-14 18:19:30 +00:00
Xubin RenandXubin Ren a0812ad60e test: cover retry termination notifications
Lock the new interaction-channel retry termination hints so both exhausted standard retries and persistent identical-error stops keep emitting the final progress message.

Made-with: Cursor
2026-04-15 01:55:57 +08:00
Xubin RenandXubin Ren 25ded8e747 test: cover active task count in status
Lock the /status task counter to the actual stop scope by asserting it sums unfinished dispatch tasks with running subagents for the current session.

Made-with: Cursor
2026-04-15 01:49:42 +08:00
Xubin RenandXubin Ren b60e8dc0ba test: cover missing tool-call arguments normalization
Lock the strict-provider sanitization path so assistant tool calls without function.arguments are normalized to {} instead of being forwarded as missing values.

Made-with: Cursor
2026-04-15 01:37:41 +08:00
Xubin RenandXubin Ren 1f33df1ea6 fix: preserve empty dict allow_from handling
Keep dict-backed channel configs compatible with both allow_from and allowFrom without losing empty-list semantics, and add focused regression coverage for the allow-list boundary.

Made-with: Cursor
2026-04-15 01:26:51 +08:00
Xubin Ren 89bf5d29d1 fix: reduce CLI streaming flicker and show model in welcome line 2026-04-14 13:38:06 +00:00
Xubin Ren c937c07178 fix: two bugs in document extraction pipeline
Bug 1: _drain_pending did not call extract_documents on follow-up
messages arriving mid-turn. Documents attached to queued messages were
silently dropped because _build_user_content only handles images.
Fix: call extract_documents before _build_user_content in _drain_pending.

Bug 2: extract_documents read the entire file into memory (up to 50 MB)
just to check 16 bytes of magic header for MIME detection.
Fix: read only the first 16 bytes via open()+read(16) instead of
Path.read_bytes().

Added regression tests for both bugs.

Made-with: Cursor
2026-04-14 13:15:04 +00:00
Xubin Ren 92d6fca323 refactor: centralize document extraction in AgentLoop._process_message
Move extract_documents() to nanobot.utils.document as a reusable helper
and call it once in AgentLoop._process_message, the single entry point
for all message processing (API + all channels).

This replaces the previous API-only _extract_documents() in server.py,
ensuring Telegram, Feishu, Slack, WeChat, and all other channels also
benefit from automatic document text extraction.

Adds a configurable max_file_size guard (default 50 MB) to skip
oversized files gracefully, preventing unbounded memory/CPU usage
from channel-downloaded attachments.

- server.py: removed _extract_documents and related imports
- document.py: added extract_documents() with size limit
- loop.py: calls extract_documents() at the top of _process_message
- Tests updated: 70 related tests pass

Made-with: Cursor
2026-04-14 13:10:03 +00:00
Xubin Ren 47f5795708 refactor: move document extraction from ContextBuilder to API layer
ContextBuilder._build_user_content now only handles images (its original
responsibility).  Document text extraction (PDF, DOCX, XLSX, PPTX) is
performed by the new _extract_documents() helper in server.py, called
before process_direct().  This keeps the core context builder free of
format-specific dependencies and makes the API boundary the single place
where uploaded files are pre-processed.

Tests updated to reflect the new responsibility boundary.

Made-with: Cursor
2026-04-14 13:00:59 +00:00
Xubin Ren 2502fc616b Merge origin/main into feat/api-file-upload
Keep the API file upload branch current with main, enforce the documented JSON base64 per-file limit, and avoid leaking document extraction error strings into user prompts.

Made-with: Cursor
2026-04-14 12:29:43 +00:00
Xubin RenandXubin Ren 0a51344483 fix(slack): keep cross-target sends out of origin threads
When Slack resolves a named target to another conversation, do not reuse the origin thread timestamp on the destination send, and keep reaction cleanup anchored to the source conversation.

Made-with: Cursor
2026-04-14 20:19:48 +08:00
Xubin Ren e4b3f9bd28 security(gateway): keep health endpoint local by default
Bind the gateway health listener to localhost by default and reduce the probe response to a minimal status payload so accidental public exposure leaks less information.

Made-with: Cursor
2026-04-14 07:19:38 +00:00
Xubin Ren 4999e2f734 Merge origin/main into feat/health-endpoint
Keep the gateway health endpoint patch current with the latest gateway runtime changes, and lock the new HTTP routes in with CLI regression coverage and README guidance.

Made-with: Cursor
2026-04-14 06:32:31 +00:00
Xubin RenandXubin Ren a38bc637bd fix(runner): preserve injection flag after max-iteration drain
Keep late follow-up injections observable when they are drained during max-iteration shutdown so loop-level response suppression still makes the right decision.

Made-with: Cursor
2026-04-14 00:30:30 +08:00
Xubin RenandXubin Ren 6484c7c47a fix(agent): close interrupted early-persisted user turns
Track text-only user messages that were flushed before the turn loop completes, then materialize an interrupted assistant placeholder on the next request so session history stays legal and later turns do not skip their own assistant reply.

Made-with: Cursor
2026-04-13 10:26:09 +08:00
Xubin RenandXubin Ren b964a894d2 test(agent): cover early user-message persistence
Use session.add_message for the pre-turn user-message flush and add focused regression tests for crash-time persistence and duplicate-free successful saves.

Made-with: Cursor
2026-04-13 10:26:09 +08:00
Xubin RenandXubin Ren 49355b2bd6 test(tools): lock non-object parameter validation
Add focused registry coverage so the new read_file/read_write parameter guard stays actionable without changing generic validation behavior for other tools.

Made-with: Cursor
2026-04-13 09:55:05 +08:00
Xubin RenandXubin Ren 217e1fc957 test(retry): lock in-place image fallback behavior
Add a focused regression test for the successful no-image retry path so the original message history stays stripped after fallback and the repeated retry loop cannot silently return.

Made-with: Cursor
2026-04-12 20:10:06 +08:00
Xubin RenandXubin Ren 7a7f5c9689 fix(dream): use valid builtin skill template paths
Point Dream skill creation at a readable builtin skill-creator template, keep skill writes rooted at the workspace, and document the new skill discovery behavior in README.

Made-with: Cursor
2026-04-12 16:49:55 +08:00
Xubin RenandXubin Ren 5dc238c7ef fix(shell): allow read-only copies from internal state files
Keep the new exec guard focused on writes to history.jsonl and .dream_cursor while still allowing read-only copy operations out of those files.

Made-with: Cursor
2026-04-12 16:38:55 +08:00
Xubin Ren a142788da9 docs(readme): document disabledSkills config
Explain the new agents.defaults.disabledSkills option so users can discover and configure skill exclusion from the main agent and subagents.

Made-with: Cursor
2026-04-12 02:42:52 +00:00
Xubin Ren e229c2ebc0 fix(pr): remove internal .docs file from PR
Keep the local review note out of the GitHub diff while preserving the actual code and test changes for this PR.

Made-with: Cursor
2026-04-12 02:21:46 +00:00
Xubin Ren 09c238ca0f Merge origin/main into pr-2959
Resolve the config plumbing conflicts and keep disabled skill filtering consistent for subagent prompts after syncing with main.

Made-with: Cursor
2026-04-12 02:02:39 +00:00
Xubin RenandXubin Ren cf8381f517 feat(agent): enhance message injection handling and content merging 2026-04-11 21:43:23 +08:00
Xubin RenandXubin Ren f6c39ec946 feat(agent): enhance session key handling for follow-up messages 2026-04-11 21:43:23 +08:00
Xubin Ren 322142f7ad Merge origin/main into main 2026-04-11 09:32:05 +00:00
Xubin RenandXubin Ren b959ae6d89 test(web): cover Kagi search provider
Add focused coverage for the Kagi web search provider, including the request format and the DuckDuckGo fallback when no API key is configured.
2026-04-11 16:53:05 +08:00
Xubin Ren 5bb7f77b80 feat(tests): add regression test for timer execution to prevent store rollback during job execution 2026-04-11 08:43:25 +00:00
Xubin Ren 8fe8537505 Merge origin/main into fix/cron-reentrant-load-store 2026-04-11 08:25:47 +00:00
Xubin RenandXubin Ren 5932482d01 refactor(agent): rename auto compact module
Rename the auto compact module to autocompact.py for a cleaner path while keeping the AutoCompact type and behavior unchanged. Update the agent loop import to match.
2026-04-11 15:56:41 +08:00
Xubin RenandXubin Ren 84e840659a refactor(config): rename auto compact config key
Prefer the more user-friendly idleCompactAfterMinutes name for auto compact while keeping sessionTtlMinutes as a backward-compatible alias. Update tests and README to document the retained recent-context behavior and the new preferred key.
2026-04-11 15:56:41 +08:00
Xubin RenandXubin Ren 1cb28b39a3 feat(agent): retain recent context during auto compact
Keep a legal recent suffix in idle auto-compacted sessions so resumed chats preserve their freshest live context while older messages are summarized. Recover persisted summaries even when retained messages remain, and document the new behavior.
2026-04-11 15:56:41 +08:00
Xubin Ren 696b64b5a6 fix(notebook): remove unused imports
Clean up unused imports in notebook_edit so the Ruff F401 check passes cleanly.

Made-with: Cursor
2026-04-10 16:02:00 +00:00
Xubin Ren 651aeae656 improve file editing and add notebook tool
Enhance file tools with read tracking, PDF support, safer path handling,
smarter edit matching/diagnostics, and introduce notebook_edit with tests.
2026-04-10 15:44:50 +00:00
Xubin RenandXubin Ren 9bccfa63d2 fix test: use async/await for run_job, add sentinel coverage
Made-with: Cursor
2026-04-10 19:03:13 +08:00
Xubin Ren 2bef9cb650 fix(agent): preserve interrupted tool-call turns
Keep tool-call assistant messages valid across provider sanitization and avoid trailing user-only history after model errors. This prevents follow-up requests from sending broken tool chains back to the gateway.
2026-04-10 05:37:25 +00:00
Xubin RenandXubin Ren c579d67887 fix(memory): preserve consolidation turn boundaries under chunk cap
Made-with: Cursor
2026-04-10 12:58:58 +08:00
Xubin Ren 363a0704db refactor(runner): update message processing to preserve historical context
- Adjusted message handling in AgentRunner to ensure that historical messages remain unchanged during context governance.
- Introduced tests to verify that backfill operations do not alter the saved message boundary, maintaining the integrity of the conversation history.
2026-04-10 04:46:48 +00:00
Xubin RenandXubin Ren 69d748bf8f Merge origin/main; warn on partial proxy credentials; add only-password test
- Merged latest main (no conflicts)
- Added warning log when only one of proxy_username/proxy_password is set
- Added test_start_no_proxy_auth_when_only_password for coverage parity

Made-with: Cursor
2026-04-09 23:54:11 +08:00
Xubin RenandXubin Ren c625c0c2a7 Merge origin/main and add regression tests for streaming error delivery
- Merged latest main (no conflicts)
- Added test_llm_error_not_appended_to_session_messages: verifies error
  content stays out of session messages
- Added test_streamed_flag_not_set_on_llm_error: verifies _streamed is
  not set when LLM returns an error, so ChannelManager delivers it

Made-with: Cursor
2026-04-09 23:10:46 +08:00
Xubin RenandXubin Ren ba8bce0f45 fix(tests): add missing from typing import Any in websocket integration tests
Made-with: Cursor
2026-04-09 18:22:35 +08:00
Xubin Ren dadf453097 Merge origin/main into fix/sanitize-messages-non-claude
Resolved conflict in azure_openai_provider.py by keeping main's
Responses API implementation (role alternation not needed for the
Responses API input format).

Made-with: Cursor
2026-04-09 04:45:45 +00:00
Xubin Ren 1dd2d5486e docs: add unified session configuration to README for cross-channel continuity 2026-04-09 03:15:21 +00:00
Xubin RenandXubin Ren cf02408fc0 Merge origin/main; remove stale comment and fix blank-line style
Made-with: Cursor
2026-04-09 11:09:25 +08:00
Xubin RenandXubin Ren 61dd5ac13a test(discord): cover streamed reply overflow
Lock the Discord streaming path with a regression test for final chunk splitting so oversized replies stay safe to merge and ship.

Made-with: Cursor
2026-04-09 00:24:11 +08:00
Xubin RenandXubin Ren 715f2a79be fix(version): fall back to pyproject in source checkouts
Keep importlib.metadata as the primary source for installed packages, but avoid PackageNotFoundError when nanobot is imported directly from a source tree.

Made-with: Cursor
2026-04-08 23:47:36 +08:00
Xubin RenandXubin Ren 6bf101c79b fix(hook): keep composite hooks backward compatible
Avoid AttributeError regressions when hooks define their own __init__ or when a CompositeHook wraps another composite.

Made-with: Cursor
2026-04-08 23:41:31 +08:00
Xubin RenandXubin Ren 142cb46956 fix(cron): preserve manual run state and merged history
Keep manual runs from flipping the scheduler's running flag, rebuild merged run history records from action logs, and avoid delaying sub-second jobs to a one-second floor. Add regression coverage for disabled/manual runs, merged history persistence, and sub-second timers.

Made-with: Cursor
2026-04-08 23:34:47 +08:00
Xubin Ren d084d10dc2 feat(openai): auto-route direct reasoning requests with responses fallback 2026-04-08 15:21:08 +00:00
Xubin RenandXubin Ren c092896922 fix(tool-hint): handle quoted paths in exec hints
Preserve path folding for quoted exec command paths with spaces so hint previews do not fall back to mid-path truncation. Add regression coverage for quoted Unix and Windows path cases.

Made-with: Cursor
2026-04-08 23:05:52 +08:00
Xubin RenandXubin Ren c7d10de253 feat(soul): restore friendly and curious tone to SOUL.md
Made-with: Cursor
2026-04-08 02:22:25 +08:00
Xubin RenandXubin Ren edb821e10d feat(agent): prompt behavior directives, tool descriptions, and loop robustness 2026-04-08 02:22:25 +08:00
Xubin RenandXubin Ren ef0284a4e0 fix(exec): add Windows support for shell command execution
ExecTool hardcoded bash, breaking exec on Windows. Now uses cmd.exe
via COMSPEC on Windows with a curated minimal env (PATH, SYSTEMROOT,
etc.) that excludes secrets. bwrap sandbox gracefully skips on Windows.
2026-04-08 01:48:55 +08:00
Xubin RenandXubin Ren 63acfc4f2f test: fix trailing-space mismatch and add regression tests for normal models
- Fix assertion in streaming dict fallback test (trailing space in data
  not reflected in expected value).
- Add two regression tests proving that models with reasoning_content
  (e.g. DeepSeek-R1) and standard models (no reasoning fields) are
  completely unaffected by the reasoning fallback.

Made-with: Cursor
2026-04-08 00:59:39 +08:00
Xubin RenandXubin Ren c736cecc28 chore(gitignore): remove bogus extensions and relocate nano.*.save
- Drop *.pycs, *.pywz, *.pyzz — not real Python file extensions.
- Move nano.*.save from "Project-specific" to "Editors & IDEs" where
  it belongs (nano editor backup files, not project artifacts).

Made-with: Cursor
2026-04-08 00:42:25 +08:00
Xubin RenandXubin Ren 8871a57b4c fix(mcp): forward prompt arg descriptions & standardise error format
- Propagate `description` from MCP prompt arguments into the JSON
  Schema so LLMs can better understand prompt parameters.
- Align generic-exception error message with tool/resource wrappers
  (drop redundant `{exc}` detail).
- Extend test fixture to mock `mcp.shared.exceptions.McpError`.
- Add tests for argument description forwarding and McpError handling.

Made-with: Cursor
2026-04-08 00:28:04 +08:00
Xubin RenandXubin Ren ce7986e492 fix(memory): add timestamp and cap to recent history injection 2026-04-08 00:03:11 +08:00
Xubin RenandXubin Ren 05d8062c70 test: add regression tests for unprocessed history injection in system prompt
Made-with: Cursor
2026-04-07 23:41:05 +08:00
Xubin RenandXubin Ren acafcf3cb0 docs: fix inaccurate claim about supports_streaming and dict config
supports_streaming already handles dict configs via isinstance check;
only is_allowed() fails with plain dicts. Narrow the explanation.

Made-with: Cursor
2026-04-07 23:01:30 +08:00
Xubin RenandXubin Ren 1e8a6663ca test(anthropic): add regression tests for thinking modes incl. adaptive
Also update schema comment to mention 'adaptive' as a valid value.

Made-with: Cursor
2026-04-07 22:53:43 +08:00
423aab09dd test(cron): add regression test for running service picking up external adds
Co-authored-by: chengyongru
Made-with: Cursor
2026-04-07 22:48:40 +08:00
Xubin RenandXubin Ren 82dec12f66 refactor: extract tool hint formatting to utils/tool_hints.py
- Move _tool_hint implementation from loop.py to nanobot/utils/tool_hints.py
- Keep thin delegation in AgentLoop._tool_hint for backward compat
- Update test imports to test format_tool_hints directly

Made-with: Cursor
2026-04-07 15:15:07 +08:00
Xubin RenandXubin Ren 02597c3ec9 fix(runner): silent retry on empty response before finalization 2026-04-07 15:03:41 +08:00
Xubin RenandXubin Ren 0355f20919 test: add regression tests for _resolve_mentions
7 tests covering: single mention, dual IDs, no-id skip, multiple mentions,
no mentions, empty text, and key-not-in-text edge case.

Made-with: Cursor
2026-04-07 14:03:55 +08:00
Xubin RenandXubin Ren 075bdd5c3c refactor: move SafeFileHistory to module level + add regression tests
- Promote _SafeFileHistory to module-level SafeFileHistory for testability
- Add 5 regression tests: surrogates, normal text, emoji, mixed CJK, multi-surrogates

Made-with: Cursor
2026-04-07 13:57:34 +08:00
Xubin Ren bf459c7887 fix(docker): fix volume mount path and add permission error guidance 2026-04-06 13:15:40 +00:00
Xubin Ren 4dac0a8930 docs: update nanobot docs badge 2026-04-06 11:55:47 +00:00
Xubin Ren a30e84bfd1 docs: update v0.1.5 release news 2026-04-06 11:46:16 +00:00
Xubin Ren 6269876bc7 docs: update v0.1.5 release news 2026-04-06 11:45:37 +00:00
Xubin Ren bc2253c83f docs: update v0.1.5 release news 2026-04-06 11:45:08 +00:00
Xubin Ren b719da7400 fix(feishu): use RawRequest for bot info API 2026-04-06 11:39:23 +00:00
Xubin Ren 79234d237e chore: bump version to 0.1.5 2026-04-06 11:26:07 +00:00
Xubin Ren 1243c08745 docs: update news section 2026-04-06 11:22:20 +00:00
Xubin RenandXubin Ren dad9c07843 fix(tests): update Tavily usage tests to match actual API response shape
The _parse_tavily_usage implementation was updated to use the real
{account: {plan_usage, plan_limit, ...}} structure, but the tests
still used the old flat {used, limit, breakdown} format.

Made-with: Cursor
2026-04-06 19:17:55 +08:00
Xubin Ren 35f53a721d refactor: consolidate _parse_retry_after_headers into base class
Merge the three retry-after header parsers (base, OpenAI, Anthropic)
into a single _extract_retry_after_from_headers on LLMProvider that
handles retry-after-ms, case-insensitive lookup, and HTTP date.

Remove the per-provider _parse_retry_after_headers duplicates and
their now-unused email.utils / time imports. Add test for retry-after-ms.

Made-with: Cursor
2026-04-06 08:44:52 +00:00
Xubin Ren aeba9a23e6 refactor: remove dead _error_response wrapper in Anthropic provider
Fold _error_response back into _handle_error to match OpenAI/Azure
convention. Update all call sites and tests accordingly.

Made-with: Cursor
2026-04-06 08:35:02 +00:00
Xubin Ren b575aed20e Merge origin/main into fix/structured-retry-classification-main
Made-with: Cursor
2026-04-06 08:28:20 +00:00
Xubin RenandXubin Ren d108879b48 security: bind api port to localhost by default
Prevents accidental exposure to the public internet. Users who need
external access can change to 0.0.0.0:8900:8900 explicitly.

Made-with: Cursor
2026-04-06 16:20:20 +08:00
Xubin RenandXubin Ren 634261f07a fix: correct api-workspace path for non-root container user
The Dockerfile runs as user nanobot (HOME=/home/nanobot), not root.

Made-with: Cursor
2026-04-06 16:20:20 +08:00
Xubin RenandXubin Ren ebf29d87ae fix: include byteplus providers, guard None reasoning_effort, merge extra_body
- Add byteplus and byteplus_coding_plan to thinking param providers
- Only send extra_body when reasoning_effort is explicitly set
- Use setdefault().update() to avoid clobbering existing extra_body
- Add 7 regression tests for thinking params

Made-with: Cursor
2026-04-06 16:12:08 +08:00
Xubin RenandXubin Ren c0e161de23 docs: add attachment example to email config JSON
Made-with: Cursor
2026-04-06 15:09:44 +08:00
Xubin RenandXubin Ren b98a0aabfc style: fix stdlib import ordering in email.py
Made-with: Cursor
2026-04-06 15:09:44 +08:00
Xubin Ren bdec2637ae test: add regression test for oversized stream-end splitting
Made-with: Cursor
2026-04-06 06:39:23 +00:00
Xubin Ren 09ec9991e1 Merge remote-tracking branch 'origin/main' into pr-2520
Made-with: Cursor

# Conflicts:
#	nanobot/channels/telegram.py
2026-04-06 06:37:54 +00:00
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 722ffe0654 Merge remote-tracking branch 'origin/main' into pr-2531
Made-with: Cursor

# Conflicts:
#	nanobot/channels/whatsapp.py
2026-04-06 06:17:56 +00:00
Xubin Ren 019eaff225 simplify: remove transcription fallback, respect explicit config
Configured provider is the only one used — no silent fallback.

Made-with: Cursor
2026-04-06 06:13:43 +00:00
Xubin Ren 3bf1fa5225 feat: auto-fallback to other transcription provider on failure
When the primary transcription provider fails (bad key, API error, etc.),
automatically try the other provider if its API key is available.

Made-with: Cursor
2026-04-06 06:10:08 +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 413740f585 Merge remote-tracking branch 'origin/main' into pr-2530
Made-with: Cursor

# Conflicts:
#	nanobot/channels/whatsapp.py
2026-04-06 05:59:31 +00:00
Xubin RenandXubin Ren 71061a0c82 fix: return on login failure, use loguru format strings, fix import order
- Add missing return after failed password login to prevent starting
  sync loop with no credentials
- Replace f-strings in logger calls with loguru {} placeholders
- Fix stdlib import order (asyncio before json)

Made-with: Cursor
2026-04-06 13:57:57 +08:00
Xubin RenandXubin Ren f82b5a1b02 fix: graceful fallback when langfuse is not installed
- Use import importlib.util (not bare importlib) for find_spec
- Warn and fall back to standard openai instead of crashing with
  ImportError when LANGFUSE_SECRET_KEY is set but langfuse is missing

Made-with: Cursor
2026-04-06 13:53:42 +08:00
Xubin RenandXubin 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
Xubin RenandXubin Ren 424b9fc262 refactor: extract _kill_process helper to DRY timeout/cancel cleanup
Made-with: Cursor
2026-04-06 13:47:09 +08:00
Xubin RenandXubin 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
Xubin RenandXubin 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
Xubin Ren 84b1c6a0d7 docs: update nanobot features 2026-04-05 20:07:11 +00:00