2549 Commits

Author SHA1 Message Date
Soulter
ffb196f9a6 fix(plugin_manager): improve plugin state cleanup and add tests for unbinding and loading plugins
fixes: #8439
2026-05-30 18:43:36 +08:00
Loagaeth
e26fe1c3f5 feat(kb): add Markdown-aware chunker for structured documents (#8151)
* feat(kb): add Markdown-aware chunker for structured documents

* fix: address review feedback from sourcery-ai and gemini

- Clamp max_heading_depth to 1-6 to prevent regex errors
- Deduct prefix length when splitting oversized sections
- Replace hardcoded "[续]" with configurable continuation_prefix
- Skip fenced code blocks when detecting headings
- Cap pending size to prevent chunks exceeding chunk_size
- Refactor into dataclass + helper methods

* fix: handle unmatched fenced code block at EOF

* fix: prevent chunks exceeding chunk_size with long heading prefixes

* chore: rf

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-05-30 17:43:13 +08:00
NayukiChiba
bd597859f3 fix(provider): 修复 base64:// 图片引用的 MIME 类型声明不准确问题 (#8177)
- 新增 `_detect_image_format` 方法,使用 Pillow verify() 检测图片真实格式,避免完整解码像素带来的额外开销
- 新增 `_base64_image_ref_to_data_url` 方法,将 base64:// 引用转换为携带真实 MIME 类型的 data URL,修复 PNG/GIF/WebP 等图片被错误声明为 image/jpeg 的问题
- 提取 `_IMAGE_FORMAT_MIME_TYPES` 类常量和 `_image_format_to_mime_type` 方法,统一本地文件与 base64:// 引用的格式映射逻辑,新增 TIFF/AVIF 格式支持
- 新增单元测试 `test_resolve_image_part_preserves_base64_png_mime_type`,覆盖 PNG 图片 MIME 类型正确声明的场景

Closes #8174
2026-05-30 17:26:36 +08:00
Ruochen Pan
95d80578bf refactor(ltm): redesign long-term memory with context compaction (reopen of #8144) (#8226)
* refactor(ltm): redesign long-term memory with context compaction

- Add raw_records / contexts / summaries data model per group
- Add LLM summary compaction strategy alongside truncation
- Add turn-based (_split_into_rounds) granularity
- Add image caption integration into LTM history
- Add tool_call / tool_result persistence into raw_records
- Add active reply support driven by LTM state
- Improve summary injection prefix with system note and delimiters
- Add info-level logging for summary compaction lifecycle
- Clarify default summary prompt with explicit preserve/drop rules
- Add context_guard for history overflow protection in agent runner
- Add internal agent history compaction in agent_sub_stages
- Add comprehensive LTM unit tests and compaction test suites

* fix(ltm): handle malformed JSON in tool args and clean up lock on session removal

* fix(ltm): guard against duplicate system prompt note injection

* fix(ltm): fall back to user message when internal marker parsing fails

- Treat lines starting with <T:CALL>, <T:RES, or <BOT/ as regular user
  messages when their respective parsers return None, instead of silently
  dropping them. Defensive guard against malformed internal markers.

* fix(ltm): release session lock during LLM summary generation

* fix(ltm): trim raw_records in handle_message to prevent unbounded growth

* perf(ltm): use len(s) instead of len(s.encode()) in trim loop

Avoid allocating a new bytes object for every string when calculating
buffer size in _trim_raw_records. Character count is sufficient for
the approximate memory cap.

* feat(ltm): make user segment truncation limits configurable

* feat(ltm): pre-fill default LTM summary prompt in config and i18n

* refactor(ltm): hardcode internal segment/trim constants

* refactor(ltm): unify compaction strategy with main agent runner

* feat(ltm): add @mention weight marker for group chat messages

* test: fix test failures from LTM compaction unification

* chore(dashboard): remove obsolete LTM compaction i18n metadata

* chore: shrink codebase

* feat(group-chat): implement group chat context management and related functionality

---------

Co-authored-by: Tsukumi <112180165+Tsukumi233@users.noreply.github.com>
Co-authored-by: zenfun <zenfun510@gmail.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-05-30 17:16:36 +08:00
Soulter
61b6813dc7 fix(docs): update download link for dashboard zip file in FAQ 2026-05-30 14:49:44 +08:00
Soulter
9fc03fa95e chore: remove useless logs
closes: #8142
2026-05-30 14:45:56 +08:00
Soulter
49036f8f9d fix(message_tools): improve description for SendMessageToUserTool usage
fixes: #8355
2026-05-30 14:01:25 +08:00
Yokami
0ffdf54407 feat(context): improve default LLM compression prompt for better continuity (#8424) 2026-05-30 13:46:41 +08:00
NayukiChiba
8353fe1608 fix(anthropic): Anthropic API tool_choice schema conversion (#8328)
* fix(anthropic): 修复 Anthropic API tool_choice 格式转换及参数支持

- 将 tool_choice 从简单的 auto/required 逻辑改为遵循 Anthropic API 规范,支持 auto/any/none/tool 四种原生值
- 兼容 OpenAI 风格的 tool_choice="required",自动映射为 {"type": "any"}
- 允许直接传入 dict 类型的 tool_choice 以实现指定工具调用
- 更新 text_chat 和 stream_chat 入口的参数类型标注,扩大可接收的 tool_choice 类型
- 新增 tool_choice 格式转换的单元测试,覆盖各类输入场景

Closes #8319

* Clean up test cases and remove unused mocks

Removed unused mock classes and tests for tool_choice conversion.

* fix(anthropic): 修复 Anthropic API tool_choice="tool" 参数处理及重构格式转换逻辑

- 提取静态方法 _normalize_tool_choice 统一处理 tool_choice 格式转换,消除重复代码
- 处理字符串 "tool" 值时,因无法指定具体工具名而回退为 auto 并记录警告,避免无效请求
- 在 _query 和 _stream_query 中采用默认值 auto 并应用规范化逻辑,确保一致性

* test(anthropic): 添加空工具集时跳过工具参数设置的测试

- 新增 _EmptyToolSet 模拟类,模拟无工具场景
- 新增测试用例 test_tool_choice_empty_tool_list_skips_tool_choice
- 验证当 ToolSet 存在但工具列表为空时,请求不包含 tools 和 tool_choice 参数
- 完善边缘情况测试覆盖,确保与现有逻辑一致

* style: ruff 格式化一下

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-05-30 13:44:45 +08:00
時壹
01a47b8360 feat: pass through qq webhook extra fields (#6274) 2026-05-29 21:06:04 +08:00
elecvoid243
adae1f3598 fix(command-suggestion): support custom wake-up words & hover information (#8353)
* feature: add command suggestion for ChatUI

* feat(chat): add focus functionality to chat input after sending messages

* feat(llm): add error handling for LLM provider selection failures

* feat(command-suggestion): enhance command filtering and sorting logic

* fix(command-suggestion): support custom wake-up words & hover information

* ruff

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-05-29 01:17:32 +08:00
Waterwzy
e087b9def3 fix(plugin): plugin name in the marketplace does not match the local plugin (#8276)
* fix: plugin name in the marketplace does not match the local plugin

* chore: update test

* Update astrbot/dashboard/routes/plugin.py

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update astrbot/dashboard/routes/plugin.py

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update astrbot/dashboard/routes/plugin.py

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* chore: reformat code

* Clean up unused variables in useExtensionPage.js

Removed unused sets for installed repositories and names.

* fix: 统一repo匹配逻辑,移除fallback

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-05-29 01:02:51 +08:00
千岚之夏
9bd38cad57 fix: strip segment text to remove extra blank lines in segmented reply (#8304)
* fix: strip segment text to remove extra blank lines in segmented reply

Fixes #8300

* refactor: optimize seg.strip() per PR review suggestion
2026-05-29 00:54:47 +08:00
千岚之夏
022a5dd9f8 fix: prevent duplicate processing of quoted images by multimodal main providers when no dedicated image caption provider is configured (#8401)
Co-authored-by: C₂₂H₂₅NO₆ <Sisyphbaous-DT-Project@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-05-29 00:54:36 +08:00
Dt8333
e960c1495e fix(dashboard): fix plugin displayed dup (#8389)
Fixed the issue of duplicate plugin cards introduced in #8369
2026-05-28 10:39:56 +08:00
liuwanwan
8b16e4d6c9 fix: sanitize file name in file component (#8318)
* fix: sanitize remote file component names

* fix: handle windows-invalid file names

* test: cover windows-invalid file names

---------

Co-authored-by: liuwanwan1 <243261597+liuwanwan1@users.noreply.github.com>
2026-05-28 08:20:11 +08:00
Yufeng He
26e867cc6d fix(core): route image requests to vision fallback (#8089) 2026-05-27 22:21:55 +08:00
lingyun14
a221c74b74 Fix/plugin metadata repo type guard (#8207)
* fix: 修复插件 repo 字段类型导致前端报错

* fix: 修复插件 repo 字段类型导致前端报错

* fix: 使用 normalizeInstallUrl 统一 repo 字段处理

* fix:优化 installedRepos 构建方式
2026-05-27 22:00:42 +08:00
Weilong Liao
7f94bce360 feat(qqofficial): split message chain by media and update sending logic (#8376)
* feat(qqofficial): split message chain by media and update sending logic

* Delete tests/test_qqofficial_adapter.py
2026-05-27 21:59:47 +08:00
NayukiChiba
85f9c4dff8 fix(mimo): 修复voice design模型请求中包含无效voice参数的问题 (#8326)
* fix(mimo): 修复voice design模型请求中包含无效voice参数的问题

- voice design模型不支持audio.voice参数,之前统一添加导致请求可能出错
- 在构建请求payload时根据模型名称动态决定是否包含voice字段
- 增加单元测试覆盖voicedesign模型和普通模型的参数构建逻辑

close #8283

* style: 使用snake case命名法
2026-05-27 21:36:22 +08:00
NayukiChiba
89153fdf80 fix: 8267 mimo reasoning content (#8327)
* feat(openai): 为MiMo推理模型自动补充reasoning_content字段

- 消息过滤时增加reasoning_content判断,保留仅含思考内容的assistant消息
- 自动为MiMo推理模型的assistant历史消息注入空reasoning_content,满足API要求
- 通过模型名称集合和xiaomimimo.com端点双重判断是否为MiMo推理模型
- 添加单元测试覆盖不同模型识别、字段注入、端点检测和已有内容保留等场景

* fix(openai): 移除MiMo推理模型检测中的端点主机名判断

- 回退通过xiaomimimo.com主机名自动识别MiMo推理模型的逻辑
- 仅保留基于模型名称集合的判断方式,避免误判非MiMo模型
- 删除对应主机名检测的单元测试用例

* test(openai): 补充MiMo推理模型仅含reasoning_content消息不过滤的单元测试

- 添加test_mimo_filter_preserves_reasoning_only_assistant_message参数化测试
- 验证仅有reasoning_content的assistant消息不会被_sanitize过滤
- 确保包含reasoning_content的空content消息仍保留在对话历史中

* Update test_openai_source.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-05-27 21:13:40 +08:00
星空凌
538772c305 feat: add Xiaomi 和 Xiaomi Token Plan LLM provider (#7744)
* feat: 新增 Xiaomi 和 Xiaomi Token Plan LLM 提供商

- 新增 Xiaomi provider(OpenAI 兼容)
- 新增 Xiaomi Token Plan provider(Anthropic 兼容)
- 支持全模态(图片理解)
- 内置 MiMo v2.5 系列模型

* Update astrbot/core/provider/sources/xiaomi_token_plan_source.py

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Remove default config from Xiaomi provider adapter

Removed default configuration template for Xiaomi provider adapter.

* Remove default config from Xiaomi Token Plan adapter

Removed default configuration template for Xiaomi Token Plan provider adapter.

* chore: rf

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-05-27 21:11:00 +08:00
lxfight
23d70dbdbd feat(webui): add direct access button on plugin cards and improve embedded page height (#8369)
* feat(plugin): add pages field to plugin list API response

Include discovered page names for each plugin in the /api/plugin/get
response, so the frontend can determine whether a plugin has a WebUI
without an extra detail request.

* feat(webui): add direct WebUI access button on plugin cards

- Add "open-webui" button on plugin cards when plugin has pages
- Navigate to plugin's first page directly from the card
- Adjust PluginPagePage iframe height for better UX
- Add i18n labels (zh-CN/en-US/ru-RU)

* perf(plugin): use asyncio.gather for concurrent page discovery

Replace sequential await loop with concurrent processing to avoid
blocking on disk I/O when discovering plugin pages.

* fix(webui): disable open plugin UI button when plugin is deactivated

Prevent navigation to a disabled plugin's WebUI page which would
result in an error.

* test: update plugin API tests to match pages field in list response

- test_plugin_get_excludes_scanned_pages: expect pages field now present
- test_plugins: use name-based lookup instead of exact count assertion

---------

Co-authored-by: lxfight <lxfight@192.168.5.50>
2026-05-27 20:33:10 +08:00
hibiki233i
2d78626840 fix SQLAlchemy compatibility issues on macOS (#7724)
* Stabilize packaged SQLite knowledge base initialization

* Apply suggestion from @sourcery-ai[bot]

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* Apply suggestion from @gemini-code-assist[bot]

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* fix: updating database URL handling and ensuring unique document IDs

* fix: preserve sqlite pragmas with null pool

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-05-26 09:37:01 +09:00
NayukiChiba
ff28eca9ca fix(openai): 修复流式响应末尾usage信息丢失问题 (#8306)
- 修复在流式处理过程中,因跳过 delta=None 且 choices=[] 的 usage chunk 导致最终 completion 丢失 usage 数据的问题
- 在 handle_chunk 调用条件中增加 chunk.usage 判断,确保末尾 usage chunk 能被正常传递给 state 处理
- 更新相关注释,说明 usage chunk 的例外情况,保障流式响应的 usage 信息完整性
2026-05-23 23:17:44 +08:00
elecvoid243
dcc99e6b9b feat: 为ChatUI添加指令候选功能 (#8279)
* feature: add command suggestion for ChatUI

* feat(chat): add focus functionality to chat input after sending messages

* feat(llm): add error handling for LLM provider selection failures

* feat(command-suggestion): enhance command filtering and sorting logic

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-05-22 20:57:19 +08:00
EmilyCheoh
f5bd4f30e5 fix: preserve original completion_text in skills_like tool re-query (#8240)
Only overwrite tool-call-related fields from the re-query response, preserving the original completion_text and reasoning_content that were already sent to the user.
2026-05-22 20:32:29 +08:00
x1051445024
1e48bab514 fix: handle delta=None chunks in streaming to prevent SDK to_dict() error (#8244)
* fix: handle delta=None chunks in streaming to prevent SDK to_dict() error

When certain OpenAI-compatible providers (Gemini, DeepSeek, some proxies)
return chunks with choice.delta=None (e.g. ContentBlockDeltaEvent),
ChatCompletionStreamState._convert_initial_chunk_into_snapshot internally
calls choice.delta.to_dict() at line 747, causing:
  'NoneType' object has no attribute 'to_dict'

Fix:
  1. Skip handle_chunk when delta is None (delta=None chunks have no
     content contribution anyway)
  2. Wrap get_final_completion in try/except to gracefully fall back to
     empty ChatCompletion if SDK state is corrupted

Refs: openai-python#5069, openai-python#5047

* fix: resolve bugs found by Sourcery and gemini-code-assist review

- Remove orphan logger.error that caused NameError on every chunk
- Replace broken empty ChatCompletion fallback with clean return;
  streamed content already yielded, no data loss

Co-authored-by: sourcery-ai[bot] <sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <gemini-code-assist[bot]@users.noreply.github.com>

* fix: properly replace get_final_completion fallback in _query_stream

Previous fix_pr_v3 wrongly injected code into terminate() instead.
Now correctly:
1. Replace empty ChatCompletion fallback with clean return in _query_stream
2. Revert terminate() to original (await self.client.close() only)

* fix: revert corrupted terminate() to original

Previous fix_pr_v3 injected wrong-indentation code into terminate().

---------

Co-authored-by: sourcery-ai[bot] <sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <gemini-code-assist[bot]@users.noreply.github.com>
2026-05-22 20:28:03 +08:00
lingyun14
3f20bbdf23 fix: t2i shiki issue (#8013)
* fix(t2i): run Shiki runtime injection in executor to avoid blocking event loop

* Update network_strategy.py

* ruff
2026-05-22 19:11:38 +08:00
lingyun14
0711172fa7 Fix/stale command hints (#8245)
* Update stage.py

* fix: remove stale slash command hints

* fix: remove stale slash command hints

* fix: remove stale slash command hints

* Update openai_source.py
2026-05-21 21:45:57 +08:00
Weilong Liao
d15606d202 feat(password): add command to change AstrBot dashboard password (#8272)
closes: #8268
2026-05-21 21:37:10 +08:00
Yufeng He
c4693fa68e fix: support rst and adoc knowledge uploads (#8255) 2026-05-20 14:38:16 +08:00
Yufeng He
5bbcdced0f fix: skip empty llm summaries (#8195) 2026-05-19 09:38:55 +08:00
Soulter
d609f23b71 chore: bump version to 4.25.1 2026-05-17 15:01:59 +08:00
Soulter
a1e95081be feat: add random suffix for weixin and dingtalk id 2026-05-17 14:56:15 +08:00
Soulter
02291a3217 chore: bump version to 4.25.0 2026-05-16 01:39:04 +08:00
Yufeng He
1d69626421 fix: pass image inputs through active replies (#8119)
* fix(core): pass images through active replies

* fix: harden active reply image collection

* test: avoid logger coupling in active reply test

* Delete tests/unit/test_builtin_astrbot_main.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-05-16 01:34:03 +08:00
Tom8266
871b932785 fix: detect Tencent SILK (\x02 prefix) in audio magic bytes to avoid ffmpeg failure (#8009)
* fix: detect Tencent SILK (\x02 prefix) in audio magic bytes to avoid ffmpeg failure

QQ official bot sends voice in Tencent SILK format (leading \x02 byte before
#!SILK_V3 magic). _get_audio_magic_type() had two off-by-one slice errors:

  1. Standard SILK:  header[:8]  vs b'#!SILK_V3' (8 != 9 bytes) — never matched
  2. Tencent SILK:   not detected at all

Fixes:
  - Standard SILK:  header[:9]  == b'#!SILK_V3'   (correct 9-byte slice)
  - Tencent SILK:   header[:1] == b"\x02" and header[1:10] == b'#!SILK_V3'
  - ensure_wav() routes detected silk to tencent_silk_to_wav()

Before: QQ voice → ffmpeg → 'Invalid data found'
After:  QQ voice → magic detects silk → tencent_silk_to_wav → WAV OK

* refactor: use startswith() for SILK magic byte detection

Replace manual slice comparisons with startswith() — cleaner, less
error-prone, and immune to off-by-one slice errors.

Suggested by: sourcery-ai
2026-05-16 01:20:52 +08:00
Weilong Liao
c88025c2a3 feat(dingtalk): implement one-click QR registration and polling mechanism (#8198) 2026-05-15 18:43:21 +08:00
lingyun14
094aef6241 fix: drop **kwargs bug in two register funcs (#8141) 2026-05-15 17:00:03 +08:00
Weilong Liao
6982ef7d94 feat(weixin_oc): handle session timeout and clear login state (#8196) 2026-05-15 15:30:56 +08:00
千岚之夏
a09657e620 fix: handle MiniMax TTS timber weight configuration more robustly to avoid crashes on invalid or empty values
* fix: add comments and await asyncio.sleep(0) for startup signal

* fix: [Bug] 修复 MiniMax TTS 空字符串配置解析报错

* fix: 采纳AI审查建议,添日志+提取默认配置变量

* fix: 移除误加的core_lifecycle.py改动

---------

Co-authored-by: RainBot-Ai <qianlanzhiya@gmail.com>
2026-05-15 13:01:36 +08:00
Weilong Liao
aace90daab feat: supports scan QR code to configure feishu / lark (#8191)
* feat(lark): implement app registration and bot info retrieval

- Add app registration functionality for Lark and Feishu platforms, including endpoints and request handling.
- Introduce polling mechanism for app registration status.
- Create bot info retrieval functionality to fetch bot details after successful registration.
- Enhance dashboard with new UI components for one-click QR setup and manual setup options.
- Update internationalization files to support new features and actions.
- Add unit tests for app registration endpoint resolution and data handling.

* feat(weixin_oc): add WeChat login registration and QR code handling
2026-05-15 13:00:26 +08:00
Yufeng He
094c2de85a fix: surface weixin media send failures (#8175)
* fix: surface weixin media send failures

* fix: include weixin send failure context

* Delete tests/unit/test_weixin_oc_adapter.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-05-14 12:17:59 +08:00
counhopig
7d402fa16a fix: add ollama and nvidia embedding (#8104)
* fix: add ollama and nvidia embedding

* fix: address code review feedback for embedding providers

 - Remove redundant proxy branch in NvidiaEmbeddingProvider._get_client

 - Change ClientError handling to re-raise instead of wrapping in Exception

 - Add exc_info=True for better error diagnostics

 - Remove redundant isinstance check in OllamaEmbeddingProvider._build_payload
2026-05-14 12:16:35 +08:00
lingyun14
3a1d6c8f89 fix: handle None tool arguments from Claude API for no-parameter tools (#8136)
* fix: handle None tool arguments returned by Claude API for no-parameter tools

* fix: handle None tool arguments from Claude API for no-parameter tools

* fix: generalize None tool args comment

* fix: generalize None tool args comment

* 去除空格,以保证格式正确
2026-05-14 12:01:19 +08:00
Chang Lee
35f5d7e710 perf: enhance AMR audio quality and simplify opus logic (#8153)
* chore: streamline convert_audio_to_opus logic

- Route Opus conversion directly through the underlying convert_audio_format.
- Remove redundant FFmpeg processing chains to improve code reusability.

* perf: optimize AMR voice encoding parameters

- Enhance AMR audio quality via built-in FFmpeg filters.
2026-05-14 11:57:14 +08:00
Yufeng He
3290d75519 fix: prefer bundled dashboard over stale data dist (#8172)
* fix: prefer bundled dashboard over stale dist

* fix: harden dashboard dist version checks
2026-05-14 09:00:16 +08:00
Soulter
c77cb0f4e2 chore: bump version to 4.24.5 2026-05-14 01:16:26 +08:00
Soulter
0e6ad1c443 feat: cli supports ASTRBOT_DASHBOARD_INITIAL_PASSWORD env 2026-05-14 01:13:46 +08:00