X Tutup
Skip to content

refactor(plugins): 重构插件安装流程,引入扩展中心架构#5798

Draft
whatevertogo wants to merge 18 commits intoAstrBotDevs:masterfrom
whatevertogo:codex/extension-hub-v1
Draft

refactor(plugins): 重构插件安装流程,引入扩展中心架构#5798
whatevertogo wants to merge 18 commits intoAstrBotDevs:masterfrom
whatevertogo:codex/extension-hub-v1

Conversation

@whatevertogo
Copy link
Contributor

@whatevertogo whatevertogo commented Mar 6, 2026

Motivation / 动机

重构插件安装流程,引入扩展中心架构,支持更安全、可控的插件安装确认机制。

原有插件安装直接执行,缺乏权限控制和确认流程。此次重构将插件安装能力统一纳入扩展管理框架,支持会话级确认、策略控制和 LLM 工具调用。

给予astrbot自主搜索安装插件的能力,通过他自己的搜索和安装,在用户输入"确认安装"之后可自动安装


Modifications / 改动点

插件安装流程重构:

  1. /plugin get 命令重构

    • 改用 ExtensionOrchestrator 处理安装请求
    • 支持会话级确认工作流(PENDING → 用户确认 → 执行)
    • 根据策略自动判断是否需要确认
  2. CLI astrbot plug search 增强

    • 使用新的 search_plugin_records 模块
    • 支持评分排序(精确匹配 > 前缀匹配 > 包含匹配)
    • 新增 --limit 参数控制结果数量
  3. 新增 astrbot/core/star/plugin_search.py

    • 带优先级的插件搜索算法
    • 主字段(name/display_name)优先于次字段(desc/author/repo)
    • 可配置的结果限制

扩展中心架构(本次一并引入):

  • astrbot/core/extensions/ - 扩展管理核心模块
  • astrbot/core/db/ - SQLite 持久化层
  • astrbot/builtin_stars/builtin_extension_hub/ - 内置扩展中心插件

测试覆盖:

  • tests/test_extension_hub.py - 集成测试(~680 行)

  • tests/unit/test_plugin_search.py - 插件搜索单元测试

  • tests/unit/test_cli_plugin_search.py - CLI 搜索测试

  • This is NOT a breaking change. / 这不是一个破坏性变更。


Screenshots or Test Results / 运行截图或测试结果

# 运行相关测试
pytest tests/unit/test_plugin_search.py tests/unit/test_cli_plugin_search.py -v

# 测试覆盖场景:
# - 插件搜索评分排序
# - CLI --limit 参数
# - 安装确认工作流

Checklist / 检查清单

  • 😊 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。/ If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
  • 👀 我的更改经过了良好的测试,并已在上方提供了"验证步骤"和"运行截图"。/ My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
  • 🤓 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到了 requirements.txtpyproject.toml 文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
  • 😮 我的更改没有引入恶意代码。/ My changes do not introduce malicious code.

whatevertogo and others added 10 commits March 6, 2026 01:54
- Implement extension orchestration system for plugins/skills/MCP
- Add pending operation management with database persistence
- Support installation confirmation via commands and natural language intent detection
- Add /extend command group (search/install/confirm/deny/pending)
- Add LLM tools for extension management
- Include comprehensive test coverage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n workflow

- Updated extension command methods to handle installation confirmation via conversation context.
- Enhanced error handling for unmatched quotes in command parsing.
- Modified database schema to include conversation_id for pending operations.
- Refactored orchestrator methods to manage installation requests based on conversation context.
- Adjusted dashboard routes and frontend components to support new confirmation flow.
- Updated unit tests to cover new functionality and ensure proper behavior.
Introduce a unified search result limiting mechanism across all extension
search interfaces. This allows users to control the number of results
returned and improves performance by reducing unnecessary data transfer.

- Add plugin_search module with scoring and limit logic
- Add --limit option to CLI search command
- Add limit parameter to /extend search command
- Add limit support in LLM tool and dashboard API
- Add search_result_limit config (default: 6)
- Add unit tests for search functionality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add deny_all and deny_for_conversation methods to orchestrator for
  flexible rejection scopes (conversation-level and global)
- Add ExtensionDenyTool and ExtensionDenyAllTool LLM tools for agent-
  initiated rejection workflows
