3826 Commits

Author SHA1 Message Date
Xubin Ren
be5af019b9 fix(wecom): sanitize fallback media filename 2026-08-04 22:04:21 +08:00
santhreal
98507ae4fe fix(wecom): fallback to default filename when sanitize strips to empty 2026-08-04 22:04:21 +08:00
concertypin
cb2f9d0bbd fix(webui): configure public websocket URL 2026-08-04 21:53:16 +08:00
concertypin
e318e21cad fix(webui): require proxy-generated auth assertions 2026-08-04 21:53:16 +08:00
concertypin
465a918cf8 feat(webui): bypass tokens for trusted proxy auth 2026-08-04 21:53:16 +08:00
concertypin
5cd14a42df feat(webui): support trusted proxy bootstrap auth 2026-08-04 21:53:16 +08:00
santhreal
170c7083ed fix(telegram): require newline for language tag to preserve single-line fenced code 2026-08-04 21:40:03 +08:00
santhreal
a13e29bf07 fix(telegram): preserve code block content when language tag contains special characters 2026-08-04 21:40:03 +08:00
chengyongru
5770329542
fix(webui): render markdown in prompt rail previews (#5244) 2026-08-04 18:24:54 +08:00
chengyongru
29fdb7d628 fix(webui): align timestamp tooltip styles 2026-08-04 18:22:12 +08:00
Xubin Ren
fa65a01977 refactor(webui): narrow floating control migration 2026-08-04 18:05:34 +08:00
Xubin Ren
28ec8a1b47 fix(webui): correct combobox navigation semantics 2026-08-04 18:05:34 +08:00
Xubin Ren
3b4a056947 chore(webui): sync npm lockfile 2026-08-04 18:05:34 +08:00
Xubin Ren
7819cef7bd refactor(webui): unify floating controls 2026-08-04 18:05:34 +08:00
chengyongru
faff0ac2fa fix(webui): align automation metadata with timestamps 2026-08-04 17:46:24 +08:00
chengyongru
f45436b61d fix(commands): reject invalid slash commands 2026-08-04 17:11:44 +08:00
chengyongru
287fd88fe4
fix(webui): refine inline token highlights (#5241) 2026-08-04 16:40:41 +08:00
chengyongru
2fe135db3e
feat(webui): add integrated Vite dev mode (#5239) 2026-08-04 16:14:32 +08:00
chengyongru
4e8702a47b
fix(anthropic): support Opus 5 effort controls (#5236) 2026-08-04 13:38:54 +08:00
Xubin Ren
d99f589a59 refactor(session): clarify reference boundaries 2026-08-04 12:14:51 +08:00
Xubin Ren
d8aeb0eb2c refactor(session): simplify cross-session flow 2026-08-04 12:14:51 +08:00
Xubin Ren
62d34b5eb7 refactor(session): tighten cross-session access 2026-08-04 12:14:51 +08:00
Xubin Ren
f15ea84dd1 fix(session): enforce trusted read scope 2026-08-04 12:14:51 +08:00
Xubin Ren
4c07c40b34 feat(session): link agent references 2026-08-04 12:14:51 +08:00
Xubin Ren
cf01978e71 feat(webui): link session mentions 2026-08-04 12:14:51 +08:00
Xubin Ren
5dd3dc5450 fix(session): harden cross-session references 2026-08-04 12:14:51 +08:00
Xubin Ren
9b25da7b92 feat(session): add cross-session references 2026-08-04 12:14:51 +08:00
chengyongru
44b7e1bf41 fix(providers): keep serde errors explicit 2026-08-03 18:06:45 +08:00
arcdrake22
6eda67b50c fix(providers): keep reasoning items wire-valid for DeepSeek Responses
convert_messages() emitted reasoning items with ``content`` as a plain
string whenever preserve_reasoning was enabled (the DeepSeek spec).
DeepSeek's Responses gateway rejects that shape with a serde error
("input: invalid type: string ..., expected a sequence"), which surfaced
only after token consolidation cleared provider_state and forced the
full-history conversion path; replayed server items already carry list
content, which is why normal multi-turn requests never failed. Serialize
reasoning content as a list of output_text parts, matching the OpenAI
Responses schema and DeepSeek's accepted wire shape (verified live against
api.deepseek.com/responses).

The serde fallback classifier introduced in the previous commit remains as
a last-resort safeguard for any remaining wire incompatibility.

Tests: extend test_preserves_deepseek_reasoning_content to the array shape;
add a full-history regression with the observed failing item, a
replay/consolidation regression covering both replayed and converted
reasoning items, and provider-level request fixtures for both paths.
Full suite: 5773 passed, 22 skipped (only the known local-only
channels/sms packaging failure remains).
2026-08-03 18:06:45 +08:00
arcdrake22
fb2688fd37 fix(providers): fall back to chat completions on serde body rejections
DeepSeek's new Responses endpoint (deepseek-v4-flash) intermittently rejects valid request bodies with serde deserialization errors such as 'input: invalid type: string ..., expected a sequence'. These were not classified as compatibility errors, so affected conversations died instead of falling back to Chat Completions.

The wire format is correct (input serializes as a list), so this is a server-side Responses compatibility issue; Chat Completions is strictly more permissive, making fallback safe. Extend the fallback classifier to recognize serde body-parsing markers. Repeated failures still trip the existing circuit breaker.
2026-08-03 18:06:45 +08:00
chengyongru
2b63715282 fix(webui): complete i18n audit 2026-08-03 17:53:33 +08:00
Xubin Ren
df11fd92a6 docs(providers): link ModelScope setup sources 2026-08-03 16:57:10 +08:00
Xubin Ren
b29f9dcbcb docs(providers): align ModelScope setup with current config 2026-08-03 16:57:10 +08:00
Krislu1221
02df20cd55 docs(providers): add ModelScope (魔搭) section
ModelScope is a fully implemented provider (nanobot/providers/registry.py,
image_generation.py, schema.py) with async image-generation task submission
and polling, but was previously undocumented in docs/providers.md.

This patch adds a ModelScope entry under 'Common Provider Patterns',
covering:

- Default base URL: https://api-inference.modelscope.cn/v1
- OpenAI-compatible chat/completions endpoint
- Async image-generation flow (task submit + status poll)
- Automatic 'modelscope/' prefix stripping when calling the API
- A minimal nanobot.yaml example

No code changes; docs-only.
2026-08-03 16:57:10 +08:00
chengyongru
f11710a578
fix(webui): show actual local trigger messages (#5228) 2026-08-03 16:43:01 +08:00
chengyongru
eeecfac538 fix(webui): stabilize thread during IME input 2026-08-03 16:41:08 +08:00
Xubin Ren
ac216c3e94 docs(providers): document Eden AI setup and WebUI parity 2026-08-03 16:40:13 +08:00
Xubin Ren
e7ec981f79 test(providers): verify Eden AI gateway contract 2026-08-03 16:40:13 +08:00
Victor M. SMITH
f42a44817a feat(providers): add Eden AI as an OpenAI-compatible gateway provider
Eden AI (https://www.edenai.co) is an EU-hosted, OpenAI-compatible gateway exposing 100+ models from many providers through a single endpoint and API key. Models use the provider/model naming scheme (the full id is sent upstream, like OpenRouter).

Adds it following the registry's documented two-step recipe:
- a ProviderSpec in providers/registry.py (backend openai_compat, gateway, default_api_base https://api.edenai.run/v3, EDENAI_API_KEY, reasoning_effort)
- the matching field in ProvidersConfig (config/schema.py)

API key via EDENAI_API_KEY only; never hardcoded.

Signed-off-by: Victor M. SMITH <72023257+MVS-source@users.noreply.github.com>
2026-08-03 16:40:13 +08:00
Xubin Ren
84f98f5e92 test(cron): cover invalid schedule expressions 2026-08-03 16:20:22 +08:00
ferkans-amir
73a0080484 fix(cron): validate expression syntax in _validate_schedule_for_add 2026-08-03 16:20:22 +08:00
arcdrake22
c6bd5f0075 test(gateway): align runtime-tasks gather tests with bounded retrieval
The helper never waits on the runtime-tasks gather after cancelling it
(its children are bounded individually), so the finished-gather test must
hand the helper an already-complete gather to exercise the bounded
retrieval path, and the cancelled-gather test must settle the gather
itself instead of expecting the helper to await a still-pending future.

Use a pre-completed child for the finished case and suppress(await) for
the cancelled case; both now assert done() and a single close.
2026-08-03 16:00:39 +08:00
Xubin Ren
39e1533c3b fix(gateway): make resource teardown cancellation-safe 2026-08-03 16:00:39 +08:00
arcdrake22
a91ce900ef test(gateway): add shutdown teardown regression coverage
Covers the lifecycle contract of _close_gateway_runtime: runtime tasks are
cancelled before shared resources close, pending background work is drained
before the close returns, cancellation-swallowing tasks and hanging cleanup
are bounded by their timeouts, a failing close is logged without blocking the
stop, duplicate cleanup is idempotent, and the runtime_tasks gather await path
is exercised for both completed and cancelled gathers.
2026-08-03 16:00:39 +08:00
arcdrake22
8942c22d86 fix(gateway): close agent resources deterministically on shutdown
The gateway shutdown path never closed agent resources explicitly: it relied
on the agent loop task's own finally to run close_mcp() when that task is
cancelled. When the service stops with an in-flight exec session or MCP
subprocess, that path can be skipped or cut short, leaving asyncio subprocess
transports alive after the event loop closes. They are then finalized by
__del__ against a closed loop, producing "RuntimeError: Event loop is closed"
noise in the shutdown log, and in the worst case orphaned subprocesses with
the stop stalling until systemd's timeout kills the cgroup.

The teardown is now extracted into _close_gateway_runtime() with explicit
ordering and bounds:

- Runtime tasks (including the agent loop and any in-flight turn) are
  cancelled and awaited -- bounded -- before exec sessions, subagents, and MCP
  servers are closed, so no active turn is using a shared resource when it
  closes.
- Channel transports are closed before waiting for their runners to exit, since
  some SDKs swallow task cancellation while attempting to reconnect.
- agent.close_mcp() is invoked explicitly, bounded to 15s, and is idempotent:
  it is a no-op when the agent loop's own cleanup already ran, and the
  guaranteed final close otherwise.
- A coroutine that swallows cancellation (e.g. an SDK reconnect loop) can no
  longer hold the stop open until systemd's timeout kills the cgroup; cleanup
  failures are logged instead of blocking shutdown.
2026-08-03 16:00:39 +08:00
chengyongru
a9bb39b833 fix(webui): dismiss mobile keyboard after send 2026-08-03 15:53:05 +08:00
KDB
52bc79d3a0 fix(plugins): use uv when pip is unavailable 2026-08-03 15:42:26 +08:00
chengyongru
5c72fdcd88 fix(webui): remove unused bot identity settings 2026-08-03 14:06:44 +08:00
yang1
f7a6bc2d21 fix(webui): globally register correct MIME types for static assets (#5190)
On Windows, mimetypes.guess_type() reads the Content Type value from
HKEY_CLASSES_ROOT\.js (and other extensions) in the registry, which is
commonly set to text/plain because .js is associated with Windows Script
Host rather than web JavaScript. The registry value overrides Python's
built-in mapping and causes browsers to reject ES module scripts.

Fix by explicitly registering correct MIME types via mimetypes.add_type()
at module import time for common web static extensions (.js, .mjs, .css,
.html, .json, .svg, .wasm). Using strict=True ensures the values replace
the registry-backed standard mappings used by mimetypes.guess_type(). This
benefits all callers of mimetypes.guess_type() in the gateway process, not
just _serve_static.

Closes #5190

Co-authored-by: amkile <44280409+amkile@users.noreply.github.com>
2026-08-03 11:33:02 +08:00
arcdrake22
08fe9f7b3a fix(image): send Gemini Flash hints via generationConfig.imageConfig
The live v1beta API rejects the legacy responseFormat.image block
(enum-based aspectRatio/imageSize fields) for gemini-3.1-flash-lite-image
with INVALID_ARGUMENT, even for documented plain-string values. Gemini
Flash image models accept plain-string hints under
generationConfig.imageConfig instead (e.g. aspectRatio 16:9, imageSize
1K), which the API accepts. Switch the flash path to imageConfig and
update the provider tests accordingly. Other providers (aihubmix,
ollama, imagen) are untouched.
2026-08-03 11:22:09 +08:00