Commit Graph
3699 Commits
Author SHA1 Message Date
chengyongruandchengyongru 6c0f151f6e fix(webui): polish responsive layout 2026-07-23 18:22:02 +08:00
chengyongruandGitHub 4b1547db7d style(webui): unify settings and dark mode surfaces (#5058) 2026-07-23 17:47:20 +08:00
Xubin Ren c3ec2e665f test(documents): preserve nested block order 2026-07-23 16:53:59 +08:00
Xubin Ren 911a7e3a82 test(documents): cover vertical merged cells 2026-07-23 16:53:59 +08:00
Xubin Ren fc9d17eb7b fix(documents): bound nested DOCX table parsing 2026-07-23 16:53:59 +08:00
Xubin Ren 60ab580f8b fix(documents): preserve DOCX table content 2026-07-23 16:53:59 +08:00
chengyongruandGitHub 96eb965aae feat(webui): show the actual fallback model (#5017) 2026-07-23 15:57:13 +08:00
chengyongruandchengyongru 4188ffc88d chore: pin migration TODOs to v0.2.4 2026-07-23 15:40:44 +08:00
chengyongruandchengyongru 089216f9c7 chore(session): schedule legacy fallback removal for v0.2.4 2026-07-23 14:53:00 +08:00
axelray-devandchengyongru 464f71b488 fix(session): fall back to legacy paths in metadata reads
Fixes #4940
2026-07-23 14:53:00 +08:00
chengyongruandchengyongru 15de6be0af fix(providers): fall back on authentication errors 2026-07-23 14:52:04 +08:00
chengyongruandGitHub 01cdfc8100 fix(telegram): expose proxy setup in WebUI (#5033) 2026-07-23 14:18:49 +08:00
Arthur K.andchengyongru 3647875aba fix: add one second to retry after delays 2026-07-23 14:10:27 +08:00
santhrealandchengyongru 299bcf491b fix(cron): skip null runHistory elements when loading jobs.json
Null entries in state.runHistory raised TypeError and quarantined the
store. Skip non-dict elements like LocalTrigger.from_dict already does.
2026-07-23 14:07:06 +08:00
santhrealandchengyongru 0191c0db73 fix(pairing): treat null approved channel lists as empty
pairing.json with "telegram": null crashed is_approved during load.
Treat non-list channel entries as an empty allow-list.
2026-07-23 14:04:53 +08:00
santhrealandchengyongru 5851bd432a fix(slack): keep fenced markdown tables intact in _to_mrkdwn 2026-07-23 14:03:09 +08:00
santhrealandchengyongru 8195181783 fix(feishu): keep fenced markdown tables out of card tables 2026-07-23 14:02:33 +08:00
chengyongruandGitHub 9cf2fb19c2 feat(xai): surface hosted X Search activity (#5050) 2026-07-23 13:42:09 +08:00
chengyongruandchengyongru f3099286ea docs: explain slow optional dependency installs 2026-07-23 13:23:55 +08:00
chengyongruandchengyongru 5f054c0e74 fix(agent): deliver non-streamed finalization responses 2026-07-23 13:16:47 +08:00
Xubin Ren 536e8db324 refactor(webui): remove unused picker styling hooks 2026-07-23 12:42:24 +08:00
Xubin Ren 2f4f00bb9f refactor(image): reuse the model picker 2026-07-23 12:42:24 +08:00
Xubin Ren 8bd951a06f test(image): update model picker assertion 2026-07-23 12:42:24 +08:00
Xubin Ren e875f29185 fix(image): allow custom model ids 2026-07-23 12:42:24 +08:00
Xubin Ren 1616fa9f14 feat(image): apply generation settings live 2026-07-23 12:42:24 +08:00
chengyongruandGitHub c7393c785e feat(providers): add xAI Grok OAuth with capability-gated X Search (#5035) 2026-07-23 11:55:16 +08:00
chengyongruandGitHub c22efb5f7a feat(agent): make model presets session-scoped (#4866) 2026-07-23 00:38:49 +08:00
chengyongruandGitHub 66690fdb0c fix(webui): deliver late subagent results as new turns (#4992) 2026-07-22 23:04:36 +08:00
Xubin Ren aa8387fb4d feat(webui): polish agent output and app discovery 2026-07-22 22:42:31 +08:00
chengyongruandGitHub b189a37648 fix(agent): preserve agent-owned state in project workspaces (#4945) 2026-07-22 17:25:22 +08:00
chengyongruandchengyongru 4cd6eb6c38 fix(webui): avoid mobile welcome composer overlap 2026-07-22 15:55:09 +08:00
chengyongruandchengyongru 80085085d9 fix(exec): retain failed owner session cleanup 2026-07-22 15:28:34 +08:00
yorkhellenandchengyongru ebf1ef5cab test(subagent): verify cascade exec termination on /stop
- terminate_by_owner kills matching sessions, skips others, handles
  empty owner case
- cancel_by_session calls terminate_by_owner on the session key
2026-07-22 15:28:34 +08:00
yorkhellenandchengyongru 7b1d81a868 fix(subagent): cascade exec session termination on /stop
cancel_by_session() only cancelled asyncio tasks, leaving child
processes from exec sessions orphaned. Since each SubagentManager
now owns a dedicated ExecSessionManager, terminate those sessions
by owner_session_key after cancelling tasks.

Add ExecSessionManager.terminate_by_owner() to kill all sessions
for a given owner, and call it from cancel_by_session().
2026-07-22 15:28:34 +08:00
chengyongruandGitHub 254497c02e fix(webui): improve mobile composer layout (#5030) 2026-07-22 14:59:56 +08:00
chengyongruandGitHub 96abb4d2c4 style(webui): clarify surface hierarchy (#5029) 2026-07-22 14:33:58 +08:00
chengyongruandGitHub 63bc6e98a7 fix(webui): detect Chrome voice recording support (#5027) 2026-07-22 14:10:09 +08:00
chengyongruandGitHub 3748f664b2 feat(config): watch runtime configuration changes (#5026) 2026-07-22 13:08:39 +08:00
chengyongruandGitHub 7bf7469d90 feat(webui): show pin indicators for pinned chats (#5025) 2026-07-22 11:47:45 +08:00
seteiroandGitHub 79d9455313 fix(providers): add Qwen model-level thinking style mapping (#5023)
Add _QWEN_THINKING_MODELS to _MODEL_THINKING_STYLES with enable_thinking style. Prevents Qwen 3.5/3.6/3.7 models from exposing raw reasoning content in chat responses. Closes #4934
2026-07-22 10:46:22 +08:00
hamb1yandXubin Ren a9867a5a4e fix: quarantine invalid tool results 2026-07-22 01:59:09 +08:00
seteiroandXubin Ren c6a4d46a2a docs(security): recommend env-var references over plaintext API keys
Prefer ${VAR} env references in config over plaintext keys on disk. Closes #4803
2026-07-22 01:45:28 +08:00
yrkandXubin Ren be1cc769d5 docs: refine ModelScope documentation wording 2026-07-22 01:35:20 +08:00
yrkandXubin Ren 9abad4746e feat(providers): add ModelScope provider for LLM and image generation 2026-07-22 01:35:20 +08:00
chengyongruandchengyongru b32d673ead fix(webui): decouple skill reference rendering 2026-07-21 22:56:04 +08:00
chengyongruandchengyongru 79b89f4f4c feat(webui): highlight skill references in sent messages 2026-07-21 22:56:04 +08:00
Kris LuandXubin Ren 89d8c055a8 fix(providers): sanitize UTF-16 surrogates at provider request boundary
Symptom
-------
LLM requests intermittently fail with:
  'utf-8' codec can't encode characters in position N-N+1: surrogates not allowed
when messages contain emoji-heavy content (e.g. HTML with mixed emoji + JSON round-trips).
This blocks the affected session until the session file is quarantined.

Root cause
----------
Surrogate sanitization was only applied at the CLI entry point
(nanobot/cli/commands.py: _sanitize_surrogates). Requests entering
the LLM provider layer through other channels (Feishu, cron, webui,
tool results, memory injection) had no defensive cleaning, so any
message that happened to carry unpaired UTF-16 surrogates (from an
upstream JSON round-trip with ensure_ascii=True on ill-formed input,
memory rehydration, or third-party content) would blow up at
json.dumps -> HTTP encode time inside the provider client.

Fix
---
1. Extract sanitize_surrogates() and sanitize_surrogates_deep() into
   nanobot/utils/helpers.py as the single source of truth. Both use
   utf-16-le round-tripping with errors='surrogatepass' / 'replace',
   so paired surrogates reconstruct back into their real code point
   and lone surrogates collapse to U+FFFD.
2. Make nanobot/cli/commands.py:_sanitize_surrogates a thin wrapper
   that re-exports the shared helper (backward compatible).
3. Add defense-in-depth at the LLM provider boundary in
   nanobot/providers/base.py:_sanitize_empty_content by running
   sanitize_surrogates_deep over each message and its content blocks
   right before requests are serialized to JSON.

Non-goals
---------
- truncate_text() is intentionally left untouched. Python str slicing
  cannot split a single code point into surrogate halves, so it is
  not the source of lone surrogates.
- session/manager storage layer is untouched. Archived sessions
  reproduced the failure only through the request path, not through
  storage.

Verification
------------
- New regression suite tests/providers/test_sanitize_surrogates.py
  covers: paired surrogate reconstruction, lone surrogate replacement,
  identity return on clean input (zero allocation), deep recursion on
  dict/list/tuple, provider _sanitize_empty_content integration, and
  full utf-8 encodability of the sanitized request body.
- 14/14 new tests pass; full existing test module also green.
- Replayed 58 archived real session messages plus adversarial
  lone-surrogate injection through the provider path with no encode
  errors after the fix.

Impact
------
- No behaviour change for clean inputs (sanitize_surrogates_deep is
  an identity return when no surrogate is present).
- Fails-safe: unpaired surrogates degrade to U+FFFD instead of
  aborting the entire request.
2026-07-21 19:17:58 +08:00
santhrealandXubin Ren b81c05581f fix(cron): coerce string schedule/state ms fields from jobs.json
jobs.json can store everyMs/atMs and next/last run timestamps as strings.
Loading left them as str, so _compute_next_run compared str to int and raised TypeError.
Coerce with an optional-int helper at from_store_dict, matching runHistory int() paths.
2026-07-21 19:07:45 +08:00
chengyongruandchengyongru 1d7bad3909 feat(providers): support Codex fast mode 2026-07-21 17:55:17 +08:00
Xubin Ren b46e7f4377 fix(config): invalidate fields with missing env refs 2026-07-21 17:35:16 +08:00