Conversation
* add bocha web search tool * Revert "add bocha web search tool" This reverts commit 1b36d75. * add bocha web search tool * fix: correct temporary_cache spelling and update supported tools for web search * ruff --------- Co-authored-by: Soulter <905617992@qq.com>
) * fix: messages[x] assistant content must contain at least one part fixes: #4876 * ruff format
… audio and video processing (#4938) * feat: implement media file handling utilities for audio and video processing * feat: refactor file upload handling for audio and video in LarkMessageEvent * feat: add cleanup for failed audio and video conversion outputs in media_utils * feat: add utility methods for sending messages and uploading files in LarkMessageEvent
* perf: optimize webchat and wecom ai queue lifecycle * perf: enhance webchat back queue management with conversation ID support
* fix: localize provider source ui * feat: localize provider metadata keys * chore: add provider metadata translations * chore: format provider i18n changes * fix: preserve metadata fields in i18n conversion * fix: internationalize platform config and dialog * fix: add Weixin official account platform icon --------- Co-authored-by: Soulter <905617992@qq.com>
* feat: 添加 Provider 级别代理支持及请求失败日志 * refactor: simplify provider source configuration structure * refactor: move env proxy fallback logic to log_connection_failure * refactor: update client proxy handling and add terminate method for cleanup * refactor: update no_proxy configuration to remove redundant subnet --------- Co-authored-by: Soulter <905617992@qq.com>
…4887) * feat(backend): add permission update api * feat(useCommandActions): add updatePermission action and translations * feat(dashboard): implement permission editing ui * style: fix import sorting in command.py * refactor(backend): extract permission update logic to service * feat(i18n): add success and failure messages for command updates --------- Co-authored-by: Soulter <905617992@qq.com>
* feat: 允许 LLM 预览工具返回的图片并自主决定是否发送 * 复用 send_message_to_user 替代独立的图片发送工具 * feat: implement _HandleFunctionToolsResult class for improved tool response handling * docs: add path handling guidelines to AGENTS.md --------- Co-authored-by: Soulter <905617992@qq.com>
* feat(telegram): 添加媒体组(相册)支持 / add media group (album) support ## 功能说明 支持 Telegram 的媒体组消息(相册),将多张图片/视频合并为一条消息处理,而不是分散成多条消息。 ## 主要改动 ### 1. 初始化媒体组缓存 (__init__) - 添加 `media_group_cache` 字典存储待处理的媒体组消息 - 使用 2.5 秒超时收集媒体组消息(基于社区最佳实践) - 最大等待时间 10 秒(防止永久等待) ### 2. 消息处理流程 (message_handler) - 检测 `media_group_id` 判断是否为媒体组消息 - 媒体组消息走特殊处理流程,避免分散处理 ### 3. 媒体组消息缓存 (handle_media_group_message) - 缓存收到的媒体组消息 - 使用 APScheduler 实现防抖(debounce)机制 - 每收到新消息时重置超时计时器 - 超时后触发统一处理 ### 4. 媒体组合并处理 (process_media_group) - 从缓存中取出所有媒体项 - 使用第一条消息作为基础(保留文本、回复等信息) - 依次添加所有图片、视频、文档到消息链 - 将合并后的消息发送到处理流程 ## 技术方案论证 Telegram Bot API 在处理媒体组时的设计限制: 1. 将媒体组的每个消息作为独立的 update 发送 2. 每个 update 带有相同的 `media_group_id` 3. **不提供**组的总数、结束标志或一次性完整组的机制 因此,bot 必须自行收集消息,并通过硬编码超时(timeout/delay)等待可能延迟到达的消息。 这是目前唯一可靠的方案,被官方实现、主流框架和开发者社区广泛采用。 ### 官方和社区证据: - **Telegram Bot API 服务器实现(tdlib)**:明确指出缺少结束标志或总数信息 tdlib/telegram-bot-api#643 - **Telegram Bot API 服务器 issue**:讨论媒体组处理的不便性,推荐使用超时机制 tdlib/telegram-bot-api#339 - **Telegraf(Node.js 框架)**:专用媒体组中间件使用 timeout 控制等待时间 https://github.com/DieTime/telegraf-media-group - **StackOverflow 讨论**:无法一次性获取媒体组所有文件,必须手动收集 https://stackoverflow.com/questions/50180048/telegram-api-get-all-uploaded-photos-by-media-group-id - **python-telegram-bot 社区**:确认媒体组消息单独到达,需手动处理 python-telegram-bot/python-telegram-bot#3143 - **Telegram Bot API 官方文档**:仅定义 `media_group_id` 为可选字段,不提供获取完整组的接口 https://core.telegram.org/bots/api#message ## 实现细节 - 使用 2.5 秒超时收集媒体组消息(基于社区最佳实践) - 最大等待时间 10 秒(防止永久等待) - 采用防抖(debounce)机制:每收到新消息重置计时器 - 利用 APScheduler 实现延迟处理和任务调度 ## 测试验证 - ✅ 发送 5 张图片相册,成功合并为一条消息 - ✅ 保留原始文本说明和回复信息 - ✅ 支持图片、视频、文档混合的媒体组 - ✅ 日志显示 Processing media group <media_group_id> with 5 items ## 代码变更 - 文件:astrbot/core/platform/sources/telegram/tg_adapter.py - 新增代码:124 行 - 新增方法:handle_media_group_message(), process_media_group() Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * refactor(telegram): 优化媒体组处理性能和可靠性 根据代码审查反馈改进: 1. 实现 media_group_max_wait 防止无限延迟 - 跟踪媒体组创建时间,超过最大等待时间立即处理 - 最坏情况下 10 秒内必定处理,防止消息持续到达导致无限延迟 2. 移除手动 job 查找优化性能 - 删除 O(N) 的 get_jobs() 循环扫描 - 依赖 replace_existing=True 自动替换任务 3. 重用 convert_message 减少代码重复 - 统一所有媒体类型转换逻辑 - 未来添加新媒体类型只需修改一处 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix(telegram): handle missing message in media group processing and improve logging messages --------- Co-authored-by: Ubuntu <ubuntu@localhost.localdomain> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Soulter <905617992@qq.com>
* feat: add desktop wrapper with frontend-only packaging * docs: add desktop build docs and track dashboard lockfile * fix: track desktop lockfile for npm ci * fix: allow custom install directory for windows installer * chore: migrate desktop workflow to pnpm * fix(desktop): build AppImage only on Linux * fix(desktop): harden packaged startup and backend bundling * fix(desktop): adapt packaged restart and plugin dependency flow * fix(desktop): prevent backend respawn race on quit * fix(desktop): prefer pyproject version for desktop packaging * fix(desktop): improve startup loading UX and reduce flicker * ci: add desktop multi-platform release workflow * ci: fix desktop release build and mac runner labels * ci: disable electron-builder auto publish in desktop build * ci: avoid electron-builder publish path in build matrix * ci: normalize desktop release artifact names * ci: exclude blockmap files from desktop release assets * ci: prefix desktop release assets with AstrBot and purge blockmaps * feat: add electron bridge types and expose backend control methods in preload script * Update startup screen assets and styles - Changed the icon from PNG to SVG format for better scalability. - Updated the border color from #d0d0d0 to #eeeeee for a softer appearance. - Adjusted the width of the startup screen from 460px to 360px for improved responsiveness. * Update .gitignore to include package.json * chore: remove desktop gitkeep ignore exceptions * docs: update desktop troubleshooting for current runtime behavior * refactor(desktop): modularize runtime and harden startup flow --------- Co-authored-by: Soulter <905617992@qq.com> Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
* chore: auto fix by ruff * refactor: 统一修正返回类型注解为 None/bool 以匹配实现 * refactor: 将 _get_next_page 改为异步并移除多余的请求错误抛出 * refactor: 将 get_client 的返回类型改为 object * style: 为 LarkMessageEvent 的相关方法添加返回类型注解 None --------- Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
* Initial plan * feat: add delete button to persona management dialog - Added delete button to PersonaForm dialog (only visible when editing) - Implemented deletePersona method with confirmation dialog - Connected delete event to PersonaManager for proper handling - Button positioned on left side of dialog actions for clear separation - Uses existing i18n translations for delete button and messages Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com> * fix: use finally block to ensure saving state is reset - Moved `this.saving = false` to finally block in deletePersona - Ensures UI doesn't stay in saving state after errors - Follows best practices for state management Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
…deo, audio message type (#4986)
* fix: handle pip install execution in frozen runtime * fix: harden pip subprocess fallback handling
* fix(dashboard): preserve custom GitHub proxy setting on reload * fix(dashboard): keep github proxy selection persisted in settings
* fix: ensure tool call/response pairing in context truncation * refactor: simplify fix_messages to single-pass state machine
fix(persona): preserve conversation persona_id and unify session/conversation resolution
- Implemented a new composable `useExtensionPage` to handle various functionalities related to plugin management, including fetching extensions, handling updates, and managing UI states. - Added support for conflict checking, plugin installation, and custom source management. - Integrated search and filtering capabilities for plugins in the market. - Enhanced user experience with dialogs for confirmations and notifications. - Included pagination and sorting features for better plugin visibility.
… Platform (#5445) * fix: clear markdown field when sending media messages via QQ Official API * refactor: use pop() to remove markdown key instead of setting None
…vider (#5442) * fix(dashboard): 强化 API Key 复制临时节点清理逻辑 * fix(embedding): 自动检测改为探测 OpenAI embedding 最大可用维度 * fix: normalize openai embedding base url and add hint key * i18n: add embedding_api_base hint translations * i18n: localize provider embedding/proxy metadata hints * fix: show provider-specific embedding API Base URL hint as field subtitle * fix(embedding): cap OpenAI detect_dim probes with early short-circuit * fix(dashboard): return generic error on provider adapter import failure * 回退检测逻辑
* refactor: 修正 Sqlite 查询、下载回调、接口重构与类型调整 * feat: 为 OneBotClient 增加 CallAction 协议与异步调用支持
* perf: batch metadata query in KB retrieval to fix N+1 problem Replace N sequential get_document_with_metadata() calls with a single get_documents_with_metadata_batch() call using SQL IN clause. Benchmark results (local SQLite): - 10 docs: 10.67ms → 1.47ms (7.3x faster) - 20 docs: 26.00ms → 2.68ms (9.7x faster) - 50 docs: 63.87ms → 2.79ms (22.9x faster) * refactor: use set[str] param type and chunk IN clause for SQLite safety Address review feedback: - Change doc_ids param from list[str] to set[str] to avoid unnecessary conversion - Chunk IN clause into batches of 900 to stay under SQLite's 999 parameter limit - Remove list() wrapping at call site, pass set directly
#5462) * fix:fix the issue where incomplete cleanup of residual plugins occurs in the failed loading of plugins * fix:ruff format,apply bot suggestions * Apply suggestion from @gemini-code-assist[bot] Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* feat: implement websockets transport mode selection for chat - Added transport mode selection (SSE/WebSocket) in the chat component. - Updated conversation sidebar to include transport mode options. - Integrated transport mode handling in message sending logic. - Refactored message sending functions to support both SSE and WebSocket. - Enhanced WebSocket connection management and message handling. - Updated localization files for transport mode labels. - Configured Vite to support WebSocket proxying. * feat(webchat): refactor message parsing logic and integrate new parsing function * feat(chat): add websocket API key extraction and scope validation
There was a problem hiding this comment.
Pull request overview
This pull request synchronizes changes from the main branch into the current branch. The changes include refactoring the Star plugin architecture, improving type annotations across the codebase, standardizing temporary file handling, and updating various provider implementations.
Changes:
- Refactored Star plugin system by extracting base class to separate module for better modularity
- Added comprehensive return type annotations (
-> None) to methods across the codebase - Standardized temporary file path handling using
get_astrbot_temp_path()utility - Updated multiple provider implementations with proxy support, proper cleanup, and improved error handling
Reviewed changes
Copilot reviewed 204 out of 427 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| astrbot/core/star/base.py | Extracted Star base class from init.py with improved context handling |
| astrbot/core/star/init.py | Simplified imports by moving Star class definition to base.py |
| astrbot/core/provider/sources/*.py | Added return type annotations, proxy support, and terminate methods |
| astrbot/core/utils/temp_dir_cleaner.py | Added (referenced but not shown in diff) |
| Multiple platform adapters | Added proper return type annotations to async methods |
| Multiple agent/tool files | Improved type safety with return type hints |
| name: str | ||
|
|
||
| class _ContextLike(Protocol): | ||
| def get_config(self, umo: str | None = None) -> Any: ... |
There was a problem hiding this comment.
The parameter name umo is ambiguous and unclear. Consider renaming to a more descriptive name like unified_msg_origin or adding a docstring to clarify what this parameter represents.
| def get_config(self, umo: str | None = None) -> Any: ... | |
| def get_config(self, unified_msg_origin: str | None = None) -> Any: ... |
| temp_dir = get_astrbot_temp_path() | ||
| path = os.path.join( | ||
| temp_dir, | ||
| f"whisper_selfhost_{uuid.uuid4().hex[:8]}.input", | ||
| ) |
There was a problem hiding this comment.
The filename prefix "whisper_selfhost_" is inconsistent with "whisper_selfhosted_" used elsewhere. Consider using "whisper_selfhosted_" for consistency.
| provider_settings, | ||
| *, | ||
| use_api_key: bool = True, | ||
| ) -> None: |
There was a problem hiding this comment.
The use_api_key parameter appears to change initialization behavior but its purpose is unclear without documentation. Consider adding a docstring to explain when and why this parameter should be False.
| ) -> None: | |
| ) -> None: | |
| """ | |
| Initialize the Anthropic provider adapter. | |
| Parameters | |
| ---------- | |
| provider_config : | |
| Provider configuration dictionary. Typically contains keys such as | |
| ``api_base``, ``timeout``, ``anth_thinking_config``, and any proxy | |
| settings required to reach the Anthropic API. | |
| provider_settings : | |
| Global or shared settings passed down from the AstrBot provider | |
| system. | |
| use_api_key : bool, optional | |
| Whether to automatically initialize an authenticated Anthropic | |
| client using the API keys managed by the base :class:`Provider`. | |
| When ``True`` (default), :meth:`_init_api_key` is called during | |
| construction, which selects an API key and creates an | |
| :class:`AsyncAnthropic` client. | |
| Set this to ``False`` when you need to defer or override client | |
| initialization (for example, when injecting a preconfigured or | |
| mocked client in tests, or when another component is responsible | |
| for managing authentication and HTTP clients). In that case no | |
| Anthropic client is created here, and you are responsible for | |
| configuring ``self.client`` before making requests. | |
| """ |
| cls._instance._initialized = False | ||
| return cls._instance | ||
|
|
||
| def __init__(self) -> None: | ||
| if self._initialized: |
There was a problem hiding this comment.
Setting _initialized as an instance attribute in __new__ before __init__ runs could lead to confusion. Consider using a class-level tracking mechanism or documenting this pattern clearly, as it's a non-standard singleton implementation.
| cls._instance._initialized = False | |
| return cls._instance | |
| def __init__(self) -> None: | |
| if self._initialized: | |
| return cls._instance | |
| def __init__(self) -> None: | |
| if getattr(self, "_initialized", False): |
| def flush_pending_if_valid() -> None: | ||
| nonlocal pending_assistant, pending_tools | ||
| if pending_assistant is not None and pending_tools: | ||
| fixed_messages.append(pending_assistant) | ||
| fixed_messages.extend(pending_tools) | ||
| pending_assistant = None | ||
| pending_tools = [] |
There was a problem hiding this comment.
The nested function flush_pending_if_valid modifies outer scope variables. While correct, consider extracting this logic to a private method or adding a comment explaining the state management pattern for better maintainability.
| # try: | ||
| # os.remove(local_path) | ||
| # except Exception as e: | ||
| # logger.error(f"Error removing temp file {local_path}: {e}") |
There was a problem hiding this comment.
Commented-out code for removing temporary files should either be removed or documented with a clear reason for disabling. The comment "remove" on line 193 suggests this was intentional, but leaving cleanup code commented increases tech debt.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request primarily focuses on upgrading the Python environment, expanding web search options, and enhancing agent stability and message processing. It introduces new features for managing active agent tasks, improves the reliability of quoted message parsing, and adds a secure API key management system. Additionally, it updates all documentation to reflect these significant changes and new deployment methods. Highlights
Changelog
Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Modifications / 改动点
Screenshots or Test Results / 运行截图或测试结果
Checklist / 检查清单
requirements.txt和pyproject.toml文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations inrequirements.txtandpyproject.toml.