feat: supports plugin to add skills (#7945)

* feat: supports plugin to add skills

* fix tests

* fix: fs tools

* Add tests for plugin skills handling and improve skill management

- Implement test for restricted local member reading plugin skill inventory even if the plugin is inactive.
- Ensure that the skill synchronization process retains built-in skills when local skills are empty, including proper handling of plugin paths.
- Update dashboard tests to verify that plugin details include components when requested.
- Enhance skill metadata enrichment tests to include inactive plugin-provided skills for inventory.
- Add filtering tests for plugin skills based on current configuration, ensuring only allowed plugins are considered and inactive plugins are skipped.

Co-authored-by: Copilot <copilot@github.com>

* fix: handle PPIO platform context-length error messages (#7888)

* fix: 压缩算法删除 user 消息 Bug 修复

* perf: improve truncate algo

* fix: improve context length error detection for PPIO platform compatibility

- Extend error detection to handle PPIO's error message format:
  'The input is longer than the model's context length'
- Add case-insensitive matching using .lower() for robustness
- Maintain backward compatibility with existing 'maximum context length' check

This fixes the issue where PPIO platform models (e.g., ppio/zai-org/glm-5-turbo)
would fail with AgentState.ERROR due to unrecognized context length errors.

---------

Co-authored-by: Soulter <905617992@qq.com>

* fix: 支持微信客服文件消息 (#7923)

* fix: 支持微信客服文件消息

* fix: remove WeCom file message placeholder

* fix(provider): fix Anthropic custom headers and system prompt compatibility (#7587)

* fix(provider): fix Anthropic custom headers and system prompt compatibility

- Pass custom_headers via AsyncAnthropic's `default_headers` parameter
  instead of creating a separate httpx.AsyncClient. This avoids
  `isinstance` check failures when multiple httpx installations exist
  on sys.path (e.g. bundled Python + system Python).

- Use list format for the `system` parameter (`[{"type": "text", ...}]`)
  instead of a plain string. The list format is supported by the official
  Anthropic API and is also compatible with third-party API proxies that
  reject the string format.

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

* fix(provider): fix Anthropic custom headers and system prompt compatibility

- Pass custom_headers via AsyncAnthropic's `default_headers` parameter
  instead of creating a separate httpx.AsyncClient. This avoids
  `isinstance` check failures when multiple httpx installations exist
  on sys.path (e.g. bundled Python + system Python).

- Use list format for the `system` parameter (`[{"type": "text", ...}]`)
  instead of a plain string. The list format is supported by the official
  Anthropic API and is also compatible with third-party API proxies that
  reject the string format.

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

* Add test unit

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* perf: improve logic of adding models

Co-authored-by: piexian <piexian@users.noreply.github.com>

* chore: remove redundant logger messages and improve log clarity

Co-authored-by: Copilot <copilot@github.com>

* chore: ruff format

* docs: update knowledge base docs

closes: #7962

* fix(#7907): send_message_to_user cron 场景下 session 容错 (#7911)

* fix: send_message_to_user cron 场景下 session 容错 (#7907)

- LLM 在主动场景可能只传 session_id 而非完整三段式,
from_str 失败时用 current_session 补全前两段。

Co-authored-by: Copilot <copilot@github.com>

* fix: 限制 session 补全仅对裸 session_id 生效,避免误修带冒号的错误输入 (#7907)

* feat: add session information to cron job payload

Co-authored-by: Copilot <copilot@github.com>

* fix: improve clarity and consistency of safety mode prompts

Co-authored-by: Copilot <copilot@github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>

* perf: tool rendering in conversation page (#7937)

* fix(dashboard): route conversation history tool messages through ToolCallCard

When viewing conversation history, large tool outputs (e.g. a single
git log --stat producing tens of KB) caused the browser renderer to
freeze. Root cause: formattedMessages mapped every role (including
tool / system / _checkpoint) into user/bot bubbles, and bot plain
strings went through markstream-vue's MarkdownRender. Single 88KB
tool messages plus 88-of-them adding up to ~349KB of synchronous
markdown parsing was enough to block the main thread for 5+ seconds.

This patch:

- Indexes tool-role messages by tool_call_id
- Filters formattedMessages to user/assistant only — tool, system and
  _checkpoint roles no longer render as standalone bubbles
- Converts assistant.tool_calls (OpenAI shape, with tc.name/tc.arguments
  fallbacks) into the existing tool_call MessagePart, attaching the
  paired result so MessageList's ToolCallCard renders it (default
  collapsed, no longer feeds large strings into the markdown renderer)
- Drops empty placeholder plain parts when an assistant message only
  carries tool_calls
- Sets ts/finished_ts to 0 as a sentinel: ToolCallCard.toolCallDuration
  returns "" when startTime <= 0, suppressing a misleading "0ms"
  duration that would otherwise appear because conversation history
  has no real timing data

Behavior change: tool results are now embedded in their assistant's
ToolCallCard.result instead of appearing as separate bot bubbles.
This matches the main chat UI's behavior.

Fixes #7929
Refs #7372 #7456

* style(dashboard): use single scrollbar in conversation history preview

ToolCallCard's result/args panes have their own max-height + overflow,
which produced a nested scrollbar when nested inside the history
preview's already-scrollable .conversation-messages-container. Override
those constraints inside the preview only — the outer 500px-bounded
container already provides scroll bounds, so a single scrollbar feels
cleaner. The main chat UI is unaffected.

---------

Co-authored-by: wanger <wanger@example.com>

* fix: ruff format

* feat: add python tool timeout param (#7953)

* feat: add python tool timeout param

* Update python.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>

* fix: 钉钉连接超时后自动重连失败 (#7924)

* fix: improve DingTalk adapter error handling in run() method

* fix: add retry logic for DingTalk SDK task unexpected exit

* fix: use task.add_done_callback to wake thread on task completion, handle UnboundLocalError

* refactor: extract retry logic into handle_retry helper function

---------

Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: leonforcode <leonbeyourside01@gmail.com>
Co-authored-by: AstralSolipsism <134063164+AstralSolipsism@users.noreply.github.com>
Co-authored-by: Pink YuDeer <wer00001@outlook.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: piexian <piexian@users.noreply.github.com>
Co-authored-by: NayukiMeko <ChibaNayuki@163.com>
Co-authored-by: wanger <122891289+10knamesmore@users.noreply.github.com>
Co-authored-by: wanger <wanger@example.com>
Co-authored-by: Haoran Xu <3230105281@zju.edu.cn>
Co-authored-by: 千岚之夏 <108566281+Blueteemo@users.noreply.github.com>
Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>
This commit is contained in:
Weilong Liao
2026-05-03 16:37:36 +08:00
committed by GitHub
co-authored by wanger Blueteemo Copilot leonforcode AstralSolipsism Pink YuDeer Claude Opus 4.6 piexian NayukiMeko wanger Haoran Xu 千岚之夏
parent 859ab28d43
commit f2370cd1ba
28 changed files with 3129 additions and 1602 deletions
+27
View File
@@ -61,6 +61,33 @@ You can add a `short_desc` field to `metadata.yaml` as the short description sho
short_desc: A one-line summary of your plugin.
```
### Bundle Skills with a Plugin (Optional)
Plugins can provide a `skills/` directory. After AstrBot loads the plugin, valid Skills inside that directory are automatically included in the Skill Manager, with their source shown as the plugin.
For multiple Skills, use this structure:
```text
your_plugin/
metadata.yaml
main.py
skills/
web-search-helper/
SKILL.md
report-writer/
SKILL.md
```
If `skills/` itself is one Skill, you can also place `SKILL.md` directly under it:
```text
your_plugin/
skills/
SKILL.md
```
In that case, the Skill name uses the plugin directory name. Plugin-provided Skills are managed by the plugin and appear as read-only sources in the WebUI Skills page. They can be enabled or disabled, but cannot be deleted or edited from Local Skills. When the plugin is uninstalled or updated, its bundled Skills change with the plugin files.
### Declare Supported Platforms (Optional)
You can add a `support_platforms` field (`list[str]`) to `metadata.yaml` to declare which platform adapters your plugin supports. The WebUI plugin page will display this field.
+2 -1
View File
@@ -76,11 +76,12 @@ When enabled:
- Admin users can use Shell, Python, file read, file write, file edit, and Grep search in `local` mode.
- Non-admin users cannot use Shell or Python.
- Non-admin users can only use file read, write, edit, and search inside restricted directories.
- Non-admin users can only use file read, write, edit, and search inside restricted directories. Plugin-provided Skills are read/search-only and cannot be written or edited.
Allowed directories for non-admin users in `local` mode include:
- `data/skills`
- `data/plugins/*/skills` (read-only, for plugin-provided Skills)
- Current session's `data/workspaces/{normalized_umo}`
- AstrBot temporary directories
- `.astrbot` under the system temporary directory
+27
View File
@@ -63,6 +63,33 @@ git clone 插件仓库地址
short_desc: 一句话介绍你的插件。
```
### 随插件提供 Skills(可选)
插件可以在自己的目录下提供 `skills/` 文件夹。AstrBot 加载插件后会自动把其中合法的 Skill 纳入 Skill Manager,来源会显示为对应插件。
推荐一个插件包含多个 Skill 时使用以下结构:
```text
your_plugin/
metadata.yaml
main.py
skills/
web-search-helper/
SKILL.md
report-writer/
SKILL.md
```
如果 `skills/` 本身就是一个 Skill,也可以直接放置:
```text
your_plugin/
skills/
SKILL.md
```
这种情况下 Skill 名称会使用插件目录名。插件提供的 Skill 由插件管理,在 WebUI 的 Skills 页面中作为只读来源展示;可以启用或禁用,但不能从本地 Skills 页面删除或编辑。插件卸载或更新后,对应 Skill 会随插件文件变化。
### 声明支持平台(Optional)
你可以在 `metadata.yaml` 中新增 `support_platforms` 字段(`list[str]`),声明插件支持的平台适配器。WebUI 插件页会展示该字段。
+27
View File
@@ -234,6 +234,33 @@ async def on_message(self, event: AstrMessageEvent):
short_desc: 一句话介绍你的插件。
```
### 随插件提供 Skills
插件可以在自己的目录下提供 `skills/` 文件夹。AstrBot 加载插件后会自动把其中合法的 Skill 纳入 Skill Manager,来源会显示为对应插件。
推荐一个插件包含多个 Skill 时使用以下结构:
```text
your_plugin/
metadata.yaml
main.py
skills/
web-search-helper/
SKILL.md
report-writer/
SKILL.md
```
如果 `skills/` 本身就是一个 Skill,也可以直接放置:
```text
your_plugin/
skills/
SKILL.md
```
这种情况下 Skill 名称会使用插件目录名。插件提供的 Skill 由插件管理,在 WebUI 的 Skills 页面中作为只读来源展示;可以启用或禁用,但不能从本地 Skills 页面删除或编辑。插件卸载或更新后,对应 Skill 会随插件文件变化。
### 声明支持平台(Optional)
你可以在 `metadata.yaml` 中新增 `support_platforms` 字段(`list[str]`),声明插件支持的平台适配器。WebUI 插件页会展示该字段。
+2 -1
View File
@@ -74,11 +74,12 @@ data/workspaces/{normalized_umo}/notes/todo.txt
- 管理员可以使用 `local` 模式下的 Shell、Python、文件读取、文件写入、文件编辑和 Grep 搜索。
- 非管理员不能使用 Shell 和 Python。
- 非管理员只能在受限目录内使用文件读取、写入、编辑和搜索。
- 非管理员只能在受限目录内使用文件读取、写入、编辑和搜索。插件内置 Skills 只允许读取和搜索,不允许写入或编辑。
非管理员在 `local` 模式下允许访问的目录包括:
- `data/skills`
- `data/plugins/*/skills`(只读,用于插件内置 Skills)
- 当前会话的 `data/workspaces/{normalized_umo}`
- AstrBot 的临时目录
- 系统临时目录中的 `.astrbot`