- Improve search result formatting with description, version, and
  ready-to-use install commands
- Enhance pending confirmation messages with candidate metadata and
  clearer instructions
- Fix plugin adapter search to properly filter already-installed plugins
- Add operation_id prefix matching for shorter admin fallback commands
- Add permission checks allowing requesters to deny their own operations
- Update intent detection to handle conflicting confirm/deny keywords

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add documentation comments to explain the extension hub architecture:

- orchestrator.py: Module-level docstring explaining workflow, class docs
  for ExtensionAdapter, ExtensionCatalogService, ExtensionInstallOrchestrator,
  and method docs for install, confirm, deny operations
- llm_tools.py: Module-level docstring and class docs for each LLM tool
  (search, install, deny, deny_all) explaining their purpose and usage
- pending_operation.py: Module-level docstring explaining state lifecycle,
  class doc for PendingOperationService and key method docs

These comments document the features introduced in recent commits:
- 350fdf1: Extension Hub v1 initial implementation
- e64503c: Conversation-based confirmation workflow
- f3f79de: Configurable search result limit
- ef0bc37: Enhanced deny tools and user messaging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add documentation for:
- http_ssl_common.py: certifi-based SSL context builder
- http_ssl.py: thread-safe singleton SSL context
- runtime_bootstrap.py: aiohttp SSL patching at startup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move deny_words and confirm_words to class-level frozenset attributes
- Avoid recreating sets on every _detect_install_intent call
- Improves performance for frequent intent detection operations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract _target_key() and _candidate_data() helper methods
- Add mark_running/success/failed methods to PendingOperationService
- Replace direct db access with service methods (abstraction fix)
- Reduce repeated candidate data dict construction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 6, 2026 09:41
@whatevertogo whatevertogo marked this pull request as draft March 6, 2026 09:41
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @whatevertogo, your pull request is larger than the review limit of 150000 diff characters

@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Mar 6, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, 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 introduces a foundational 'Extension Hub' to streamline how AstrBot handles various types of extensions. It provides a consistent interface for users and AI agents to discover, install, and manage capabilities, moving towards a more modular and extensible architecture. The changes enhance security and control through policy enforcement and a conversational confirmation mechanism for installations, ensuring that new functionalities are integrated safely and intentionally.

Highlights

  • Unified Extension Management: Introduced a new 'Extension Hub' module (astrbot/core/extensions/) to centralize the search, installation, and management of various extensions, including plugins, skills, and future MCPs.
  • Chat-based Extension Commands: Added new /extension commands (ExtensionCommands) allowing users to search for, install, confirm, deny, and view pending extension operations directly through chat.
  • AI Agent Integration with LLM Tools: Integrated dedicated LLM tools (astrbot_extension_search, astrbot_extension_install, astrbot_extension_deny, astrbot_extension_deny_all) to empower AI agents to interact with and manage extensions dynamically.
  • Policy-driven Installation Workflow: Implemented a robust policy engine (ExtensionPolicyEngine) to control extension installation permissions based on roles and configurations, including a confirmation workflow for non-allowlisted extensions.
  • Persistent Pending Operations: Introduced a new PendingOperation database model and service to manage and persist extension installation requests that require user confirmation, ensuring statefulness across sessions.
  • Enhanced Plugin Search: Improved plugin search functionality in both the CLI and Dashboard, incorporating backend filtering, scoring, and configurable result limits for more relevant and controlled search results.
