* 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>
* feat(skills): enhance skill installation to support multiple top-level folders and add duplicate handling
closes: #6949
* refactor(skill_manager): streamline skill name normalization and validation logic
* fix(skill_manager): update skill name regex to allow underscores in skill names
* fix(skill_manager): improve skill name normalization and validation logic
* fix(skills): use actual sandbox path from cache instead of hardcoded workspace root
Fixes#6273
When using Shipyard booter, the sandbox workspace directory is
`/home/ship_{session_id}/workspace/` instead of the hardcoded `/workspace`.
This caused Agent to fail reading SKILL.md files with 'No such file or directory'.
Changes:
- In build_skills_prompt: prefer skill.path (from sandbox cache) over
hardcoded SANDBOX_WORKSPACE_ROOT for sandbox_only skills
- In list_skills: always prefer sandbox_cached_paths over hardcoded path
for sandbox_only skills
The actual path is resolved at sandbox scan time via Path.resolve() in
_build_scan_command, which returns the correct absolute path based on
the sandbox's actual working directory.
* docs: add comment explaining show_sandbox_path behavior for sandbox_only skills
Address Sourcery AI review comment:
- Clarify that show_sandbox_path is implicitly True for sandbox_only skills
- Explain why the flag is effectively ignored (no local path exists)
* refactor: simplify path_str fallback using or operator
Address review feedback: use single-line fallback instead of if-not pattern.
* style: format skill_manager.py with ruff
Fix ruff format-check failure
* fix(skills): sanitize cached sandbox skill paths
Normalize sandbox cache paths before reading or writing them so invalid,
empty, or mismatched entries fall back to a safe default SKILL.md path.
This avoids using malformed cached paths, keeps path rendering
consistent, and ensures sandbox skill listings always point to the
expected workspace location.
---------
Co-authored-by: ccsang <ccsang@users.noreply.github.com>
Co-authored-by: RC-CHN <1051989940@qq.com>
There is an issue with reading the skill directory on the Windows system, which results in a high probability of files under the skill directory being unrecognizable, now fix it.
* feat(skills): add batch upload functionality for multiple skill ZIP files
- Implemented a new endpoint for batch uploading skills.
- Enhanced the SkillsSection component to support multiple file selection and drag-and-drop functionality.
- Updated localization files for new upload features and messages.
- Added tests to validate batch upload behavior and error handling.
* feat(skills): improve batch upload handling and enhance accessibility for dropzone
* feat(skills): enhance batch upload process and improve UI for better user experience
* feat(skills): enhance skills upload dialog layout and styling for improved usability
* feat(skills): update upload dialog description styling for better visibility and usability
* feat(skills): improve upload dialog button styling and layout for enhanced usability
* feat(skills): refine upload dialog text for clarity and consistency
* feat(skills): enhance batch upload functionality by ignoring __MACOSX entries and improving upload dialog styling
* feat(skills): refactor upload dialog and button styles for improved consistency and usability
---------
Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
expose skill source metadata and sandbox cache status in the skills API
response so the dashboard can distinguish local, sandbox-only, and
synced skills.
prevent enabling, disabling, or deleting sandbox-only preset skills in
both backend guards and UI actions to avoid invalid local operations.
add source badges, discovery-pending hinting for sandbox runtime, and
new i18n strings for source labels and readonly warnings.
default sandbox skill paths to /workspace/skills/<name>/SKILL.md
when loading config and when exposing sandbox paths.
preserve cached sandbox paths when available to avoid losing
resolved locations for existing skills.
keep sandbox skill cache in sync when deleting a skill from disk.
this prevents stale entries in the UI when no sandbox session is
active to refresh runtime cache
Sanitize the `name` field in `SKILL.md` frontmatter to remove newlines and control characters. This prevents potential frontmatter injection vulnerabilities where a malicious skill name could introduce arbitrary YAML fields or corrupt the file structure.
- Modified `_ensure_skill_frontmatter` in `astrbot/core/skills/neo_skill_sync.py` to normalize whitespace in `name`.
- Ensured `name` is cast to string before splitting to handle non-string inputs safely.
Normalize SKILL.md content during sync so each file includes name and
description metadata in a frontmatter block.
Preserve existing frontmatter values when present, derive description
from markdown content when missing, and fallback to a default
description to keep metadata complete and consistent.
Normalize release stage values before stability checks so enum-like
objects and mixed-case strings are handled consistently.
When stable sync fails, treat "no previous release exists" during
auto-rollback as a skipped rollback instead of raising a secondary
runtime error
- Rewrite build_skills_prompt() with structured numbered rules and
markdown formatting for better LLM comprehension
- Sanitize example_path with _SAFE_PATH_RE before embedding in system
prompt to prevent prompt injection via crafted skill paths
- Add docstring to _parse_frontmatter_description()
- Remove debug print(top_dirs) from install_skill_from_zip()
- Remove stale commented-out SANDBOX_SKILLS_ROOT line
extract shared promote/sync orchestration into `NeoSkillSyncManager` so
computer tools and dashboard routes use the same rollback and error logic
add a reusable neo tool base runner to remove duplicated admin checks and
try/catch handling across skill-related tools, keeping responses consistent
factor sync result serialization into a single helper and reuse it where
stable release sync output is returned
* feat: temporary file handling and introduce TempDirCleaner
- Updated various modules to use `get_astrbot_temp_path()` instead of `get_astrbot_data_path()` for temporary file storage.
- Renamed temporary files for better identification and organization.
- Introduced `TempDirCleaner` to manage the size of the temporary directory, ensuring it does not exceed a specified limit by deleting the oldest files.
- Added configuration option for maximum temporary directory size in the dashboard.
- Implemented tests for `TempDirCleaner` to verify cleanup functionality and size management.
* ruff
* feat: support anthropic skills
closes: #4687
* chore: ruff
* feat: implement skills management and selection in persona configuration
* feat: enhance skills management with local environment tools and permissions