Changelog
  • astrbot/builtin_stars/builtin_commands/commands/init.py
    • Imported and exposed ExtensionCommands.
  • astrbot/builtin_stars/builtin_commands/commands/extension.py
    • Added new file defining ExtensionCommands for chat-based extension management (search, install, confirm, deny, pending).
  • astrbot/builtin_stars/builtin_commands/commands/plugin.py
    • Modified plugin installation to use the new Extension Hub orchestrator, enabling confirmation workflows.
  • astrbot/builtin_stars/builtin_commands/main.py
    • Integrated ExtensionCommands and added logic for natural language intent detection for extension installation confirmation/rejection.
  • astrbot/cli/commands/cmd_plug.py
    • Updated plugin search to use shared backend logic and added a --limit option.
  • astrbot/core/astr_main_agent.py
    • Imported and applied new Extension Hub LLM tools to the main agent's toolset.
  • astrbot/core/config/default.py
    • Added new configuration section for extension_install settings, including policy, limits, and TTLs.
  • astrbot/core/db/init.py
    • Imported PendingOperation model and added abstract methods for its CRUD operations to BaseDatabase.
  • astrbot/core/db/po.py
    • Defined the PendingOperation SQLModel for persisting extension installation requests.
  • astrbot/core/db/sqlite.py
    • Implemented concrete CRUD methods for PendingOperation in the SQLite database and added schema migration for the new table.
  • astrbot/core/extensions/init.py
    • Added new file to define the extensions package, exposing core components.
  • astrbot/core/extensions/adapters.py
    • Added new file defining adapters for different extension kinds (Plugin, Skill, McpTodo) to standardize search and install logic.
  • astrbot/core/extensions/llm_tools.py
    • Added new file defining LLM tools (ExtensionSearchTool, ExtensionInstallTool, ExtensionDenyTool, ExtensionDenyAllTool) for AI agent interaction with the Extension Hub.
  • astrbot/core/extensions/model.py
    • Added new file defining data models for Extension Hub, including ExtensionKind, InstallRequest, InstallCandidate, InstallResult, PolicyAction, PolicyDecision.
  • astrbot/core/extensions/orchestrator.py
    • Added new file implementing the ExtensionInstallOrchestrator for coordinating extension installation, policy enforcement, and confirmation workflows.
  • astrbot/core/extensions/pending_operation.py
    • Added new file implementing PendingOperationService for managing the lifecycle of pending extension installation requests.
  • astrbot/core/extensions/policy.py
    • Added new file implementing ExtensionPolicyEngine for evaluating installation policies based on configuration and requester roles.
  • astrbot/core/extensions/runtime.py
    • Added new file providing runtime initialization and access to the ExtensionInstallOrchestrator, including a cleanup task for expired pending operations.
  • astrbot/core/star/plugin_search.py
    • Added new file with utility functions for plugin search, including normalization, scoring, and filtering.
  • astrbot/core/utils/http_ssl.py
    • Updated comments to clarify the purpose and design of the shared SSL context.
  • astrbot/dashboard/routes/plugin.py
    • Modified plugin market list and install endpoints to integrate with the new Extension Hub, including search filtering and pending install handling.
  • astrbot/utils/http_ssl_common.py
    • Updated comments to clarify the purpose and usage of the SSL context building utility.
  • dashboard/src/views/alkaid/KnowledgeBase.vue
    • Updated plugin installation feedback to handle pending status from the backend.
  • dashboard/src/views/extension/useExtensionPage.js
    • Updated extension installation logic to handle pending status and added provider field to install requests.
  • runtime_bootstrap.py
    • Updated comments to clarify the purpose and usage of the runtime SSL bootstrap.
  • tests/test_dashboard.py
    • Modified dashboard plugin installation tests to account for the new pending confirmation flow and added a test for backend plugin market filtering.
  • tests/test_extension_hub.py
    • Added new file with comprehensive integration tests for the Extension Hub, covering policy, pending operations, orchestrator flows, and adapter interactions.
  • tests/unit/test_cli_plugin_search.py
    • Added new file with a unit test for CLI plugin search using the shared backend ranking.
  • tests/unit/test_extension_confirmation_intent.py
    • Added new file with unit tests for natural language intent detection for extension confirmation/rejection.
  • tests/unit/test_extension_hub_tools.py
    • Added new file with unit tests for the Extension Hub LLM tools, verifying their application and call behavior.
  • tests/unit/test_plugin_search.py
    • Added new file with unit tests for plugin search utility functions, covering normalization, scoring, and filtering.
Activity
  • A new core module, astrbot/core/extensions/, was created to house the Extension Hub's components.
  • A new database model, PendingOperation, was introduced to persist installation requests requiring confirmation.
  • A new /extension command was added, enabling chat-based management of extensions.
  • LLM tools for the Extension Hub were registered with the main agent, allowing AI to manage extensions.
  • The CLI plugin search functionality was enhanced with new backend logic and options.
  • The Dashboard API for plugin management was updated to integrate with the new Extension Hub features.
  • Extensive test coverage, including approximately 680 lines of integration tests, was added for the new functionality.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot bot added the feature:plugin The bug / feature is about AstrBot plugin system. label Mar 6, 2026
@dosubot
Copy link

dosubot bot commented Mar 6, 2026

Related Documentation

1 document(s) may need updating based on files changed in this PR:

AstrBotTeam's Space

pr4697的改动

[Accept] [Decline]

Note: You must be authenticated to accept/decline updates.

How did I do? Any feedback?  Join Discord

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements “Extension Hub v1” for AstrBot to provide a unified extension (currently plugin-focused) search/install workflow with policy enforcement and a pending-confirmation mechanism, integrated into the agent, dashboard, CLI, and chat commands.

Changes:

  • Added core Extension Hub module (orchestrator/adapters/policy/pending-operation/runtime + LLM tools).
  • Integrated extension install/search into Dashboard API/UI, CLI, and built-in /extend chat commands (including natural-language confirm/deny).
  • Added DB persistence for pending operations and accompanying integration/unit tests.

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/unit/test_plugin_search.py Verifies plugin search normalization/ranking/limit behavior.
tests/unit/test_extension_hub_tools.py Tests Extension Hub tool registration + deny/deny_all tool execution.
tests/unit/test_extension_confirmation_intent.py Tests multilingual confirm/deny intent detection helpers.
tests/unit/test_cli_plugin_search.py Ensures CLI search ordering uses shared ranking backend.
tests/test_extension_hub.py End-to-end coverage for policy/pending lifecycle/orchestrator flows/adapters.
tests/test_dashboard.py Updates dashboard plugin install test to handle pending confirmation + adds market query test.
runtime_bootstrap.py Adds runtime bootstrap to patch aiohttp SSL context to use certifi bundle.
dashboard/src/views/extension/useExtensionPage.js Handles pending install UI state + sends provider field + guards readme view.
dashboard/src/views/alkaid/KnowledgeBase.vue Handles pending status when installing plugin from KnowledgeBase view.
astrbot/utils/http_ssl_common.py Introduces shared certifi-backed SSLContext builder utility.
astrbot/dashboard/routes/plugin.py Adds market list query/limit filtering and routes plugin install through orchestrator.
astrbot/core/utils/http_ssl.py Switches to thread-safe singleton SSLContext built via shared helper.
astrbot/core/star/plugin_search.py Adds reusable plugin record normalization + scoring + payload filtering utilities.
astrbot/core/extensions/runtime.py Provides orchestrator singleton + periodic pending-expiry cleanup task wiring.
astrbot/core/extensions/policy.py Adds policy engine for role/allowlist/blocklist/confirmation decisions.
astrbot/core/extensions/pending_operation.py Adds pending operation service (create/query/expire/start/reject).
astrbot/core/extensions/orchestrator.py Adds install/search orchestration with locks + confirmation/deny flows.
astrbot/core/extensions/model.py Adds core Extension Hub data models/enums.
astrbot/core/extensions/llm_tools.py Adds LLM-callable tools for search/install/deny/deny_all.
astrbot/core/extensions/adapters.py Adds plugin/skill/MCP adapters + plugin market cache search integration.
astrbot/core/extensions/init.py Exposes Extension Hub public API surface.
astrbot/core/db/sqlite.py Adds pending_operations schema migration helper + CRUD/query APIs.
astrbot/core/db/po.py Adds PendingOperation SQLModel definition.
astrbot/core/db/init.py Adds BaseDatabase abstract methods for pending operations.
astrbot/core/config/default.py Adds default provider_settings.extension_install configuration block.
astrbot/core/astr_main_agent.py Registers Extension Hub tools into the main agent toolset.
astrbot/cli/commands/cmd_plug.py Implements CLI plugin search using shared ranking + adds --limit.
astrbot/builtin_stars/builtin_commands/main.py Adds /extend commands and natural-language confirm/deny handler.
astrbot/builtin_stars/builtin_commands/commands/plugin.py Routes /plugin get install through orchestrator with pending support.
astrbot/builtin_stars/builtin_commands/commands/extension.py Adds /extend search/install/confirm/deny/pending command implementations.
astrbot/builtin_stars/builtin_commands/commands/init.py Exports ExtensionCommands.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive Extension Hub feature, providing a unified mechanism for installing and managing extensions like plugins and skills. The implementation is well-structured, covering installation orchestration, policy enforcement, and a confirmation workflow with database persistence. The integration with existing commands and the addition of new LLM tools are well-executed. I've included a few suggestions to improve code clarity, performance, and robustness, all of which align with the repository's guidelines.

Note: Security Review did not run due to the size of the PR.

I am having trouble creating individual review comments. Click here to see my feedback.

astrbot/builtin_stars/builtin_commands/commands/extension.py (225-251)

medium

The logic for handling conversation-level denials is duplicated. The case for no arguments (if not operation_id_or_token.strip()) and the case for an explicit "conversation" argument both call orchestrator.deny_for_conversation with the same parameters. You can combine these conditions to make the code more concise and avoid repetition.

        if not operation_id_or_token.strip() or normalized in {
            "conversation",
            "current",
            "--conversation",
        }:
            result = await orchestrator.deny_for_conversation(
                conversation_id=event.unified_msg_origin,
                actor_id=event.get_sender_id(),
                actor_role=event.role,
                reason="rejected by command",
            )
        elif normalized in {"all", "--all"}:
            result = await orchestrator.deny_all(
                actor_id=event.get_sender_id(),
                actor_role=event.role,
                reason="rejected by command",
            )
        else:
            result = await orchestrator.deny(
                operation_id_or_token=operation_id_or_token.strip(),
                actor_id=event.get_sender_id(),
                actor_role=event.role,
                reason="rejected by command",
            )

astrbot/builtin_stars/builtin_commands/main.py (67-68)

medium

The list of punctuations is created on every call, and iterating with replace can be inefficient. For better performance, you can use str.translate with a pre-built translation table. This is generally faster for multiple character replacements.

        translation_table = str.maketrans(",.!?,。!?;;::", "             ")
        text = text.translate(translation_table)

astrbot/core/extensions/adapters.py (202-205)

medium

Using os.getpid() to create a temporary filename is not fully safe against race conditions, especially if the same process calls this function concurrently for URLs with the same basename. It's better to use a UUID to generate a truly unique filename. This avoids potential file overwrites or read/write conflicts. Please also move the import uuid to the top of the file.

        import uuid
        dest = (
            temp_dir
            / f"skill_install_{uuid.uuid4().hex}_{Path(urlparse(url).path).name or 'skill.zip'}"
        )

@whatevertogo whatevertogo changed the title feat:extension hub v1 refactor(plugins): 重构插件安装流程,引入扩展中心架构 Mar 7, 2026
@whatevertogo whatevertogo marked this pull request as ready for review March 7, 2026 05:34
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @whatevertogo, your pull request is larger than the review limit of 150000 diff characters

@whatevertogo whatevertogo marked this pull request as draft March 7, 2026 06:01
@whatevertogo whatevertogo marked this pull request as ready for review March 8, 2026 12:13
@auto-assign auto-assign bot requested a review from anka-afk March 8, 2026 12:13
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @whatevertogo, your pull request is larger than the review limit of 150000 diff characters

@whatevertogo whatevertogo marked this pull request as draft March 8, 2026 13:02
@whatevertogo
Copy link
Contributor Author

没写完,可配置项还没放到前端

…n options and command handling

- Removed ExtensionCommands and related command handling from the codebase.
- Introduced configuration options for extension installation, including enabling/disabling installation, default modes, and allow/block lists.
- Updated various components to check if extension installation is enabled before proceeding with related operations.
- Modified plugin installation logic to reflect the new extension installation flow.
- Added tests to ensure the correct behavior of the new extension installation features and configuration metadata.
@whatevertogo whatevertogo marked this pull request as ready for review March 9, 2026 17:16
@auto-assign auto-assign bot requested a review from Fridemn March 9, 2026 17:16
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @whatevertogo, your pull request is larger than the review limit of 150000 diff characters

- Consolidated confirmation and denial keywords in configuration from lists to single string values for clarity.
- Updated related metadata and hints in configuration files to reflect the new structure.
- Enhanced the extension policy engine to evaluate installation requests based on author rules without requiring identifiers.
- Improved the user interface for template list editors to focus on author-based rules.
- Added tests to ensure the new confirmation keyword handling works as expected and that policies are correctly applied.
- Adjusted the chat route to handle exceptions more gracefully during streaming.
@whatevertogo whatevertogo marked this pull request as draft March 9, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature:plugin The bug / feature is about AstrBot plugin system. size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

X Tutup