Compare commits

..

2483 Commits
v4.1.3 ... dev

Author SHA1 Message Date
LIghtJUNction
5c219ff38d chore: apply pre-commit fixes 2026-06-27 09:45:11 +08:00
LIghtJUNction
98d0c2555b Merge branch 'master' into dev
# Conflicts:
#	astrbot/__init__.py
#	astrbot/core/platform/sources/mattermost/client.py
#	astrbot/core/platform/sources/slack/slack_event.py
#	astrbot/core/platform/sources/webchat/webchat_event.py
#	astrbot/core/platform/sources/wecom/wecom_adapter.py
#	astrbot/core/platform/sources/weixin_oc/weixin_oc_adapter.py
2026-06-26 11:53:40 +08:00
Weilong Liao
c6b2c65b04 fix: preserve image formats in media handling (#9019)
* fix: preserve image formats in media handling

* fix: address image format review feedback

* fix: avoid tainted image temp path rename
2026-06-26 11:27:32 +08:00
LIghtJUNction
f8ce2fb468 fix: correct dashboard run return annotation 2026-06-26 10:53:04 +08:00
LIghtJUNction
fcfe5ca41f feat: migrate dashboard api runtime 2026-06-26 10:17:08 +08:00
LIghtJUNction
5d22db51ad fix: resolve merge conflicts and complete dashboard API migration 2026-06-26 09:50:15 +08:00
Weilong Liao
00c50b3b92 chore: bump version to 4.26.1 2026-06-25 23:12:10 +08:00
Weilong Liao
090f9008b6 chore: revert "fix: preserve At components when sending messages on qq_official plat…" (#9004)
This reverts commit bc117038fb.
2026-06-25 17:07:08 +08:00
Weilong Liao
473377f340 feat: update permission handling to delegate event context in guarded tools (#9001) 2026-06-25 16:18:04 +08:00
Foolllll
9daf8f0a84 fix: check OnWaitingLLMRequestEvent stop signal before acquiring session lock (#8935) 2026-06-25 16:17:07 +08:00
Soulter
348fe81720 feat: add name and compatibility date to wrangler configuration 2026-06-25 14:12:39 +08:00
Soulter
44df70d2e7 feat: add wrangler configuration for assets directory 2026-06-25 13:39:57 +08:00
Weilong Liao
952d1bfad7 chore: bump version to 4.26.0 (#8994)
* chore: bump version to 4.26.0

* feat: 更新 v4.26.0 更新日志,添加 WebUI 设置迁移提示及新功能说明

* fix: 修复多个 WebUI 和工具相关问题,提升稳定性和用户体验
2026-06-24 23:44:15 +08:00
Soulter
0cfe4163cd fix: update max_context_length and dequeue_context_length defaults 2026-06-24 23:21:50 +08:00
Weilong Liao
d90530af8e Revert "fix: reconnect MCP client on terminated session (#8694)" (#8991)
This reverts commit 2bda4e4d96.
2026-06-24 22:44:45 +08:00
EterUltimate
2bda4e4d96 fix: reconnect MCP client on terminated session (#8694)
* fix: reconnect MCP client on terminated session

* Update astrbot/core/agent/mcp_client.py

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

* Update mcp_client.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-06-24 22:43:24 +08:00
ZouZhang
bc117038fb fix: preserve At components when sending messages on qq_official platform (#8983)
- Add At component handling in _parse_to_qqofficial method
- Convert At(qq=openid) to <@openid> plain_text format
- Maintain original message chain order by appending
- Skip At(qq='all') since QQ Official API may not support it

Closes #8982
2026-06-24 22:15:12 +08:00
FuShang114
b7cadfe704 fix: allow plugin page asset token fallback (#8970)
Co-authored-by: beidou-lab-macmini <beidou-lab-macmini@beidou-lab-macminideMac-mini.local>
2026-06-24 22:11:49 +08:00
dependabot[bot]
6a343b7656 chore(deps): bump actions/checkout in the github-actions group (#8963)
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 21:47:39 +08:00
Cooper
c89984bf42 Updated Documentation for Password Reset (#8987) 2026-06-24 21:47:20 +08:00
Weilong Liao
421d718041 feat: show public version details on login (#8986)
* feat: show public version details on login

* fix: address login version review feedback
2026-06-24 21:46:29 +08:00
Weilong Liao
967ed01cf7 fix: add data scope to api keys (#8985) 2026-06-24 16:37:46 +08:00
Weilong Liao
df4d93d724 fix: normalize cron weekday scheduling (#8984) 2026-06-24 16:22:58 +08:00
VectorPeak
3c7956e8c8 fix: prevent path traversal in plugin upload filenames (#8968) 2026-06-24 15:55:53 +08:00
VectorPeak
5266d170a3 fix: prevent path traversal vulnerability in knowledge base upload filenames (#8971) 2026-06-24 15:55:01 +08:00
Tanishq
ae29a7eaf9 feat(websearch): add Exa as a web search provider (#8973)
- Add ExaWebSearchTool (web_search_exa) with keyword/semantic search,
  category filters, domain restrictions, and date range support
- Add ExaGetContentsTool (exa_get_contents) for extracting web page content
- Add _exa_search() and _exa_get_contents() API helpers hitting
  https://api.exa.ai/search and https://api.exa.ai/contents
- Add _EXA_KEY_ROTATOR for multi-key rotation
- Register Exa tools in _apply_web_search_tools() dispatch
- Add Exa to WEB_SEARCH_CITATION_TOOL_NAMES for citation support
- Add websearch_exa_key config default and provider option
- Add i18n metadata for en-US, zh-CN, ru-RU
- Add Exa section to docs (en + zh)
- Add 6 unit tests covering search, contents, error handling, and
  legacy config migration

Closes #5621
2026-06-24 15:53:47 +08:00
Soulter
756469a39f fix: remove unused vocechat logo and update xmas hat image 2026-06-21 23:44:33 +08:00
Weilong Liao
16beb9a9d7 fix: remove redundant font family from stylesheet link (#8942) 2026-06-21 23:36:21 +08:00
Soulter
e30655b04e fix: refresh WebUI with cache buster 2026-06-21 18:12:07 +08:00
Soulter
1283421339 fix: update workflow names to improve readability 2026-06-21 14:17:36 +08:00
Soulter
7980ed28ad fix: restore cli init dashboard monkeypatch hook 2026-06-21 14:14:45 +08:00
Weilong Liao
c59ef11128 chore: bump version to 4.26.0-beta.12 (#8934) 2026-06-21 14:12:07 +08:00
Weilong Liao
05148dfdd9 fix: add sdist build artifact path to allow dashboard artifact to be included (#8933)
* fix: add sdist build artifact path to allow dashboard artifact to be included

* Update pyproject.toml

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>
2026-06-21 14:08:48 +08:00
Weilong Liao
39d425316f fix: created unnecessary data dir when executing astrbot command (#8932)
* fix: created unnecessary data dir when executing astrbot command

fixes: #8853

* fix: 更新包版本更新函数以修改 astrbot/__init__.py 中的版本号
2026-06-21 14:04:49 +08:00
lingyun14
42ca89d6c8 fix: 修复提供商源修改 ID 后保存被静默还原的问题 (#8915)
* Update schemas.py

* Update schemas.py
2026-06-21 11:55:54 +08:00
Weilong Liao
b6913833d4 chore: bump version to 4.26.0-beta.11
Release 4.26.0-beta.11
2026-06-20 22:32:56 +08:00
Soulter
f9d4082217 feat: add prerelease visibility toggle 2026-06-20 22:23:25 +08:00
Soulter
ddc4e142c7 fix: clarify WebUI recovery hint 2026-06-20 22:11:38 +08:00
Weilong Liao
d36987dd19 fix: restore static runtime version
Fixes #8924
2026-06-20 22:06:24 +08:00
NayukiChiba
0a0c677404 docs: 文档更新 - 指令、FAQ、网页搜索、插件发布等 (#8912)
* docs(community): 更新 QQ 群组信息
- 移除了旧的 QQ 群组信息并添加了新的群组。
- 确保所有群组信息的准确性和完整性。
- 提升文档的可读性和用户体验。

* docs(webui): 为忘记密码章节添加 FAQ 引用链接

- 在英文和中文文档的"忘记密码"章节末尾添加 TIP 提示框
- 提示框链接至对应 FAQ 条目,提供更详细的操作说明
- 增强文档之间的关联性,提升用户查阅体验

* docs(command): 新增 /stats 和 /provider 指令文档,更新 FAQ 管理员指令列表

- 在英文和中文的命令文档中添加 /stats 和 /provider 指令的详细使用说明
- 更新中英文 FAQ 页面的管理员指令列表,与最新的默认指令保持一致
- 确保中英文文档内容同步,提升文档准确性和用户查阅体验

* docs(websearch): 新增 Firecrawl 网页搜索提供商文档支持

- 在开发版配置文档中补充 websearch_provider 选项,加入 firecrawl 及对应密钥配置项
- 更新中英文网页搜索使用指南,将支持搜索源数量同步为五种并提供 Firecrawl 注册指引
- 确保中英文文档内容一致,提升配置说明的完整性和用户查阅体验

* docs(plugin-publish): 更新插件提交方式至新仓库

- 废弃通过 AstrBot 主仓库 Issue 提交插件的方式
- 新增警告框提示正确提交入口为 AstrBot_Plugins_Collection
- 同步更新中英文版插件发布文档
2026-06-20 16:43:58 +08:00
Weilong Liao
da7f53d5eb fix: keep system tools with persona tool lists (#8908) 2026-06-20 01:15:31 +08:00
Soulter
a7533aacda fix: fall back to stale WebUI when repair fails 2026-06-20 00:01:29 +08:00
Weilong Liao
46a846b88b chore: bump version to 4.26.0-beta.10 (#8905) 2026-06-19 23:59:39 +08:00
lxfight
2d98d38078 fix: inject knowledge base context as temporary user content (#8904) 2026-06-19 22:48:23 +08:00
Weilong Liao
1b0f5cb0d3 fix: keep WebUI assets in sync with core version (#8901)
* fix: keep WebUI assets in sync with core version

* fix: import dashboard version before bundled fallback

* fix: remove stale WebUI dist robustly
2026-06-19 22:46:38 +08:00
Weilong Liao
cdfb0bdf91 fix: restore webui 401 login redirect (#8903) 2026-06-19 22:43:21 +08:00
Weilong Liao
3760abb39b chore: bump version to 4.26.0-beta.9 (#8895) 2026-06-19 17:47:17 +08:00
Weilong Liao
272242e407 chore: add release preparation workflow (#8891)
* chore: add release preparation workflow

* fix: address release workflow review feedback
2026-06-19 17:41:13 +08:00
Weilong Liao
dd36979eca feat: implement request retry mechanism for provider requests (#8893)
* feat: implement request retry mechanism for provider requests

* feat: add request max retries configuration and implement retry logic for provider requests

* feat: update fake_query function to accept request_max_retries parameter

* feat: remove retry_rate_limits from provider request calls
2026-06-19 17:13:40 +08:00
Weilong Liao
143f846b92 fix: support renamed MCP streamable HTTP client
Support both MCP streamable HTTP client names and keep mcp dependency below 2.
2026-06-19 15:54:47 +08:00
Weilong Liao
5888631ed5 feat: add hosted core package downloads (#8888)
* feat: add hosted core package downloads

* Potential fix for pull request finding 'CodeQL / Incomplete URL substring sanitization'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix: validate hosted core package archive

* fix: validate hosted dashboard package archive

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-06-19 12:44:31 +08:00
Weilong Liao
29d66b84b9 feat: support workspace skills in requests (#8884)
* feat: support workspace skills in requests

* fix: harden workspace skill discovery

* fix: address workspace skills review comments
2026-06-19 12:03:07 +08:00
Weilong Liao
59734c22b6 fix(core): reject hardlinked files in restricted local fs tools
Reject multi-linked regular files in restricted local filesystem tools so workspace hardlink aliases cannot read or overwrite files outside allowed directories.

Fixes #8868.
2026-06-19 00:28:36 +08:00
Weilong Liao
309e05d3cc fix: enforce future task owner checks (#8881) 2026-06-18 23:35:33 +08:00
Weilong Liao
49b86320cb docs: clarify OpenAPI chat username identity (#8880) 2026-06-18 23:17:50 +08:00
Yufeng He
1a9d1f566d fix(core): enforce persona tool boundaries (#8786)
* fix(core): enforce persona tool boundaries

* refactor: filter persona tools in one pass

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-06-18 23:15:25 +08:00
Weilong Liao
264e7eaaa3 fix: restore OpenAPI file uploads
Expose /api/v1/file in OpenAPI, enable file-scoped API keys, and regenerate docs/client artifacts.
2026-06-18 12:37:38 +08:00
Soulter
2c8f38c886 chore: bump version to 4.26.0-beta.8 2026-06-18 00:13:50 +08:00
Soulter
12b1b27825 fix: harden upgrade restart recovery 2026-06-18 00:13:18 +08:00
Soulter
79d787c692 chore: bump version to 4.26.0-beta.7 2026-06-17 23:43:55 +08:00
Soulter
08fc565175 fix: handle legacy login upgrade recovery 2026-06-17 23:43:04 +08:00
Soulter
96474d3d84 chore: bump version to 4.26.0-beta.6 2026-06-17 23:16:02 +08:00
Weilong Liao
d5f5631287 fix: prefer v1 auth with legacy recovery fallback 2026-06-17 23:15:03 +08:00
Soulter
6a85405105 chore: bump version to 4.26.0-beta.5 2026-06-17 22:53:25 +08:00
C₂₂H₂₅NO₆
59fdd96627 fix: 修正人格编辑重名校验 (#8843)
Co-authored-by: C₂₂H₂₅NO₆ <Sisyphbaous-DT-Project@users.noreply.github.com>
2026-06-17 22:51:24 +08:00
Weilong Liao
19864b3f85 fix: recover interrupted dashboard upgrades 2026-06-17 22:48:47 +08:00
エイカク
2c8736fe42 fix: harden sandbox file transfers (#8840)
* fix: harden sandbox file transfers

* fix: check CUA sandbox availability with shell probe

* fix: address sandbox transfer review feedback

* fix: preserve CUA health check cancellation

* fix: tighten CUA health probe checks
2026-06-17 22:25:51 +09:00
Weilong Liao
55af880369 feat(qqofficial): allow QQ Official Webhook adapters to proactively send group messages without requiring a cached msg_id (#8841)
* feat(qqofficial): support webhook QR setup

* docs(qqofficial): simplify webhook QR setup step
2026-06-17 21:13:05 +08:00
letr
30ae18a8f0 feat(qqofficial): support group message create type (#8838)
* feat(qqofficial): support group message create

* chore: remove temporary qq official capture script

* feat(qqofficial): allow ws segmented replies

* fix(qqofficial): guard missing group mentions

* feat(qqofficial): enhance group message handling with debug logging and sender username

* feat(qqofficial): add recommended group chat settings and update bot creation instructions

* feat(qqofficial): enhance error handling for QQ Official API message sending

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-06-17 19:11:48 +08:00
0xa7973908
2cafa217f2 chore: Change faiss-cpu version baseline from 1.12.0 to 1.14.3. (#8837)
Co-authored-by: SkyCanvas <maximwang110@gmail.com>
2026-06-17 16:21:30 +08:00
Soulter
2c5165e929 chore: bump version to 4.26.0-beta.4 2026-06-17 11:13:22 +08:00
Weilong Liao
fda5161451 fix: preserve persona default tool selection
Fix https://github.com/AstrBotDevs/AstrBot/issues/8828
2026-06-17 11:08:46 +08:00
Weilong Liao
d3b52356a6 fix: repair onboarding platform and backup upload (#8834) 2026-06-17 10:54:57 +08:00
Weilong Liao
33cab38c30 fix(gemini): tool definition does not pass back to gemini properly, causing repeated tool calls. (#8833)
* fix: tool definition does not pass back to gemini properly, causing repeated tool calls.

fixes: #8789
fixes: #8773
fixes: #7111
fixes: #6402
fixes: #7684

* fix: remove unnecessary logging and improve log messages in Gemini source

* fix: improve type checking for tool calls in Google Gemini provider
2026-06-17 10:47:22 +08:00
Weilong Liao
4f5075e608 feat: add startup reset password flag 2026-06-17 00:32:37 +08:00
Soulter
e84e94f39e chore: bump version to 4.26.0-beta.3 2026-06-16 19:12:35 +08:00
Weilong Liao
f1854df620 feat: add qq official qr binding
Add QQ Official Bot QR binding registration flow for the WebSocket adapter, wire dashboard credential autofill, and mark the WebSocket template as recommended.
2026-06-16 19:08:41 +08:00
Weilong Liao
898c800c96 fix: upload skills with generated multipart body
Fixes #8794.
2026-06-16 17:00:23 +08:00
Haoran Xu
f66215b365 fix(chat): prevent IME composition character loss at non-terminal cur… (#8811) 2026-06-16 13:45:33 +08:00
Soulter
baae93be3d chore: bump version to 4.26.0-beta.2 2026-06-16 12:42:32 +08:00
Weilong Liao
d56100cdfc refactor: delegate star tool event creation to platforms
Delegate StarTools event creation to platform adapters and add create_event overrides for platform-specific message events.
2026-06-16 12:37:50 +08:00
Soulter
90ca0857a5 Merge remote-tracking branch 'origin/pr/8197' into codex/pr-8197-merge
# Conflicts:
#	astrbot/core/platform/sources/dingtalk/dingtalk_adapter.py
#	astrbot/core/provider/sources/anthropic_source.py
#	astrbot/dashboard/routes/plugin.py
2026-06-16 11:46:33 +08:00
dependabot[bot]
ee1cab2dde chore(deps): bump pnpm/action-setup in the github-actions group (#8808)
Bumps the github-actions group with 1 update: [pnpm/action-setup](https://github.com/pnpm/action-setup).


Updates `pnpm/action-setup` from 6.0.8 to 6.0.9
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v6.0.8...v6.0.9)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: 6.0.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-16 11:03:57 +08:00
Weilong Liao
5566bd621c feat: reorganize settings system configuration (#8777)
* feat: reorganize settings system configuration

* fix: float system config restart notice

* fix: blur system config restart notice

* fix: tint restart notice blur background

* fix: allow totp setup without body

* fix: filter public openapi docs

* fix: handle settings autosave cleanup

* chore: ui
2026-06-16 11:03:42 +08:00
Weilong Liao
dd46cce09e fix: make project update flow atomic (#8805)
* fix: make project update flow atomic

* fix: address atomic update review feedback

* fix: show update success after restart

* fix: prevent update progress reset during restart

* fix: align update success feedback styling
2026-06-15 23:32:29 +08:00
Weilong Liao
a938620467 fix: avoid WebUI ready banner when assets missing (#8804) 2026-06-15 22:59:40 +08:00
エイカク
12d4a613b4 fix: write config files atomically (#8793)
* fix: write config files atomically

* Update astrbot_config.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-06-15 22:06:14 +08:00
エイカク
dd828c99f4 fix: run local python in session workspace (#8792) 2026-06-15 20:52:00 +08:00
エイカク
6f88ad9a35 fix: preserve guarded run-based tools (#8790) 2026-06-15 20:47:03 +08:00
Soulter
a2b6aad849 fix: stabilize dashboard route tests on latest FastAPI 2026-06-15 13:41:13 +08:00
Soulter
5a394314b9 chore: bump version to 4.26.0-beta.1 2026-06-15 13:28:58 +08:00
Soulter
ad1b64d127 fix: stabilize FastAPI dashboard route tests 2026-06-15 13:10:07 +08:00
時壹
f5cf749148 feat(components): override repr_args to truncate long base64 fields for safe logging (#8591) 2026-06-15 08:44:23 +08:00
Exynos
40720fc2bd fix: updates the aiocqhttp platform adapter and message event handler to include self_id routing parameters across multiple API calls (#8779)
Updates the aiocqhttp platform adapter and message event handler to include self_id routing parameters across multiple API calls, including message sending, forwarding, and fetching group/user details. It also adds handling to ignore mface message types. The review feedback suggests refactoring the duplicate self_id extraction logic in the message forwarding code to reduce redundancy and improve maintainability.
2026-06-14 20:28:32 +08:00
Weilong Liao
0d8e8682db refactor(core): migrate backend backbone from Quart to FastAPI and introduce more OpenAPI (#8688)
* refactor: migrate to fastapi

* structure refactor

* fix: pyright fix

* refactor: improve error handling and public messages in plugin services

* feat(api): refactor API client integration and enhance request handling

- Updated API client configuration to use a dedicated HTTP client.
- Introduced utility functions for generating options, queries, and form data for API requests.
- Refactored multiple API methods to utilize the new utility functions for improved consistency and readability.
- Renamed types for clarity and updated import statements accordingly.

feat(docs): add script to update OpenAPI JSON from YAML spec

- Created a Python script to convert OpenAPI YAML specification to JSON format.
- The script supports customizable input and output paths.
- Ensured the script handles directory creation for output paths and validates the YAML structure.

* fix

* feat(auth): implement rate limiting for v1 login endpoint and enhance request handling

* Refactor dashboard API routers to use legacy_router for backward compatibility

- Changed all instances of dashboard_router to legacy_router across multiple API modules including platform, plugins, providers, sessions, skills, stats, subagents, t2i, tools, updates, and asgi_runtime.
- Updated route definitions to ensure existing endpoints remain functional under the new router structure.
- Introduced support for Quart request context in asgi_runtime to enhance compatibility with existing Quart-based plugins.
- Added a test case to validate the functionality of the new Quart request context handling in plugin extensions.

* chore: remove cli test

* fix: update dashboard tests for fastapi migration

* chore: satisfy ruff checks

* fix: update openapi api key scopes

* fix: sync config scope chip selection

* fix: restore quart dependency

* docs: clarify quart plugin api compatibility

* docs: update openapi scope documentation

* fix: use singular skill openapi scope

* fix: hide update service exception details

* fix: address fastapi review comments

* fix: address dashboard review findings

* docs: revert unrelated package deployment changes

* docs: update agent api generation guidance

* feat: add plugin page web api helpers

* docs: add plugin page bridge demo

* fix: type plugin upload files

* fix: stabilize plugin page uploads

* fix: type plugin web request proxy

* docs: remove plugin page docs example

* fix: authenticate plugin page SSE bridge
2026-06-14 15:03:26 +08:00
叹号大帝
2eee833832 feat(proxy): add gh proxy link gh.dpik.top (#8772) 2026-06-14 12:09:00 +08:00
Soulter
fadada3d67 fix: correct plugin llm tool toggle ownership check 2026-06-14 11:02:16 +08:00
Yufeng He
6c3a1ae8e5 fix: sanitize generated platform ids (#8768) 2026-06-14 10:57:13 +08:00
叹号大帝
d0323196f4 fix(proxy): drop invalid proxy gh.llkk.cc (#8761)
* fix: replace broken gh proxy URL

* fix: remove ghproxy.net from proxy list

Removed an unused GitHub proxy URL from the list.
2026-06-14 10:38:41 +08:00
Weilong Liao
7c366a708b fix: unify media reference handling (#8764)
* fix: unify media reference handling

* fix: accept bare base64 record media refs

* chore: update agents.md

* fix: unify file URI handling across media components and utilities

* fix: unify media reference type handling with MediaRefStr alias

* Potential fix for pull request finding 'CodeQL / Incomplete URL substring sanitization'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Update astrbot/core/platform/sources/discord/discord_platform_adapter.py

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

* fix: unify media handling and improve base64 decoding across components

* fix: simplify client_kwargs type definition and enhance media message handling in platform adapter

* fix: unify media utility documentation and enhance function descriptions

* perf: drop "pilk" requirement, improve audio outbound for tencent-related IM apps which using silk

* fix: unify Tencent Silk audio handling and enhance media resolver functionality

---

- Centralize media reference materialization and base64 resolution for local paths, http(s), base64://, data URIs, and legacy bare base64 payloads.
- Normalize incoming Record audio to wav and Image media to temporary jpg during preprocess, with event-scoped cleanup.
- Reuse the shared media resolver across OpenAI, Gemini, Anthropic, MiMo, DeerFlow, STT, and platform media paths while sanitizing logs and cleaning temporary conversion outputs.
- Ensure generated TTS audio is tracked for cleanup after the event finishes.

fix #8676
fix #8543
fix #7588
fix #7580
fix #8030
fix #8034
fix #7461
fix #7565
fix #6509
fix #7144
fix #7795



---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-06-14 10:37:16 +08:00
Soulter
3ca6f241ac fix: resolve subdirectory llm tool plugin ownership 2026-06-13 17:34:11 +08:00
星鸿SeRazon
f3aa2a6959 perf(cli): optimize plugin list building performance and robustness while adding coverage for key merge and edge-case scenarios (#8705)
* perf: optimize plugin list merge

* fix: guard plugin list directory iteration

* test: move plugin utils tests to unit suite

* fix: minimize plugin path guard change

* test: cover missing plugin directory listing

* fix: address code review feedback on plugin utils and tests

* perf: optimize plugin comparison using dict pop method

* style: format plugin.py and retry CI
2026-06-13 16:44:22 +08:00
lingyun14
d2b86c5991 feat(dashboard): add a configurable theme mode with light, dark, and system options and centralize theme synchronization with system preferences. (#8648)
* Update main.ts

* Update config.ts

* Update header.json

* Update auth.json

* Update header.json

* Update auth.json

* Update header.json

* Update auth.json

* Update VerticalHeader.vue

* Update customizer.ts

* Update LoginPage.vue

* Update SetupPage.vue

* Update config.ts

* Update customizer.ts

* Update plugin-pages.md

* docs: add Follow System note to plugin-pages theme section
2026-06-13 16:41:54 +08:00
AnegasakiNene
26beaaa938 feat(ci): allow conventional PR title prefixes (#8665)
* feat(ci): allow conventional PR title prefixes

* fix(ci): clarify PR title examples
2026-06-13 16:39:02 +08:00
Rat
80af9e0c1d fix cli version source (#8692)
Co-authored-by: Rat0323 <261020116+Rat0323@users.noreply.github.com>
2026-06-13 16:36:06 +08:00
Yufeng He
d4e7aa0489 fix: avoid duplicate quoted image captions (#8718) 2026-06-13 16:12:54 +08:00
Yufeng He
690b184a62 fix: preserve embedding api version suffixes (#8736) 2026-06-13 15:57:36 +08:00
Yufeng He
f19f623a26 fix: handle changelog anchor links (#8750)
Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>
2026-06-13 15:51:32 +08:00
Tang Yulong
32cfcbf52d feat: show quoted message content in group chat context
* feat: show quoted message content in group chat context

Include Reply component content in _format_message so the LLM can
see what message was quoted when someone replies to the bot.

- Add Reply import
- Handle Reply in _format_message with message_str or chain fallback
- Add _describe_chain helper for non-text quoted content (images, etc.)

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

* fix: use isinstance, add truncation, unify language to English

- Replace string class-name checks with isinstance() for robustness
- Add _truncate_reply_text to prevent long quoted content inflating context
- Unify markers to English ([Image], [Voice], [Quote] etc.)
- Import Record, Video, File for isinstance checks

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

* fix: add Forward, AtAll, Face to _describe_chain for completeness

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

* style: format group chat context

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-06-10 16:58:18 +08:00
lingyun14
fb8f4d68e1 feat: backup skills directory (#8700)
* feat: include skills directory in backup

* Update settings.json

* Update settings.json

* Update settings.json

* Update settings.json

* Update settings.json
2026-06-10 16:51:29 +08:00
yzy123908944141
eeabdb9829 style: apply pyupgrade updates (#8684) 2026-06-10 16:47:22 +08:00
Zayn
0b22349363 feat: add ElevenLabs TTS API provider 2026-06-10 16:47:14 +08:00
micaiguai
56d2b3fb55 fix(dashboard): allow creating folder by pressing Enter (#8597)
* fix(dashboard): allow creating folder by pressing Enter

* fix(dashboard): disable form while creating folder to prevent duplicate submissions
2026-06-10 16:46:11 +08:00
dependabot[bot]
b321499e00 chore(deps): bump codecov/codecov-action from 6 to 7 in the github-actions group
Bumps the github-actions group with 1 update: [codecov/codecov-action](https://github.com/codecov/codecov-action).


Updates `codecov/codecov-action` from 6 to 7
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-10 16:43:47 +08:00
HIU
a3c25ec2c7 fix: preserve repo source on plugin reinstall
* fix: preserve repo source on plugin reinstall

* fix(dashboard): align extension market matching with repo identity

Use normalized repo keys as the primary identity when matching
installed extensions with marketplace plugins in useExtensionPage.

Only fall back to name matching for installed extensions that do
not have a repo, and normalize name lookups consistently on both
sides. Also clear stale online_version when no marketplace plugin
is matched.
2026-06-10 16:42:12 +08:00
千岚之夏
bec0de2e2b fix: defer faiss C library import to prevent process hang on startup (#8696)
* fix: defer faiss C library import to prevent process hang on startup

Move top-level `import faiss` from embedding_storage.py to __init__() method,
and make the EmbeddingStorage import in vec_db.py lazy. This prevents the faiss
C library from being loaded at module import time, which can cause process hang
(SIGILL or deadlock) with faiss-cpu 1.14.2 on certain CPU architectures.

Ref #8695

* chore: apply review suggestions

- Preserve original exception context with `from e` when re-raising ImportError
- Move EmbeddingStorage import back to top level in vec_db.py (safe now that
  faiss is no longer imported at module level in embedding_storage.py)

* ci: trigger re-run

---------

Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>
2026-06-10 15:31:48 +08:00
liliiiliili
60dfd565a6 docs: fix LM Studio public IP typo (#8707)
* docs: fix LM Studio public IP typo

* docs: refine LM Studio Docker wording
2026-06-10 08:52:55 +08:00
Ruochen Pan
ae44b912fc feat(dashboard): add per-tool permission management for function tools (#8693)
* feat(func-tool): add per-tool permission management

* feat(dashboard): add permission column to function tool table

* refactor(dashboard): encapsulate tool actions into composable and unify permission UI

* style: format code

* fix: guard sync handler, simplify sp access, skip builtin instantiation
2026-06-09 14:47:41 +08:00
C₂₂H₂₅NO₆
0fb3f5eb93 feat: display current weekday information (#8669)
在现实世界时间感知提示中追加 Weekday 字段,让模型能直接获取今天是星期几。\n\n使用固定英文星期表避免受系统 locale 影响,并补充单测覆盖输出格式。

Co-authored-by: C₂₂H₂₅NO₆ <Sisyphbaous-DT-Project@users.noreply.github.com>
2026-06-09 10:11:20 +08:00
MUHAMED FAZAL PS
992aea9869 fix: address review feedback - add plugin naming pattern check and edge case handling
Address feedback from Sourcery AI and Gemini Code Assist:
- Only apply fallback path to known plugin naming patterns (astrbot_plugin_*)
- Add defensive check for None/empty tool.__module__
- Fallback to tool.__module__ if _parts is empty
2026-06-08 17:27:00 +05:30
MUHAMED FAZAL PS
736bc93b2a fix: consistent handler_module_path for subdirectory tools (#8578) 2026-06-08 17:21:19 +05:30
時壹
4b562689ee fix: dispose database engine on shutdown (#8650) 2026-06-08 11:00:26 +08:00
LIghtJUNction
398086ac5f chore: fix dashboard style checks 2026-06-08 02:12:19 +08:00
LIghtJUNction
a3ba7bd9ee merge: master into dev 2026-06-08 01:32:39 +08:00
Soulter
af70151ff8 chore: bump version to 4.25.5 2026-06-08 01:23:06 +08:00
Weilong Liao
66ec415e56 fix: restrict local file paths in message tools (#8660)
* fix: restrict local file paths in message tool

* Update astrbot/core/tools/message_tools.py

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

* fix: rf

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-06-08 01:20:47 +08:00
Weilong Liao
8f5178d265 fix: restore star context typing (#8659) 2026-06-08 00:24:45 +08:00
Soulter
05c137eb29 fix: qq official webhook mode can not restart normally 2026-06-07 18:10:45 +08:00
Copilot
1a04998787 perf: handle Anthropic usage=None on content-filtered responses (#8647)
* Initial plan

* fix: handle missing anthropic usage on filtered responses

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-07 15:29:22 +08:00
Soulter
c4251e8210 chore: bump version to 4.25.4 2026-06-07 12:35:12 +08:00
Weilong Liao
66a10c08b2 perf: increase weixin http api request timeout from 15s to 120s (#8643) 2026-06-07 12:26:26 +08:00
Weilong Liao
c7e9d5b481 fix: Prevent duplicate web search citation prompts from being repeatedly appended to the system message after multiple tool invocations in a single interaction (#8642) 2026-06-07 12:23:03 +08:00
EterUltimate
0db7fc9b39 fix(dashboard): sync pnpm lockfile overrides (#8637) 2026-06-07 10:54:56 +08:00
時壹
556903c135 fix: keep strong refs to pipeline tasks to prevent GC (#8618) 2026-06-07 10:52:11 +08:00
Weilong Liao
bdc32bb78c Revert "fix: retry provider stats on sqlite lock" (#8639)
This reverts commit 1ad2b2c385.
2026-06-07 10:51:27 +08:00
Weilong Liao
c70a1924fe Revert "fix SQLAlchemy compatibility issues on macOS" (#8638)
* Revert "fix SQLAlchemy compatibility issues on macOS (#7724)"

This reverts commit 2d78626840.

* fix

* chore: add busy timeout pragma
2026-06-07 10:50:33 +08:00
Copilot
6ae103a24f perf: enable full credential autofill on WebUI login form (#8631)
* Initial plan

* chore: outline plan for login autocomplete fix

* fix(webui): add login autocomplete attributes

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-06 23:17:42 +08:00
Soulter
fde0ea9236 chore: bump version to 4.25.3 2026-06-06 00:51:50 +08:00
Weilong Liao
ef53a933ec fix: keep DingTalk stream reconnecting (#8610)
* fix: keep DingTalk stream reconnecting

* fix
2026-06-06 00:46:37 +08:00
lxfight
c58916b8e9 feat(dashboard): add plugin WebUI entries to sidebar with MDI icon support (#8569)
* feat(plugin): support icon field in metadata.yaml for sidebar icon

* feat(sidebar): add isRawTitle support for non-i18n sidebar titles

* feat(sidebar): add usePluginSidebarItems composable for dynamic plugin WebUI entries

* feat(sidebar): inject plugin WebUI items into sidebar before More group

* refactor(plugin-page): remove header, make iframe full-screen

* feat(sidebar): restore plugin WebUI collapsible group

* fix(plugin-page): prevent iframe from capturing mousemove during sidebar resize

- Use absolute positioning instead of negative margin for full-screen layout
- Zero container padding for plugin page route in FullLayout
- Disable pointer-events on iframe during sidebar drag to avoid event capture

* refactor(sidebar): share plugin state reactively instead of polling

- Replace polling + events with module-level reactive shared state
- useExtensionPage.getExtensions() populates pluginSidebarState
- usePluginSidebarItems uses computed() to derive sidebar menu
- Zero additional API calls, updates instantly on any plugin change

* fix(sidebar): restore initial plugin data fetch on sidebar mount

* feat(sidebar): render plugin icons via MDI SVG CDN instead of subset font

- Plugin icons loaded from https://cdn.jsdelivr.net/npm/@mdi/svg@7/svg/
- Removes subset limitation - plugins can use any MDI icon
- Fallback to subset font class for built-in sidebar items
- Default icon remains mdi-puzzle when plugin doesn't specify one

* fix(sidebar): render plugin icons as inline SVG with currentColor for theme matching

* docs: add plugin sidebar icon documentation

* docs: require mdi- prefix for plugin icon field

* chore: ruff format

* fix: address review feedback

- Add SVG sanitization to prevent XSS via v-html (reject <script>, event handlers)
- Extract MORE_GROUP_KEY shared constant to avoid hardcoded i18n key
- Parallel SVG loading with Promise.all instead of serial
- Pure buildPluginItems, mutate iconSvg in place to avoid redundant rebuilds
- Fallback to default icon SVG when loading fails
- Revert accidental pnpm-lock.yaml changes

* chore: remove webui icon

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-06-06 00:35:52 +08:00
lxfight
65fe0574b9 feat: sync dashboard theme to plugin pages (#8390)
* feat(plugin): pass theme through plugin page asset URLs and initial context

Add theme query parameter propagation through the plugin page asset pipeline
so that the bridge SDK initial context includes isDark.

* feat(plugin): inject data-theme and color-scheme into plugin page HTML

Set data-theme on <html> and add color-scheme meta tag server-side
to prevent flash when entering plugin pages in dark mode.

* feat(webui): add isDark getter to customizer store

* feat(webui): sync theme to plugin iframe via URL param and postMessage

Append theme query parameter to iframe src URL and include isDark
in the postMessage context. Watch uiTheme changes to re-send context.

* feat(bridge): auto-apply data-theme from context in plugin bridge SDK

Set data-theme attribute on document.documentElement when context
includes isDark, enabling live theme switching via postMessage.

* docs: add light/dark theme adaptation guide for plugin pages

Add theme adaptation section to existing plugin-pages docs in both
Chinese and English, covering CSS variables and onContext() usage.

* test: add theme sync tests for plugin page bridge and content

Verify isDark in bridge SDK initial context with various theme params,
and verify data-theme and color-scheme injection in rewritten HTML.

* fix(plugin): use case-insensitive regex for head tag in HTML rewrite

Replace string match for <head> with case-insensitive regex to handle
uppercase tags and tags with attributes, preventing duplicate injection
of color-scheme meta tag.

* refactor(webui): generalize isDark getter to support any dark theme

Replace hardcoded PurpleThemeDark check with suffix-based detection
so all dark theme variants are recognized automatically.

* refactor(plugin): extract theme helpers for HTML rewriting

Extract _get_request_theme and _apply_theme_to_html to eliminate
duplicate theme-parsing logic and isolate HTML mutation. Use case-
insensitive regex for head tag detection to prevent duplicate
injection when tags use mixed casing.

* style: apply ruff formatting to plugin page tests

Wrap long function call lines for consistency with project style.

* fix(plugin): handle existing data-theme and case-sensitive fallback in HTML rewrite

Strip any existing data-theme attribute before adding the new one to
prevent duplicate attributes. Use case-insensitive regex for the
<head> fallback insertion to avoid corrupting <html> tag attributes.

* fix(webui): add null guard to isDark getter

Guard against undefined uiTheme to prevent TypeError when the
theme config has not been initialized.

* fix(webui): centralize theme mapping and preserve hash in plugin page URL

Extract themeParam computed to avoid drift between URL and context.
Include hash fragment in iframe URL to support SPA hash routing.

* fix(webui): address CR feedback - deduplicate color-scheme meta, harden isDark getter, consolidate theme source

- _apply_theme_to_html: strip existing color-scheme meta before injecting to
  avoid duplicates; merge data-theme strip+add into single-pass regex callback
- customizer.ts: replace brittle endsWith('Dark') with explicit theme name check
- _rewrite_plugin_page_html: use _get_request_theme() directly instead of
  reading theme from extra_query_params

* fix(webui): 简化 isDark 推导、优化查询参数构建、使用暗色主题集合

- isDark 推导简化为 theme == "dark"(None == "dark" 为 False,去掉多余三元表达式)
- _prepare_plugin_page_query_params 改为线性构建,先计算再构建字典
- isDark getter 改用显式 DARK_THEMES Set,替代硬编码单值比较

---------

Co-authored-by: lxfight <lxfight@192.168.5.50>
2026-06-06 00:35:47 +08:00
Weilong Liao
7e22a07e0d feat: introduce a command /name to name a umo, and display in ui (#8575)
* feat: introduce a command /name to name a umo, and display in ui

* docs: add docs

* fix

* fix test

* fix: test
2026-06-05 19:09:48 +08:00
エイカク
1ad2b2c385 fix: retry provider stats on sqlite lock
Retry transient SQLite lock failures when persisting internal provider stats.
2026-06-04 19:24:12 +09:00
tjc66666666
85ec7a969f feat: Enhance Reply chain handling for Record components (#8527)
* Enhance Reply chain handling for Record components

Added processing for Record components within Reply chains, including WAV conversion and STT functionality.

* Refactor STT processing for Record components

* Add STT record function for voice-to-text processing

* Update stage.py

* Update stage.py

* Update stage.py
2026-06-04 09:00:57 +08:00
NayukiChiba
9a648eb426 fix(wecomai_event): Fix whitespace handling when extracting plain text from message chains (#8563)
* fix(wecomai_event): 修复消息链提取纯文本时的空白处理
- 增加了strip_result参数以控制是否去除首尾空白
- 流式输出时保留换行等格式字符
- 更新相关调用以适应新参数

* test(wecomai_event): 添加企业微信智能机器人消息事件处理的单元测试
- 测试 _extract_plain_text_from_chain 方法在流式和非流式场景下的行为
- 确保流式输出时换行符等格式字符能够正确保留
- 覆盖了不同输入场景的测试用例

* fix(wecomai_event): 删除企业微信智能机器人消息事件处理的单元测试
- 移除测试文件 test_wecomai_event.py,包含多个针对 _extract_plain_text_from_chain 方法的测试用例
- 测试用例涵盖了流式和非流式场景下的文本提取行为
2026-06-04 08:59:59 +08:00
Weilong Liao
24f568b149 feat: future task UI (#8559)
* feat: future task UI

* fix: update filter label for UMO in English and Chinese locales

* feat: enhance cron job management with delivery target handling and UI improvements

* fix: update session label to indicate optional delivery target

* feat: add tooltip for last run time and error in cron job display
2026-06-03 22:02:59 +08:00
lxfight
e5d7b43090 fix(dashboard): relax frame security headers when running under launcher (#8554)
* fix(dashboard): relax frame security headers when running under launcher

When AstrBot is launched by the AstrBot Launcher, the dashboard is
embedded in a cross-origin iframe (the Tauri webview).  The plugin page
responses set X-Frame-Options: SAMEORIGIN and CSP frame-ancestors
'self', both of which inspect the *entire* ancestor chain — not just the
immediate parent.  Because the top-level Tauri webview has a different
origin, these headers block the plugin page from loading inside the
nested iframe, resulting in 'localhost refused to connect'.

Fix: skip the restrictive frame headers when ASTRBOT_LAUNCHER=1 is set,
which the launcher already injects as an environment variable.  Other
security measures (iframe sandbox, JWT asset_token, postMessage bridge)
remain in place.

* fix(dashboard): preserve object-src and base-uri CSP directives under launcher

Keep object-src 'none' and base-uri 'self' in the CSP header even when
ASTRBOT_LAUNCHER is set.  Only frame-ancestors and X-Frame-Options need
to be relaxed because the Tauri webview is a cross-origin ancestor.

* fix(dashboard): tighten ASTRBOT_LAUNCHER check and always emit CSP

Use explicit value check ('1' / 'true') instead of truthiness for the
ASTRBOT_LAUNCHER env var.  Always emit a Content-Security-Policy header
and only conditionally prepend frame-ancestors 'self' — this keeps
object-src 'none' and base-uri 'self' active under the launcher.
2026-06-03 18:42:15 +08:00
Foolllll
1daa0e3367 fix(compress): improve context compression, improve kv-cache rate of context compression, handle compression model modalities (#8530)
* fix(context): restore turn cap, serialize content parts and tool calls for llm compress, fix AftCompact debug log

Three context-compaction regression fixes after #8226:

1. Restore max_context_length -> enforce_max_turns propagation so
   normal turn-based truncation works again.
2. Serialize ContentPart and ToolCall objects into plain dicts in
   _message_to_dict so llm_compress no longer fails with JSON
   serialization errors.
3. Print _provider_messages (compacted) instead of run_context.messages
   (unchanged) in AftCompact debug log; truncate long role lists to
   first4,...,last4 to avoid log spam.

Assertions in tests are also hardened to avoid coupling to exact prompt
wording.

* fix(tool_loop_agent_runner): simplify context handling by removing redundant provider messages

* fix(tool_loop_agent_runner): rename context manager variables for clarity

* fix: update context compression to use recent token ratio instead of fixed count

* fix: enhance LLMSummaryCompressor to sanitize contexts and improve message handling

* ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-06-03 17:40:05 +08:00
Soulter
df6eef052f fix: fix some bugs in #8226 2026-06-03 10:58:20 +08:00
Rat
f01dc474ef fix(gemini-embedding): wrap batch embedding texts in Content to avoid collapse on gemini-embedding-2 (#8537)
* fix(provider): wrap batch embedding texts in Content to avoid collapse on gemini-embedding-2

* fix(gemini_embedding): format list comprehension for better readability

---------

Co-authored-by: Rat0323 <Rat0323@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-06-03 10:42:04 +08:00
Allen You
072691877d fix(openai-embedding): temporarily fix invalid paramater for SiliconFlow provider's non-Qwen embedding models (#8508)
* fix(openai-embedding): SiliconFlow provider's non-Qwen embedding models do not support dimensions parameter

* fix: accept AI Reviewers' suggestions
2026-06-03 10:38:31 +08:00
tjc66666666
6a467fc043 perf(stt-whisper): close the audio file handle after calling the OpenAI transcription API (#8528)
* 在调用 OpenAI API 后关闭文件句柄再删除临时文件。

核心问题:whisper_api_source.py 第 121 行用 open(audio_url, "rb") 打开文件后,文件句柄没有被关闭,导致 Windows 上报 "另一个程序正在使用此文件" 的错误,temp wav 文件无法删除。
修复方案:在调用 OpenAI API 后关闭文件句柄再删除临时文件。

* fix(whisper_api): use context manager for audio file handling to ensure proper closure

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-06-03 10:32:12 +08:00
tjc66666666
d912e1497c Add check for audio file existence (#8529)
Handle case where audio file may not exist yet.
2026-06-03 10:28:32 +08:00
dependabot[bot]
92b2ce872c chore(deps): bump docker/setup-qemu-action in the github-actions group (#8533)
Bumps the github-actions group with 1 update: [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action).


Updates `docker/setup-qemu-action` from 4.0.0 to 4.1.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-03 10:27:06 +08:00
tjc66666666
4bb1b897df fix: cannot resolve voice when using aiocqhttp adapter (#8523)
Refactor file handling to resolve sources more effectively, including decoding file URIs and handling base64 data. Update methods to ensure compatibility with different file formats and paths.
2026-06-03 10:22:35 +08:00
Ruochen Pan
d2f5551513 fix(ltm): prevent wake commands from being recorded as group chat context (#8536)
* fix(ltm): prevent wake commands from being recorded as group chat context

* test: fix mock event get_extra return value in group context wiring tests

* test: strengthen group context mock and add slash-command skip test
2026-06-03 09:25:01 +08:00
Caleb
25b134444f fix(console): use toast for pip-install error display (#8462)
* fix(console): use toast for pip-install error display

The pip-install dialog displayed error messages as unstyled inline
<small> text with no color differentiation from success messages.
Replaced with useToast() to show errors as red snackbar, consistent
with the rest of the dashboard.

* fix(console): use i18n for pip-install toast fallback messages
2026-06-02 12:52:55 +08:00
Octopus
def81530b0 feat: upgrade MiniMax Token Plan default model to M3 (#8505)
Set MiniMax-M3 as the default fallback model for the Token Plan provider.
The model list itself is already fetched dynamically from the MiniMax API,
so all available models including M3 are auto-discovered. This change just
updates the hardcoded fallback used when no model is configured to the
current flagship.

MiniMax-M2.7 remains fully usable; users can still configure it explicitly.
2026-06-02 12:45:04 +08:00
C₂₂H₂₅NO₆
4b097011cf fix(core): Fix image delivery to the model by treating empty modalities as unconfigured (#8451)
* fix(core): 将空 list modalities 视为未配置,修复图片无法传递到模型的问题

migra_helper 将未配置的 modalities 迁移为空 list [],而新增的
_provider_supports_modality()、_assemble_request_context_for_provider()、
_should_fix_modalities_for_provider()、_func_tool_for_provider() 四个函数
对 [] 和 None 的处理不一致,导致所有未在 WebUI 手动配置 modalities 的
provider 无法传递图片、引用图片被跳过、工具被错误清除。

修改策略:将 [] 与 None 统一视为未配置状态,保持向后兼容。
仅在 modalities 为非空 list 时才启用过滤和修复逻辑。

- _provider_supports_modality: [] 返回 True,默认支持
- _assemble_request_context_for_provider: [] 不过滤图片
- _should_fix_modalities_for_provider: [] 不触发历史上下文修复
- _func_tool_for_provider: [] 不清除工具

复现脚本已确认 Bug 不再复现,82 个相关单元测试全部通过。

* fix(core): 补充修复 tool loop 中 cached images 的 modalities 判断

上一笔 commit 遗漏了 tool_loop_agent_runner.py 第 917 行对
cached images 的 modalities 检查,当 modalities=[] 时,tool call
返回的图片不会被追加到消息中,导致模型看不到 tool 结果中的图片。

修复方式与主修复一致:not modalities or image in modalities

复现脚本和 82 个单元测试全部通过。

* test: 补充 fake_save_image mock 缺少的 mime_type 字段

修复 modalities=[] 导致 cached images 分支变为可达后,暴露
了 test_tool_result_includes_all_calltoolresult_content 中
fake_save_image mock 不完整的问题:返回的 SimpleNamespace
缺少 mime_type 属性,而实际 tool_image_cache.save_image()
始终包含该字段。

---------

Co-authored-by: C₂₂H₂₅NO₆ <Sisyphbaous-DT-Project@users.noreply.github.com>
2026-06-02 08:53:59 +08:00
NayukiChiba
7d45a247d5 fix(message): Fix private message sending failure caused by extra fields in Reply component's toDict method (#8477)
- Reply.toDict() 继承 BaseMessageComponent.toDict() 会将所有非 None 默认字段序列化,导致 OneBot V11 reply 段包含多余字段,引起私聊引用回复失败(message not found)
- 重写 Reply.toDict() 方法,仅返回 {"type": "reply", "data": {"id": str(self.id)}},符合协议标准
- 新增 tests/unit/test_aiocqhttp_reply.py,覆盖 Reply.toDict() 输出格式、_parse_onebot_json 路径及私聊发送场景的验证
2026-06-02 08:40:55 +08:00
鸦羽
e8d13af5b9 feat: add TOTP two-factor authentication for dashboard login (#8189)
* feat: add TOTP two-factor authentication for dashboard login

* fix: ensure TOTP verification uses UTC for accurate time comparison

* fix: update recovery code validation logic for disabling TOTP

* test: add unit tests for TOTP functionality and recovery code validation

* chore: format

* feat: add trust_proxy_headers switch for auth rate-limit IP source

* feat: make dashboard auth rate-limit configurable via system settings

Add auth_rate_limit config block to dashboard settings with enable
(default: true), average_interval (default: 1.0s), and max_burst
(default: 3) options. The dashboard auth middleware now reads from
config instead of using hardcoded values. The average_interval and
max_burst fields are conditionally shown only when rate limiting is
enabled.

* fix: normalize dashboard client IP from trusted proxy headers

* refactor: encapsulate rate limiter state into registry, add TTL

* feat: show dynamic page title during two-factor verification

* fix: require two-factor verification for protected config saves

* chore: format

* refactor: reorganize TOTP verification UI components for better layout

* refactor: clean up recovery stage UI by removing unused styles and improving label handling

* docs: add TOTP two-factor authentication documentation for WebUI

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-06-01 16:40:29 +08:00
lingyun14
e4044cc5a0 fix: waking bot with a reply component and empty user prompt (#8461)
* Update internal.py

* Update astr_main_agent.py

* Update astr_main_agent.py

* ruff

* Update astr_main_agent.py
2026-06-01 10:03:24 +08:00
千岚之夏
c89ac61892 feat: dynamically fetch model list for MiniMax Token Plan (#8475) 2026-06-01 09:59:52 +08:00
Rain-0x01_
fbc0633cd3 chore: fix token terminology in zh (#8465) 2026-05-31 21:54:44 +08:00
copilot-swe-agent[bot]
99f57c9897 Harden selector writes against prototype pollution 2026-05-30 15:25:02 +00:00
copilot-swe-agent[bot]
480c078c3e Merge master into dev to resolve conflicts 2026-05-30 15:21:49 +00:00
LIghtJUNction
5990576db9 Potential fix for code scanning alert no. 89: Binding a socket to all network interfaces
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-05-30 23:18:11 +08:00
Misaka Mikoto
90a3a2171a fix: Template config optimization (#8228)
* fix: improve template list config handling

* feat(webui): show template list display item

* feat(webui): allow hiding template list hints

* docs: document template list metadata fields

* fix: support file fields in template list configs
2026-05-30 22:13:09 +08:00
LIghtJUNction
1b1ae10ffd ruff 2026-05-30 21:46:06 +08:00
Soulter
0e973bd4d4 chore: bump version to 4.25.2 2026-05-30 20:10:51 +08:00
Soulter
b0bb5c7477 fix(chatui): reasoning summary 2026-05-30 20:06:20 +08:00
Weilong Liao
0da17485bd fix(plugin_manager): improve plugin state cleanup and add tests for unbinding and loading plugins (#8441)
fixes: #8439
2026-05-30 18:45:33 +08:00
Weilong Liao
b8cf2ef552 fix: recording issue on chatui (#8440)
#8364
2026-05-30 18:04:25 +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
LIghtJUNction
a368609208 Merge remote-tracking branch 'origin/master' into dev
# Conflicts:
#	astrbot/core/astr_main_agent.py
#	astrbot/core/db/__init__.py
#	astrbot/core/db/vec_db/faiss_impl/document_storage.py
#	astrbot/core/message/components.py
#	astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py
#	astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py
#	astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py
#	astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_server.py
#	astrbot/core/provider/sources/anthropic_source.py
#	astrbot/core/provider/sources/openai_source.py
#	astrbot/dashboard/routes/command.py
#	astrbot/dashboard/routes/static_file.py
#	astrbot/dashboard/server.py
#	dashboard/package.json
#	dashboard/src/components/chat/ChatInput.vue
#	dashboard/src/components/chat/ChatMessageList.vue
#	dashboard/src/components/chat/MessageList.vue
#	dashboard/src/components/chat/StandaloneChat.vue
#	dashboard/src/components/chat/message_list_comps/ReasoningBlock.vue
#	dashboard/src/components/provider/ProviderSourcesPanel.vue
#	dashboard/src/components/shared/ExtensionCard.vue
#	dashboard/src/components/shared/ListConfigItem.vue
#	dashboard/src/composables/useProviderSources.ts
#	dashboard/src/utils/providerUtils.js
#	dashboard/src/views/extension/InstalledPluginsTab.vue
#	docs/zh/dev/star/plugin.md
2026-05-30 16:59:16 +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
千岚之夏
d16e6a869e fix: Dashboard list config item cannot input spaces (#8403)
* fix: Dashboard list config item cannot input spaces (#8393)

* docs: add comment clarifying pure-space filtering in watch is expected behavior
2026-05-29 13:03:56 +08:00
M1LKT
cea37707a5 feat: 为已配置的模型增加能力图标 (#8405) 2026-05-29 13:02:46 +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
Yufeng He
9688a64cd5 fix(dashboard): add sub-command count label (#8388) 2026-05-28 10:12:00 +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
lingyun14
465a685b66 feat: add EULA hint for first notification (#7955)
* docs: add FIRST_NOTICE.ru-RU.md

* docs: add metrics notice to FIRST_NOTICE files

* docs: add metrics notice to FIRST_NOTICE

* docs: update FIRST_NOTICE to reference system config

* docs: update FIRST_NOTICE to reference system config

* docs: update FIRST_NOTICE to reference system config

* Update FIRST_NOTICE.md

* Update FIRST_NOTICE.en-US.md

* Update FIRST_NOTICE.ru-RU.md
2026-05-27 21:33:41 +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
Simon He
ae44163bb3 feat: enable smooth markdown streaming (#8371) 2026-05-27 20:30:16 +08:00
dependabot[bot]
284c4082f3 chore(deps): bump the github-actions group with 3 updates (#8335)
Bumps the github-actions group with 3 updates: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action), [docker/login-action](https://github.com/docker/login-action) and [docker/build-push-action](https://github.com/docker/build-push-action).


Updates `docker/setup-buildx-action` from 4.0.0 to 4.1.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v4.0.0...v4.1.0)

Updates `docker/login-action` from 4.1.0 to 4.2.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v4.1.0...v4.2.0)

Updates `docker/build-push-action` from 7.1.0 to 7.2.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v7.1.0...v7.2.0)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: docker/login-action
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: docker/build-push-action
  dependency-version: 7.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-27 12:00:42 +08:00
letr
bc35daa110 fix(webui): restore mobile provider source deletion (#8321)
* fix(webui): restore mobile provider source deletion

* fix(webui): improve provider source delete accessibility
2026-05-27 11:59:06 +08:00
F. Abyssalis
000d638c1b fixed typo in the Chinese documentation for the QQ official WebSocket bot setup. (#8351) 2026-05-27 11:56:28 +08:00
香草味的纳西妲喵
7ff58f2938 fix(docs): Update FAQ, add description of hard refresh (force reload) of the page. (#8359) 2026-05-27 08:44:23 +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
lingyun14
fd4fe84310 fix: docs (#8229)
* Update listen-message-event.md

* Update other.md

* Update send-message.md

* Update ai.md

* Update ai.md

* Update send-message.md

* Update listen-message-event.md

* Delete docs/zh/dev/star/guides/env.md

* Delete docs/en/dev/star/guides/env.md

* Update simple.md

* Update discord.md

* Update discord.md

* Update matrix.md

* Update matrix.md

* Update index.md

* Update index.md

* Update openapi.md

* Update ppio.md

* Update ppio.md

* Update function-calling.md

* Update function-calling.md

* Update config.mjs

* docs: add EN desktop deployment page

* Update plugin.md

* Update ai.md

* Update ai.md

* Update ai.md

* Update desktop.md
2026-05-22 20:35:29 +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
LIghtJUNction
f48c11439b refactor(core): remove tools prompts module 2026-05-22 17:39:07 +08:00
LIghtJUNction
9528f1ca95 fix service command root path helpers 2026-05-22 17:17:30 +08:00
LIghtJUNction
96d189fadc Merge remote-tracking branch 'origin/feat/service-command' into dev 2026-05-22 16:51:59 +08:00
Soulter
250baccf5b feat(service): update Windows service command to use PowerShell and enhance task XML configuration 2026-05-22 15:37:38 +08:00
LIghtJUNction
7c224ebbd2 ruff check && format 2026-05-22 15:23:24 +08:00
LIghtJUNction
944afc4b33 Merge remote-tracking branch 'origin' into dev
# Conflicts:
#	astrbot/builtin_stars/astrbot/main.py
#	astrbot/cli/__main__.py
#	astrbot/cli/commands/__init__.py
#	astrbot/core/provider/sources/openai_source.py
2026-05-22 15:19:54 +08:00
Soulter
97f0fd3de3 feat: add CLI commands documentation and service management features
- Updated the VitePress configuration to include links to CLI commands in both English and Chinese.
- Enhanced the AstrBot deployment documentation with instructions for installing it as a system service.
- Created comprehensive CLI commands documentation covering initialization, service management, configuration, and plugin management.
- Added tests for CLI command aliases and service functionalities to ensure proper command registration and behavior.
- Implemented service log management features, including enabling application logging and controlling log visibility.
2026-05-21 23:44:28 +08:00
LIghtJUNction
3f4f171530 fix: resolve type warnings across core modules 2026-05-21 22:45:44 +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
LIghtJUNction
fb4f76af63 Merge remote-tracking branch 'origin/master' into dev 2026-05-21 19:17:37 +08:00
LIghtJUNction
4098303658 refactor: miscellaneous updates across modules 2026-05-21 19:10:02 +08:00
LIghtJUNction
01aafc21dd fix: resolve circular import in updator.py 2026-05-21 19:08:45 +08:00
M1LKT
165933545d feat: Automate generation of the MDI icon font subset during dashboard dev and build workflows (#8264)
* feat: ignore字体集的生成文件,并在编译时自动生成

* 移除preview的前置运行

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>
2026-05-21 08:48:12 +08:00
Yufeng He
c4693fa68e fix: support rst and adoc knowledge uploads (#8255) 2026-05-20 14:38:16 +08:00
LIghtJUNction
0b4cf94414 chore: fix zip_updator lint errors and allowlist existing frontend violations 2026-05-19 21:44:03 +08:00
LIghtJUNction
03b337395f fix: add missing Any import in zip_updator 2026-05-19 21:26:56 +08:00
LIghtJUNction
ec0baa4dc0 Merge remote-tracking branch 'origin' into dev 2026-05-19 21:23:04 +08:00
LIghtJUNction
92c58f8a2a fix: resolve merge follow-ups (typing, imports, frontend tests) 2026-05-19 21:16:25 +08:00
LIghtJUNction
987099d4cb chore: merge origin/master into dev 2026-05-19 21:15:22 +08:00
Jianyu Li
7a9fb33dd9 docs: fix typo of the count in FAQ deletion instructions (#8235)
Correct the number of fields to be deleted from five to six in the instructions.
2026-05-19 14:41:58 +08:00
dependabot[bot]
de0a7afdcf chore(deps): bump pnpm/action-setup in the github-actions group (#8233)
Bumps the github-actions group with 1 update: [pnpm/action-setup](https://github.com/pnpm/action-setup).


Updates `pnpm/action-setup` from 6.0.7 to 6.0.8
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v6.0.7...v6.0.8)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: 6.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 13:21:03 +09:00
Yufeng He
5bbcdced0f fix: skip empty llm summaries (#8195) 2026-05-19 09:38:55 +08:00
Soulter
dceacd5a87 docs: update release version instructions in AGENTS.md 2026-05-17 15:07:39 +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
Midwich
b3381c6448 fix(webui): add Noto Sans to global font-family stack for Cyrillic text (#8205)
PR #8015 added 'Noto Sans' to the Google Fonts link and CJK fallback list,
but the font was placed at the end of $cjk-sans-fallback where browsers
never reach it for Cyrillic text. The global $body-font-family also lacked
'Outfit' entirely, causing Vuetify to use CJK fonts as the primary face.

Changes:
- Remove 'Noto Sans' from the end of $cjk-sans-fallback (it is not a CJK font)
- Add 'Outfit' and 'Noto Sans' to $body-font-family before CJK fallbacks
- Update .Outfit class in _container.scss to match the new stack

This ensures:
- Latin text → Outfit
- Cyrillic text → Noto Sans (loaded by vite-plugin-webfont-dl)
- CJK text → Noto Sans SC / PingFang SC etc.

Fixes follow-up to #8015.
2026-05-16 22:03:13 +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
Dale Null
98acd9f0da chore: reformat with ruff 2026-05-15 16:41:51 +08:00
Dale Null
c665b6e3e5 chore: reduce pyright type errors 2026-05-15 16:31:37 +08:00
Weilong Liao
6982ef7d94 feat(weixin_oc): handle session timeout and clear login state (#8196) 2026-05-15 15:30:56 +08:00
Midwich
1a0306343a fix(webui): add Noto Sans font support for Cyrillic text (#8015)
The WebUI only loaded Noto Sans SC (Simplified Chinese), which lacks
Cyrillic glyphs. Russian text fell back to system sans-serif, causing
poor rendering depending on the OS.

Changes:
- Load Noto Sans (regular) from Google Fonts alongside Noto Sans SC
- Add 'Noto Sans' at the END of $cjk-sans-fallback (after CJK fonts)
  so Chinese text still renders with system CJK fonts first,
  while Cyrillic text falls through to Noto Sans.

This ensures both Chinese and Cyrillic text render correctly.
2026-05-15 13:36:37 +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
M1LKT
720d384b44 fix: synchronize the autoScroll state of the consoleDisplayer component using $refs (#8186) 2026-05-14 11:44:42 +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
lingyun14
ef73d2da33 docs: Clarify and expand the LLM tool registration guidance in the AI plugin documentation (#8178)
* docs(zh/ai): fix misleading tool registration guide and add warnings

* docs(en/ai): add tool registration section with deprecation warnings
2026-05-14 08:58:37 +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
Soulter
e05dd650ab feat(auth): add legacy password login failure message and FAQ guidance for upgrade issues 2026-05-14 00:48:15 +08:00
Soulter
93428a7976 feat: add initial dashboard password resolution from environment variable 2026-05-14 00:45:37 +08:00
Soulter
37142fd253 feat: enhance update dialog with progress tracking and localization updates
- Added advanced settings option in update dialog for better user control.
- Implemented detailed progress tracking for update stages including download size and speed.
- Updated localization files for English, Russian, and Chinese to include new strings for update progress and advanced settings.
- Improved UI for update dialog with better layout and responsiveness.
- Enhanced test coverage for update process including progress tracking.
2026-05-14 00:40:24 +08:00
Tsukumi
1b09132e4a fix: respect explicit Shipyard Neo profile (#8167) 2026-05-13 14:38:11 +08:00
NayukiMeko
22ba831a31 fix(message_tools): throw exception and block message sending when path does not exist (#8149)
* fix(message_tools): 路径不存在时抛出异常并阻止消息发送

- _resolve_path_from_sandbox 在所有解析路径均失败时改为抛出 FileNotFoundError,而非静默返回原始路径,避免将无效路径传递给下游组件
- 新增 component_type 关键字参数,使错误信息能明确指出是 image/record/video/file 哪类资源路径缺失
- 在 call 方法中捕获 FileNotFoundError 并提前返回错误字符串,确保路径无效时不会继续构建或发送任何消息组件
- 补充单元测试,验证缺失图片路径场景下 send_message 不会被调用

* Update tests/unit/test_message_tools.py

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

* fix(tools): propagate sandbox error instead of masking as FileNotFoundError

---------

Co-authored-by: Ruochen Pan <badbatch0x01@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: RC-CHN <1051989940@qq.com>
2026-05-13 11:50:06 +08:00
Soulter
4672a04eb7 docs: update FAQ to clarify default password usage for first-time login 2026-05-13 01:50:37 +08:00
Soulter
c48108040c chore: bump version to 4.24.4 2026-05-13 01:46:08 +08:00
Soulter
2d6f5e64b8 fix(auth): update login failure message for first-time users with details on random password 2026-05-13 01:37:35 +08:00
Soulter
7d72e3a9e7 docs: update FAQ with details on first login account and random password generation 2026-05-13 00:37:24 +08:00
Soulter
37d6159234 docs: update login instructions to use random initial password for first-time users 2026-05-13 00:24:21 +08:00
Soulter
989cc0d609 chore: bump version to 4.24.3 2026-05-13 00:17:27 +08:00
lingyun14
cb90de752d fix(docs): fix multiple errors in plugin development guides (#8166)
* Update listen-message-event.md

* Update listen-message-event.md

* Update ai.md

* Update plugin-new.md

* Update plugin-new.md

* Update simple.md

* Update star_handler.py

* Update listen-message-event.md

* Update listen-message-event.md
2026-05-13 00:04:12 +08:00
Soulter
48e111e47e chore: remove test 2026-05-12 23:57:16 +08:00
Weilong Liao
7ddf6371b9 fix(webui): enforce 12-char dashboard password policy with backend+frontend validation (#7338)
* fix(webui): enforce 12-char dashboard password policy with backend+frontend validation

* fix(i18n): update password policy hints and validation rules for improved security

* test: adapt dashboard auth fixtures for hashed default password

* fix(security): increase PBKDF2 iterations

* feat(auth): implement secure login challenge and proof verification

* chore: ruff format

* fix(auth): update md5 import syntax for consistency

* feat(dashboard): implement random password generation for empty dashboard password

* feat(auth): enforce plaintext password requirement for legacy MD5 hashes

* fix(i18n): update password hint texts to reflect auto-generated initial passwords

* feat(dashboard): implement password change requirement and reset logic

* feat(auth): implement account setup flow and password change requirements

* feat: Implement legacy password support and upgrade mechanism

- Added `hash_legacy_dashboard_password` function for MD5 hashing of passwords.
- Updated configuration handling to store both PBKDF2 and legacy password hashes.
- Introduced logic to check if password storage has been upgraded and if a password change is required.
- Modified dashboard authentication routes to handle legacy password checks and prompts for upgrades.
- Updated frontend to display warnings for legacy password storage and required upgrades.
- Enhanced tests to cover scenarios for legacy password handling and migration to new storage format.

* fix(logo): update text color styles to use CSS variables for consistency

* feat(dashboard): upgrade password storage and enforce change requirement

* fix(dashboard): update minimum password length from 12 to 10 characters

* fix(dashboard): update minimum password length from 10 to 8 characters

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-05-12 23:46:57 +08:00
Yufeng He
f86de988a4 fix: keep Discord startup alive on command quota (#8061)
* fix: keep Discord startup alive on command quota

* Update discord_platform_adapter.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-05-12 23:28:23 +08:00
dependabot[bot]
1d3f54ca49 chore(deps): bump pnpm/action-setup in the github-actions group (#8156)
Bumps the github-actions group with 1 update: [pnpm/action-setup](https://github.com/pnpm/action-setup).


Updates `pnpm/action-setup` from 6.0.5 to 6.0.7
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v6.0.5...v6.0.7)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: 6.0.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 23:16:19 +08:00
jdjfjdsfj
f6a99a25b9 Update API Key reference in knowledge-base.md (#8129)
* Update API Key reference in knowledge-base.md

* Update docs/zh/use/knowledge-base.md

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>
2026-05-12 08:43:53 +08:00
NayukiMeko
041c35c35b Fix: Fix issue where temporary directory is not cleaned and error tracking false positives when repeatedly installing plugins (#8148)
* fix(star): 修复重复安装插件时临时目录未清理及错误追踪误报问题

- 引入 skip_failed_tracking 标志,当目标目录已存在时跳过失败安装追踪,避免将预期冲突错误误记为安装失败
- 修复 finally 块中临时目录清理逻辑,确保冲突场景下 plugin_upload_* 临时目录也能被正确删除
- 新增测试用例 test_install_plugin_from_file_conflict_keeps_failed_plugins_clean,验证重复安装同名插件时 failed_plugin_dict 为空且无残留临时目录

Ref #8122

* style(star): ruff 格式化
2026-05-11 16:36:03 +08:00
エイカク
ad516950f2 fix(provider): force Gemini chat client to use managed httpx client (#8112)
When both aiohttp and httpx are installed, google-genai prefers aiohttp
as the async HTTP backend. In error response paths, the aiohttp backend
returns raw aiohttp.ClientResponse objects that google-genai cannot handle,
masking real API errors with:
  Unsupported response type: <class 'aiohttp.client_reqrep.ClientResponse'>

This fix explicitly creates an httpx.AsyncClient and passes it via
HttpOptions.httpx_async_client, ensuring the chat provider always uses
the httpx backend. The managed client is closed in terminate().

- Preserve HTTP_PROXY/HTTPS_PROXY support via trust_env=True.
- Preserve provider-level proxy via httpx.AsyncClient(proxy=...).
- Avoid logging full proxy URLs for security.

Fixes #7564
2026-05-10 00:20:36 +09:00
lingyun14
c9182c27a2 fix: fix console log level alignment and mobile layout issue (#7988)
* fix: fix console log level alignment and mobile layout issue

* Update ConsoleDisplayer.vue
2026-05-09 22:18:21 +08:00
lingyun14
bd9aade842 fix(docs):多份文档汉译英并整理 (#8001)
* docs(en): translate plugin-platform-adapter.md from Chinese to English

* docs(en): translate plugin-platform-adapter.md from Chinese to English

* Update ppio.md

* Update provider-lmstudio.md

* Update function-calling.md

* Update skills.md

* Update ai.md

* Update simple.md

* Update mcp.md

* Update config.mjs kook

* fix(docs): fix MessageSesion import path in platform adapter example

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>
2026-05-09 22:17:47 +08:00
dependabot[bot]
4bcaaab44f chore(deps): bump pnpm/action-setup in the github-actions group (#8004)
Bumps the github-actions group with 1 update: [pnpm/action-setup](https://github.com/pnpm/action-setup).


Updates `pnpm/action-setup` from 6.0.3 to 6.0.5
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v6.0.3...v6.0.5)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: 6.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-09 22:16:30 +08:00
AstrBot
224915fbc8 docs: add 16MB size limit note for plugin publishing (#8108)
Add documentation to clarify the 16MB zip size limit for plugin
marketplace submissions, along with practical recommendations:
- Compress static assets like images
- Clean up unnecessary files (.git, __pycache__, etc.)
- Optimize dependency sizes
- Use .gitattributes or release branches

Also mention the option to contact maintainers for manual bypass
when the limit cannot be met.

Co-authored-by: Seio <seio@astrbot.app>
2026-05-09 22:00:15 +08:00
M1LKT
f9cbe79099 fix(ui): always show actions btn instead of on hover in OutlinedActionListItem (#8081) 2026-05-09 08:41:26 +08:00
AstrBot
77fa0e466c docs: update Trendshift badge to AstrBotDevs repo (#21369) for all README languages (#8079)
Co-authored-by: AstrBot <astrbot@container>
2026-05-08 15:41:56 +08:00
Ruochen Pan
f29b339ea2 fix(t2i): validate template content to prevent Jinja2 SSTI injection (#8077)
* fix(t2i): validate template content to prevent Jinja2 SSTI injection

* fix(t2i): add error feedback

* fix(test): update assertion to match previous commits

* style: format code
2026-05-08 15:30:52 +08:00
LIghtJUNction
273b6777cf test: fix unit tests after master→dev merge
- Fix test_long_term_memory.py: Image(file=), Provider spec, config keys
- Fix test_star_manager.py: Metric.upload AsyncMock, os.path.exists patch
- Fix test_kb_helper.py: chunk assertion signature, session.begin mock
- Fix test_file_extract.py: match actual code behavior (AsyncClient created before read)
- Fix test_pipeline_process_stage/respond_stage.py: reload stage modules to avoid stale imports from bootstrap tests
- Fix test_provider_register.py: handle pre-existing registry entries
- Fix test_pipeline_scheduler.py: remove blanket xfail, apply per-test xfail
- Mark 23 lifecycle tests xfail due to state machine changes
- Fix scheduler.py: missing break after generator stage stops propagation
- Frontend build verified
2026-05-08 12:17:58 +08:00
LIghtJUNction
d373a24320 merge: sync origin/master into dev
Resolved 76 file conflicts across backend, frontend, and tests:
- Core backend: agent, platform, provider, star, tools, cron, KB, utils
- Dashboard backend: auth, config, plugin routes, server, runtime bootstrap
- Frontend components: shared, extension, provider components
- Frontend views: console, trace, cron, extension, platform, provider, etc.
- Frontend infrastructure: layouts, router, stores, main.ts
- Assets: MDI font subset (css, woff, woff2)
- Tests: fixtures, plugin manager, anthropic provider, dashboard tests

Strategy per file:
- Most backend: merged master improvements (metrics, http_client -> default_headers,
  download_url params, plugin i18n, runtime guards, auth middleware)
- Frontend views: adopted master dashboard-shell layout (v-container, is-dark theme)
- InstalledPluginsTab: kept dev pinned-plugins feature (drag-sort, pin/unpin)
- Binary assets: resolved via git checkout
- Tests: merged both branches' assertions and mock updates
2026-05-08 11:04:03 +08:00
エイカク
f02845ebdc fix(config): expose cua idle timeout in dashboard (#8075)
* fix(config): expose cua idle timeout in dashboard

* fix(config): remove exposed cua ttl setting

* fix(config): centralize cua idle timeout default
2026-05-08 10:08:53 +09:00
エイカク
49cd4d2a20 feat(cua): expire idle sandbox sessions (#8074)
* feat(cua): expire idle sandbox sessions

* fix(cua): simplify idle timeout state
2026-05-08 09:41:59 +09:00
Yufeng He
116c66b5b7 fix: skip KB retrieval for blank prompts (#8073) 2026-05-08 08:35:24 +08:00
LIghtJUNction
e9c348199c wip: current local changes before squash rebase 2026-05-08 06:57:08 +08:00
エイカク
5745ce5b80 fix(cua): use native file interfaces for uploads (#8069) 2026-05-08 02:36:43 +09:00
AstrBot
dd716e61a4 feat: add visual separator between thinking content and response (#8059)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-07 22:19:50 +08:00
Ruochen Pan
718449d6ac fix(core): use correct asset filename in GitHub fallback download URL (#8046)
* fix(core): use correct asset filename in GitHub fallback download URL

* fix(core):resolve the tag via GitHub API with certifi SSL and proxy support.
2026-05-07 09:00:56 +08:00
エイカク
d1059cd504 fix windows updater zip root path normalization (#8019)
* fix: normalize updater zip root paths on windows

* refactor: share updater archive path normalization

* test: expand updater archive root coverage

* fix: guard empty updater archive roots

* refactor: share updater extraction safeguards

* refactor: simplify updater extraction cleanup

* refactor: inline updater root normalization

* fix: infer archive root from zip entries
2026-05-07 09:41:45 +09:00
Ruochen Pan
b32cc8d273 feat(console): persist auto-scroll toggle state in localStorage (#8024) 2026-05-06 10:55:32 +08:00
千岚之夏
e8d3e1837c feat: add disable_metrics config option for WebUI (#7946)
* feat: add disable_metrics config option for WebUI

* fix: remove dead code _disable_metrics, narrow exception catching

* fix: add Russian translation for disable_metrics

* fix: 将 disable_metrics 移到系统配置

* fix: 将 disable_metrics 元数据从 general 移到 system 分组

---------

Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>
2026-05-06 09:02:35 +08:00
168SDTH
942dcdfc77 Fix: typo in API Key environment variable example (#7977) 2026-05-06 08:50:24 +08:00
Rhonin Wang
b4e1181d1e fix(config): hide Baidu web search key when disabled (#7992)
* fix(config): hide Baidu web search key when disabled

* chore: remove unnecessary test change

---------

Co-authored-by: RhoninSeiei <RhoninSeiei@users.noreply.github.com>
Co-authored-by: Rhonin <rhonin@STARFORGE.localdomain>
2026-05-06 08:49:11 +08:00
Midwich
7a519d4d1e fix(config): add missing websearch_firecrawl_key to DEFAULT_CONFIG (#8012)
The websearch_firecrawl_key config key was added in PR #7764 (Firecrawl
web search provider) but was missing from DEFAULT_CONFIG in default.py.

Because AstrBotConfig.check_config_integrity() removes keys that exist
in the user's cmd_config.json but are absent from DEFAULT_CONFIG, the
firecrawl API key is silently deleted on every container restart.

Fixes: unreported issue (config key removed on restart)
2026-05-06 08:47:04 +08:00
Haoran Xu
44e8c0061e fix: preserve folder parent on rename (#7974) 2026-05-05 21:16:53 +08:00
Helian Nuits
0830f48ae0 fix: resolve path conflicts and improve self-healing during backup restore and plugin installation (#7737)
* fix(数据备份与恢复): 解决备份恢复和插件安装过程中的路径冲突及自愈问题

1. 修复备份导入时目录条目被误识别为 0 字节文件的问题。
2. 增加插件加载和数据目录创建时的路径冲突自动清理逻辑。
3. 增强插件解压安装过程对现有冲突文件的兼容性。
4. 优化 remove_dir 工具类使其支持同时处理文件和目录的删除。

* fix(core): 根据 CR 建议实现通用的路径冲突自愈机制并增强损坏符号链接的处理能力
2026-05-05 01:05:43 +08:00
千岚之夏
9165278d21 fix: update contributors image max count to 300 (#8000)
* fix: update contributors image max count to 210

* fix: remove BOM from all README files

PR #8000 follow-up: Sourcery and codereview agent flagged UTF-8 BOM
in 6 README files. BOM is unnecessary in UTF-8 and may cause
compatibility issues with Markdown parsers.

* fix: update contributors image to 300 with 15 columns

---------

Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>
2026-05-05 00:53:22 +08:00
elecvoid243
e410adc188 fix: encoding issue in windows when using python tool 2026-05-05 00:03:33 +08:00
Weilong Liao
cb4f941e43 feat: enhance plugin page internationalization (#7998)
* feat: enhance plugin page internationalization

- Updated PluginRoute to read initial context from JWT and set it in the bridge SDK.
- Added methods to retrieve locale and plugin metadata for better i18n support.
- Enhanced pluginI18n utility to resolve page-specific translations and added new functions for page titles and descriptions.
- Modified PluginPagePage and PluginDetailPage to utilize new i18n features for dynamic content rendering.
- Improved documentation for plugin page i18n structure and usage.
- Added tests to verify the correct integration of i18n in plugin pages and context handling.

* fix test
2026-05-04 20:15:21 +08:00
Soulter
319f50be2a feat: plugin changelogs and update system 2026-05-04 20:03:01 +08:00
lingyun14
ca1a6c8c7f fix(docs): Fix multiple errors in the document, including broken links, spelling errors, and step numbering. (#7979)
* fix: remove trailing comma in JSON example in plugin-config doc

* fix: remove trailing comma in JSON example in plugin-config doc

* Update knowledge-base.md

* Update knowledge-base.md

* Update websearch.md

* Update websearch.md

* Update websearch.md

* Update plugin-publish.md

* Update lark.md

* Update unified-webhook.md

* Update discord.md

* Update wecom.md

* html

* html

* Update websearch.md

* html

* Update start.md

* Update start.md

* Apply suggestions from code review

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>
2026-05-04 10:59:06 +08:00
Soulter
39386eeb3e chore: bump version to 4.24.2 2026-05-04 00:21:43 +08:00
Soulter
bc2c67d4d7 fix: support dynamic plugin web api routes 2026-05-04 00:21:02 +08:00
Soulter
010e6d2eda chore: bump version to 4.24.1 2026-05-03 23:00:16 +08:00
Soulter
afe999550d chore: bump version to 4.24.0 2026-05-03 22:20:25 +08:00
Weilong Liao
93a6152eee feat: add temporary extra user content parts (#7976)
* feat: add temporary extra user content parts

* fix: 3.10
2026-05-03 22:11:24 +08:00
lxfight
fff9c8ee19 feat: supports plugin to register custom pages (webui) (#5940)
* feat(plugin): add webui metadata schema for plugins

* feat(dashboard): serve plugin webui with scoped asset tokens

* feat(dashboard): add plugin webui page and extension entry actions

* test(dashboard): cover plugin webui auth and asset routing

* fix(dashboard): use aiofiles for non-blocking plugin webui assets

* fix(dashboard): streamline JWT extraction and validation for plugin webui paths

* fix(dashboard): harden plugin webui bridge and auth cookie security

* fix(dashboard): restore plugin webui bridge under sandbox iframe

* refactor(dashboard): apply plugin webui review improvements

* docs: 补充插件 WebUI 开发指南

* fix(plugin-webui): 统一 WebUI title 契约并修复桥接行为

* docs: 更新插件 WebUI 开发指南

* fix

* feat: Introduce Plugin Pages feature

- Added support for plugins to expose Dashboard pages via a `pages/` directory.
- Updated `PluginDetailPage.vue` to include a button for opening plugin pages.
- Refactored `useExtensionPage.js` to remove the deprecated `openPluginWebUI` function.
- Updated documentation to replace references from "Plugin WebUI" to "Plugin Pages".
- Created new documentation for Plugin Pages detailing structure, examples, and API usage.
- Removed the old Plugin WebUI documentation.
- Updated tests to reflect changes from Plugin WebUI to Plugin Pages, ensuring proper functionality and security checks.

* feat: 增强插件页面功能,添加返回按钮逻辑并更新测试用例

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Soulter <905617992@qq.com>
Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-03 20:41:50 +08:00
Soulter
6eb8a51c70 docs: system prompt guide 2026-05-03 20:14:15 +08:00
Weilong Liao
f2370cd1ba 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>
2026-05-03 16:37:36 +08:00
千岚之夏
859ab28d43 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>
2026-05-03 15:09:49 +08:00
Haoran Xu
9e09299dcb 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>
2026-05-03 15:08:10 +08:00
Soulter
77fe2de2c1 fix: ruff format 2026-05-03 14:49:05 +08:00
wanger
af6632769e 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>
2026-05-03 14:41:12 +08:00
NayukiMeko
8098a92f33 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>
2026-05-03 14:37:37 +08:00
Soulter
cc4b6817a7 docs: update knowledge base docs
closes: #7962
2026-05-03 14:11:21 +08:00
Soulter
dee4f14a0a chore: ruff format 2026-05-02 15:02:06 +08:00
Soulter
56ec44eb07 chore: remove redundant logger messages and improve log clarity
Co-authored-by: Copilot <copilot@github.com>
2026-05-02 15:00:33 +08:00
Soulter
750597d848 perf: improve logic of adding models
Co-authored-by: piexian <piexian@users.noreply.github.com>
2026-05-02 14:31:09 +08:00
Pink YuDeer
1f9c2c2b50 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>
2026-05-02 12:46:34 +08:00
AstralSolipsism
03deebdd88 fix: 支持微信客服文件消息 (#7923)
* fix: 支持微信客服文件消息

* fix: remove WeCom file message placeholder
2026-05-02 12:18:08 +08:00
leonforcode
909b4ad064 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>
2026-05-02 12:17:52 +08:00
AstrBot
aa0b7a2c4a feat: add fallback_max_context_tokens config for context compression (#7942)
- New config item fallback_max_context_tokens (default 128k)
- When max_context_tokens is 0 and model not in LLM_METADATAS,
  use fallback_max_context_tokens as the context window limit
- Unified global config under provider_settings, in truncate_and_compress section
- i18n: zh-CN, en-US, ru-RU

Co-authored-by: AstrBot <astrbot@container>
2026-05-01 20:13:13 +08:00
Xu Haoran
a1ccb02cbd fix: avoid success toast on failed provider test (#7934) 2026-05-01 18:33:41 +08:00
千岚之夏
ab08759893 fix: 优化上下文管理策略 UI 文案,明确执行顺序 (#7920)
* fix: clarify context management UI text to explain execution order

* fix: update hint references to match updated description names

---------

Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>
2026-05-01 18:28:27 +08:00
lingyun14
cf6d586eb9 fix/stop-event-state-reset-by-clear-result (#7922) 2026-05-01 15:20:51 +08:00
Weilong Liao
bc1e7c9538 feat: add short description support for plugin (#7931)
short description will be displayed in the plugin card
2026-05-01 13:53:00 +08:00
Weilong Liao
ac5cb9b529 feat: supports to download plugins via astrbot official plugin storage (#7930)
* feat: supports to download plugins via astrbot official plugin storage

* fix: improve exception message for missing root directory name in PluginUpdator
2026-05-01 13:42:40 +08:00
Soulter
1aacb46289 fix: improve error message for invalid session format in SendMessageToUserTool
Co-authored-by: Copilot <copilot@github.com>
2026-05-01 13:09:27 +08:00
Soulter
a23350109c perf: metrics 2026-05-01 01:47:33 +08:00
NayukiMeko
ffc31b305c fix(#7904): QQ官方私聊主动推送不再因缺少缓存 msg_id 而跳过发送 (#7914)
* fix: QQ官方私聊主动推送不再因缺少缓存 msg_id 而跳过发送 (#7904)

- 私聊场景下 _send_by_session_common 在无缓存 msg_id 时提前 return,
导致重启后 cron 等主动推送的消息无法发送。
- 私聊主动推送不需要 msg_id,跳过此检查。

* test: 补充 QQ 官方群聊有缓存 msg_id 时正常发送的测试 (#7904)

* Delete tests/unit/test_qqofficial_adapter.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-05-01 00:41:40 +08:00
Soulter
6f83917336 feat: Enhance plugin detail and installation experience with new UI elements and internationalization support 2026-05-01 00:16:42 +08:00
Weilong Liao
2e49eb8455 feat: Implement plugin internationalization support (#7919)
* feat: Implement plugin internationalization support

- Added support for plugins to provide localized names, descriptions, and configuration texts through JSON files in the `.astrbot-plugin/i18n` directory.
- Updated various components to utilize the new internationalization functions, including `ConfigItemRenderer`, `ExtensionCard`, `ItemCard`, `ObjectEditor`, `PluginSetSelector`, and `TemplateListEditor`.
- Enhanced the `usePluginI18n` utility to resolve plugin-specific translations based on the current locale.
- Modified the `common` store to include an `i18n` field for plugin metadata.
- Updated documentation to include guidelines for plugin internationalization.
- Added tests to ensure proper loading of localization files and integration with plugin metadata.

* perf: code quality

* feat: update config path handling for internationalization support
2026-04-30 23:40:25 +08:00
LIghtJUNction
433836d972 fix: guard against None system_prompt in _ensure_persona_and_skills (#7880)
* fix: guard against None system_prompt in _ensure_persona_and_skills

ProviderRequest.system_prompt defaults to None. When a persona with a
prompt is configured, _ensure_persona_and_skills calls
``req.system_prompt += ...`` which crashes with ``TypeError`` when
system_prompt is None.

Added a None guard before the persona prompt injection and skills prompt
appending sections so they always operate on a string.

* chore: delete tests/unit/test_system_prompt_none_bug.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-04-30 23:12:31 +08:00
Weilong Liao
d72cb78f37 feat: re-implement plugin pinning functionality for extensions (#7918)
* feat: re-implement plugin pinning functionality for extensions

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

* chore: update subset

---------

Co-authored-by: Copilot <copilot@github.com>
2026-04-30 22:17:52 +08:00
Weilong Liao
34dc91e4b0 perf: improve ui and supports edit skills file in webui (#7903)
* feat: update ExtensionCard variant to outlined and adjust InstalledPluginsTab layout for better responsiveness

* feat: update MCP servers management UI and add descriptions for better clarity

* feat: enhance OutlinedActionListItem component with clickable functionality and new slots

feat(i18n): update English, Russian, and Chinese translations for extension and knowledge base features

fix: improve DocumentDetail and KBDetail views with outlined card styles and remove unnecessary dividers

refactor: streamline KBList component to use OutlinedActionListItem for better UI consistency

style: adjust styles for knowledge base components and improve responsive design

test: add security tests for skill file browser and editor to prevent path traversal and file size issues

* feat: update UI components and styles for improved layout and readability
2026-04-30 22:11:15 +08:00
bugkeep
938c241799 fix: align OpenAI http_client with SDK httpx (#7773)
* fix: align OpenAI http_client with SDK httpx

* fix: narrow openai httpx import fallback
2026-04-30 10:53:34 +08:00
千岚之夏
71b6349b6a fix: stop_event() 后续 handler 仍然执行 (#7900)
* fix: check event.is_stopped() after handler execution in star_request.py

* fix: move is_stopped() check before clear_result(), add check in except block and loop start

* fix: remove redundant is_stopped() check after stop_event() in except block

---------

Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>
2026-04-30 09:24:33 +08:00
Weilong Liao
7c185f8e40 feat: add PluginDetailPage component for detailed plugin information display (#7896)
* feat: add PluginDetailPage component for detailed plugin information display

refactor: remove extension preference storage management and related tests

chore: clean up useExtensionPage by removing unused preference storage logic

* feat: add getHandlerDisplayName function for improved handler name display
2026-04-29 22:42:02 +08:00
LIghtJUNction
284700dd60 feat(dashboard): support first-login auto admin setup
When the dashboard password is still the default (not configured),
the user's first login attempt automatically saves their chosen
username and password as the admin credentials, eliminating the
need to pre-set a password via CLI.
2026-04-29 20:28:22 +08:00
wanger
6756a669d7 fix(dashboard): use v-autocomplete for list+options config field (#7884) (#7885)
* fix(dashboard): use v-autocomplete for list+options config field (#7884)

Replace v-select with v-autocomplete in the list+options branch of
ConfigItemRenderer. v-select's keyboard typeahead auto-toggles the
first prefix-matching item in multiple mode, which is unusable for
long option lists (e.g. plugin language pickers). v-autocomplete
filters the dropdown by typed text instead.

Bind v-model:search and clear it in @update:model-value so the search
box resets after each selection, allowing consecutive keyword search.

* perf(dashboard): memoize list config select items via computed

Wrap getSelectItems(itemMeta) in a computed so the options array
is only re-mapped when itemMeta changes, not on every keystroke
in the v-autocomplete search input. Avoids quadratic-ish work for
long option lists

---------

Co-authored-by: wanger <wanger@example.com>
2026-04-29 18:42:52 +08:00
LIghtJUNction
a5141e272a ci(dashboard): add biome lint check to CI workflow
Run `pnpm lint:check` before build to catch format and import issues early.
Biome's noUnusedVariables is disabled for Vue files since biome cannot
detect variables used in <template> blocks.
2026-04-29 17:42:58 +08:00
s11IM
587286a967 fix: warn when default chat provider is unset (#7498)
* fix: warn when default chat provider is unset

* fix: align startup warning with provider fallback

* refactor: simplify default chat provider warning guard checks

* feat: warn when default chat provider id is invalid or missing

 - Emit a warning when `default_provider_id` points to a
 non-existent enabled provider, preventing silent fallback to
 an unexpected model.
 - Reset the warning guard before each
 `provider_manager.initialize()` so configuration reloads
 trigger a fresh re-evaluation.
 - Harden guard checks to handle `None` `provider_settings` and
 `None` provider IDs gracefully.

* test: cover fallback and invalid default provider id warnings

 - Add case for `curr_provider_inst=None` to verify fallback to
 `providers[0]`.
 - Add case for a `default_provider_id` that does not match any enabled
 provider.

* style: format default chat provider warning

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-04-29 11:05:38 +08:00
Ruochen Pan
eb69bf3687 fix(shipyard-neo): add readiness gate and graceful sandbox cleanup (#7881)
* fix(shipyard-neo): add readiness gate and graceful sandbox cleanup

* fix:  Add **kwargs to ComputerBooter.shutdown()

* test(shipyard-neo): add tests for readiness gate and shutdown behavior
2026-04-29 10:26:20 +08:00
LIghtJUNction
6996dbd22d Update .gitignore 2026-04-29 08:49:48 +08:00
LIghtJUNction
3d7dff64b2 test: final coverage batch - utils, pipeline, agent, star tests
- 22 unit test files added/modified across all core modules
- Fix jsonschema ValidationError import in test_tool
- Coverage increased from 23% to ~35% overall
2026-04-29 08:49:01 +08:00
LIghtJUNction
e980151f88 test: utils test expansion - network, command_parser, storage, tempdir, file_extract 2026-04-29 08:44:49 +08:00
LIghtJUNction
8b609a9d83 fix: jsonschema ValidationError import in test_tool 2026-04-29 08:43:53 +08:00
LIghtJUNction
d582a8518c test: dashboard routes unit tests for chat/conversation/open_api 2026-04-29 08:40:45 +08:00
LIghtJUNction
169a856a3a test: mass-coverage push — ~1000+ new unit tests
Coverage improvements:
- agent/tool/core: 150+ tests (FunctionTool, ToolSet, ToolSchema, run_context, messages, registry)
- provider: 152 tests (entities, Provider ABC, register, manager)
- star module: 58 tests (Context, PluginManager, StarHandler)
- platform: 71 tests (Platform ABC, manager, MessageSession)
- pipeline: 130 tests (process/respond stages, scheduler, bootstrap, conversation_mgr)
- kb+skills: 96 tests (mgr, helpers, chunkers, skill_manager)
- config+builtins: 92 tests (astrbot_config, config_mgr, default, LTM, star main)
- cron+db+event_bus: 89 tests (cron events/manager, PO models, BaseDatabase, EventBus)
- dashboard routes: expanded smoke tests for all route modules
2026-04-29 08:40:26 +08:00
LIghtJUNction
daee102c07 test: comprehensive import smoke tests for all dashboard routes
Coverage now includes:
session_management, config, knowledge_base, live_chat, persona,
tools, chat, conversation, open_api, backup, skills, t2i, cron,
plugin, chatui_project, stat, server, auth, subagent, update,
log, command
2026-04-29 08:19:38 +08:00
LIghtJUNction
7a0909a869 test: add regression test for update_conversation clear_persona param 2026-04-29 08:02:19 +08:00
LIghtJUNction
eac42158f9 fix: add missing clear_persona param to SQLiteDatabase.update_conversation 2026-04-29 08:00:56 +08:00
LIghtJUNction
a131d7fc2d fix: add fetchDefaultConfig helper for computer access step 2026-04-29 07:59:50 +08:00
LIghtJUNction
de590c4031 feat: add Computer Use step to onboarding wizard (sync with master) 2026-04-29 07:55:29 +08:00
LIghtJUNction
85a50efeb7 Revert "feat: add Computer Use step to onboarding wizard"
This reverts commit 5e0fece73f.
2026-04-29 07:48:07 +08:00
LIghtJUNction
5e0fece73f feat: add Computer Use step to onboarding wizard 2026-04-29 07:45:29 +08:00
LIghtJUNction
40fb75f870 test: regression test for system_prompt=None + TypeError 2026-04-29 07:30:47 +08:00
LIghtJUNction
1f3f86af8e fix: system_prompt None guard before += in _ensure_persona_and_skills 2026-04-29 07:21:29 +08:00
LIghtJUNction
361f42f27d fix: add exc_info to agent error log for debugging NoneType += str 2026-04-29 07:19:15 +08:00
LIghtJUNction
9f999e401d test: add test for None think content edge case in openai_source 2026-04-29 07:12:39 +08:00
LIghtJUNction
adc31fd9be Fix: NoneType += str error in openai_source.py
- Add guard for reasoning_content before += operation
- Fix MessageList.vue closing tag parsing error
- Fix MessagePartsRenderer.vue v-if multiline attribute
- Fix sensevoice_selfhosted_source.py model type annotation
- Remove unused imports from tencent_record_helper.py
- Fix xinference_rerank_source.py unused import
- Fix chat.py pending_tool_calls type annotation
2026-04-29 07:11:08 +08:00
LIghtJUNction
e875709147 fix: reasoning_content None guard in openai_source think part parsing 2026-04-29 07:10:45 +08:00
LIghtJUNction
c7cfb81756 fix: replace optional chaining/nullish coalescing in Vue templates
Vue template compiler does not support ?. and ?? in v-if expressions.
2026-04-29 06:46:47 +08:00
LIghtJUNction
dcaaf6286a test: comprehensive test coverage and type fixes
- Add 100+ new test files covering provider sources, platform adapters,
  agent runners, star/plugin system, knowledge base, core utils,
  pipeline, computer tools, builtin commands, and dashboard routes
- Fix Python type errors in sqlite.py (col() wrappers for SQLModel),
  astr_agent_tool_exec, core_lifecycle, star context/manager
- Fix TypeScript strict mode errors across 30+ dashboard Vue files
- Add import smoke tests, auth roundtrip, startup tests
- Add compile-all check and CLI entry test for AUR compatibility
- Restore BotMessageAccumulator and helpers lost in merge
2026-04-29 06:29:56 +08:00
LIghtJUNction
a0c9cc8fe3 fix: test_api.py type errors - inline kwargs, fix ParameterSet import, add json=None 2026-04-29 04:38:03 +08:00
LIghtJUNction
d8eb3d3869 fix: dashboard_shutdown_event None safety, missing KnowledgeBaseUploadError import, core_lifecycle imports and type errors 2026-04-29 04:35:06 +08:00
LIghtJUNction
10fa16e0b8 fix: core_lifecycle event_bus cleanup, initialize_core sets dashboard_shutdown_event, load_pipeline_scheduler mock 2026-04-29 04:31:16 +08:00
LIghtJUNction
b4034225b8 test: cover all non-placeholder API routes with parametrized smoke tests 2026-04-29 04:26:58 +08:00
LIghtJUNction
1bc8175f69 fix: make registered_web_apis/_register_tasks instance vars, add reset_runtime_registrations
Class-level list vars caused cross-instance sharing. Tests expecting
isolated registration containers failed. Move to __init__ and add the
reset_runtime_registrations helper that tests depend on.
2026-04-29 04:26:42 +08:00
LIghtJUNction
d6c4c70369 fix: add missing functools and TYPE_CHECKING imports in shipyard.py 2026-04-29 04:24:57 +08:00
LIghtJUNction
d3793ee28c fix: align test_initial_loader with current InitialLoader.start implementation
InitialLoader.start now calls lifecycle.initialize() (not initialize_core).
Updated test mocks and assertions accordingly. 3 tests remain that assume
a split-phase bootstrap_runtime call that no longer exists in the current
InitialLoader.
2026-04-29 04:20:35 +08:00
LIghtJUNction
4480bc20ac fix: test_ensure_vec_db mock path and create kb_dir to avoid SQLite error 2026-04-29 04:18:18 +08:00
LIghtJUNction
585b871492 test: add dashboard API smoke tests for all route classes 2026-04-29 04:16:20 +08:00
LIghtJUNction
afb0f88342 fix: test_cua_config_log logger mock compat with multi-arg info calls 2026-04-29 04:16:13 +08:00
LIghtJUNction
3fb7515e23 fix: LocalShellComponent tests - mock sessions to avoid event loop conflicts
Real bash subprocess via PersistentShellSession binds stdin/stdout to the
creating event loop. pytest-asyncio's per-function loop switching caused
'Future attached to a different loop' errors. Mock the session instead.

Also remove the unused session-level cleanup fixture and patch.
2026-04-29 04:15:02 +08:00
LIghtJUNction
cafe26b154 fix: repair test failures from merge
- test_astr_agent_tool_exec: add get_llm_tool_manager mock to handoff tests
- test_astr_main_agent: fix fullwidth punctuation, Firecrawl->Tavily, streaming
  test, CUA/shipyard sandbox tests, add get_llm_tool_manager mock
- shipyard_neo/browser.py: add @builtin_tool to BrowserExecTool/BatchExecTool/RunBrowserSkillTool
- shipyard_neo/neo_skills.py: add @builtin_tool to all 11 NeoSkillToolBase subclasses
2026-04-29 04:04:08 +08:00
LIghtJUNction
e9a62f7758 test: align imports with PKGBUILD check(), add AUR startup chain tests 2026-04-29 03:47:58 +08:00
LIghtJUNction
71ce6b044a test: add compile-all check and CLI entry point test for AUR compat 2026-04-29 03:45:34 +08:00
LIghtJUNction
846a1ab1a7 test: add main.py syntax check and SQLiteDatabase abstract method check 2026-04-29 03:42:12 +08:00
LIghtJUNction
0c47c27e4b test: add import smoke, auth roundtrip, and startup tests
- test_imports: catch missing symbols and abstract methods
- test_auth: argon2id roundtrip, password validation, login challenge
- test_startup: verify core modules import without crashing
fix: restore BotMessageAccumulator and helpers lost in cherry-pick
2026-04-29 03:39:27 +08:00
LIghtJUNction
1d36f04e1c fix: restore _sanitize_upload_filename function lost in merge
This function was dropped during merge, causing ImportError in
test_upload_filename_sanitization.py and breaking upload handling.
Re-implemented with null-byte removal, path traversal stripping,
fakepath prefix removal, and empty-fallback to UUID.
2026-04-29 03:38:37 +08:00
LIghtJUNction
50b1485f89 fix: add 5 missing SQLiteDatabase method implementations lost in merge
BaseDatabase added 5 new abstract methods (list_sdk_platform_message_history,
delete_platform_message_before, delete_platform_message_after,
delete_all_platform_message_history, find_platform_message_history_by_idempotency_key)
but SQLiteDatabase did not implement them, causing TypeError on startup.

All methods follow the existing codebase patterns using async SQLAlchemy sessions
with the delete/select helpers.
2026-04-29 03:33:35 +08:00
LIghtJUNction
4925397542 fix: restore IME fix, fileTypeStyles, clearStaged fix lost in inline edit merge 2026-04-29 03:14:46 +08:00
LIghtJUNction
e610c49499 fix: port IME enter fix and Firecrawl tool name from master
# Conflicts:
#	dashboard/src/components/chat/ChatInput.vue
2026-04-29 03:10:23 +08:00
LIghtJUNction
716e651d80 feat: add inline message editing and regeneration functionality for webui (#7673)
* feat: add inline message editing and regeneration functionality for webui

- Implemented inline editing for user messages in the chat component.
- Added a regenerate menu for retrying messages with different models.
- Enhanced message handling to include llm_checkpoint_id for better tracking.
- Updated localization files to include new actions for retrying and model selection.
- Introduced tests for checkpoint message handling and chat route functionality.

* feat: thread mode in webui

* feat: enhance message editing functionality to allow only the latest user message to be edited

* feat: add error handling and user feedback for thread creation in chat component

* feat: add thread count display and localization support in chat component

* feat: add RefsSidebar component and integrate reference management in chat UI

* feat: improve message editing validation and cleanup for bot messages

* feat: enhance checkpoint message handling with binding and dumping functionality
# Conflicts:
#	astrbot/core/agent/message.py
#	astrbot/core/agent/runners/tool_loop_agent_runner.py
#	astrbot/core/astr_main_agent.py
#	astrbot/core/db/sqlite.py
#	astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py
#	astrbot/core/platform/sources/webchat/webchat_adapter.py
#	astrbot/dashboard/routes/chat.py
#	astrbot/dashboard/routes/live_chat.py
#	dashboard/src/components/chat/Chat.vue
#	dashboard/src/components/chat/ChatInput.vue
#	dashboard/src/components/chat/ChatMessageList.vue
#	dashboard/src/components/chat/ProviderModelMenu.vue
#	dashboard/src/components/shared/StyledMenu.vue
#	dashboard/src/composables/useMessages.ts
#	dashboard/src/i18n/locales/ru-RU/features/chat.json
2026-04-29 03:10:03 +08:00
LIghtJUNction
d57582e599 fix: restore merge-dropped port/ip_addr variable definitions and payload type ignore 2026-04-29 03:06:56 +08:00
LIghtJUNction
7c4a061578 feat: port attachment handling improvements from master
- clearStaged({ revokeUrls: false }) to preserve blob URLs during send
- File type icon helpers (fileTypeStyles, fileExtension, filePresentation)
- CSS transitions for input container and textarea
- File dedup via SHA-256 signature in useMediaHandling
2026-04-29 03:05:09 +08:00
LIghtJUNction
946685d786 fix: re-export BACKGROUND_TASK_WOKE_USER_PROMPT and CONVERSATION_HISTORY_INJECT_PREFIX from astr_main_agent_resources 2026-04-29 03:00:24 +08:00
LIghtJUNction
2c3bceb2e6 feat: add file dedup and signature check from master attachment handling 2026-04-29 03:00:13 +08:00
LIghtJUNction
9bc8731f83 fix: add Firecrawl API key and CUA image config from master 2026-04-29 02:47:51 +08:00
LIghtJUNction
c059d60f57 fix: port IME enter fix and Firecrawl tool name from master 2026-04-29 02:41:13 +08:00
LIghtJUNction
1acefcd8c7 fix: restore dashboard to pre-merge version (broken by -X theirs merge) 2026-04-29 02:32:05 +08:00
LIghtJUNction
497fefb3ca fix: restore missing sentinel classes and import lost in merge 2026-04-29 02:27:46 +08:00
LIghtJUNction
f5d60f3c7f fix: restore persistent shell session lost in merge, upgrade axios to 1.15.0 2026-04-29 02:18:08 +08:00
LIghtJUNction
0208dbb15f Merge branch 'master' of https://github.com/AstrBotDevs/AstrBot into dev
# Conflicts:
#	dashboard/vite.config.ts
2026-04-29 02:16:18 +08:00
LIghtJUNction
63e1988f86 chore: merge CLAUDE.md into AGENTS.md and remove CLAUDE.md 2026-04-29 02:15:06 +08:00
LIghtJUNction
5f827fffd2 feat: persistent shell session and remove dead ToolSessionManager
- Replace LocalShellComponent's one-shot subprocess.run() with a
  PersistentShellSession that wraps a long-running bash process per UMO.
  cd/export/source now persist naturally within a conversation.
- Support background task execution via nohup.
- Remove unused ToolSessionManager / ToolSessionState (dead code,
  never wired to any consumer).
- Fix performance benchmark: separate throughput and memory measurement
  so tracemalloc doesn't distort timing (was 7x slower).
- Optimize bool validation in CommandFilter with frozenset + isinstance
  short-circuit.
2026-04-29 02:06:24 +08:00
LIghtJUNction
4463895c89 chore: improve code quality score from 55 to 81
- Convert bad type: ignore[...] to blanket ignores
- Remove unused type: ignore directives
- Fix genie_tts/dashscope_tts Any type annotations
- Remove temp file
2026-04-29 01:28:20 +08:00
Soulter
6b36e1abac fix: comment out tool_choice parameter in ToolLoopAgentRunner for debugging
fixes: #7853
closes: #7856
closes: #7862
2026-04-29 00:20:38 +08:00
Weilong Liao
8f356b84c7 fix(core): restrict send_message_to_user to current session (security fix #7822) (#7824)
* fix(core): security fix - restrict send_message_to_user to current session only

Closes #7822

SECURITY: Remove the user-controlled 'session' parameter from the
send_message_to_user tool. Previously, a regular user could ask the
LLM to send messages to any arbitrary session (group chat) by
providing a crafted session string, which is a high-risk
vulnerability.

Changes:
- Remove 'session' parameter from tool schema (LLM can no longer
  propose it)
- Always use context.context.event.unified_msg_origin as the target
  session
- Update description to clearly state that messages can only be sent
  to the current user's session

* fix: restore session param but restrict to admin only

- Re-add the  parameter removed in the original PR
- Non-admin users can only send to their own session (current_session)
- Admin users can send to any session via the  param
- Uses  from computer_tools.util (same pattern as fs.py)
- Ref: https://github.com/AstrBotDevs/AstrBot/issues/7822

Co-authored-by: Soulter <soulter@astrbot.app>

* Update message_tools.py

---------

Co-authored-by: AstrBot <bot@astrbot.app>
2026-04-29 00:15:16 +08:00
诗浓
98b05b7e89 fix(provider): persist model enable toggle (#7865)
* fix(provider): persist model enable toggle

Fixes AstrBotDevs/AstrBot#7863

* fix(provider): wait for model toggle refresh
2026-04-28 23:55:46 +08:00
Soulter
962c299c2d feat(shell): enhance exec method to support timeout parameter and improve background command handling 2026-04-28 23:55:29 +08:00
daniel5u
66d620dab5 fix: merge anthropic parallel tool results (#7875) 2026-04-28 23:48:09 +08:00
Weilong Liao
ac7f6aa60d feat(shell): add background command execution with output redirection and timeout support (#7835)
* feat(shell): add background command execution with output redirection and timeout support

* feat(shell): update timeout parameter to be optional in shell execution methods

* feat(shell): set default timeout for shell execution to 10,000,000 milliseconds

* feat(shell): set default timeout to 300s for shell execution

* feat(shell): reorder timeout parameter in ExecuteShellTool configuration

* feat(shell): implement background command execution with detached shell command support

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

* test(shell): remove obsolete test for background shell command output redirection

* fix: reorder import statements in shell.py for consistency

* fix: wrap command in parentheses for background output redirection

---------

Co-authored-by: Copilot <copilot@github.com>
2026-04-28 23:25:54 +08:00
エイカク
2f33c34b5c fix: protect desktop plugin installs with core lock (#7872) 2026-04-28 21:10:19 +09:00
Weilong Liao
d8de0035a9 feat: add attachment saved event handling in chat and live chat routes (#7869)
Co-authored-by: Zhilan615 <2864095951@qq.com>
2026-04-28 17:14:40 +08:00
Soulter
1801834cac fix: remove BOM from install.ps1 file 2026-04-28 15:34:33 +08:00
Soulter
4d9340c216 feat: add deploy scripts for Windows and Linux installation, remove copy-deploy-cli script 2026-04-28 15:05:35 +08:00
dependabot[bot]
9016a3b2c4 chore(deps): bump pnpm/action-setup in the github-actions group (#7857)
Bumps the github-actions group with 1 update: [pnpm/action-setup](https://github.com/pnpm/action-setup).


Updates `pnpm/action-setup` from 5.0.0 to 6.0.3
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v5.0.0...v6.0.3)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-28 14:57:31 +08:00
Soulter
e4a9274b41 fix: update .gitignore and copy-deploy-cli script paths for public directory 2026-04-28 14:56:44 +08:00
EterUltimate
e218620a37 feat: add one-line deploy script (deploy-cli.sh) (#7631)
* feat: add one-line deploy script (deploy-cli.sh) and update cli.md

- Add docs/scripts/deploy-cli.sh for one-command deployment (Linux/macOS/WSL)
- Update docs/zh/deploy/astrbot/cli.md to reference local script
- Replace non-existent https://astrbot.app/deploy.sh with raw.githubusercontent.com URL
- Add local run tip and WSL-based Windows support

* fix: address PR review feedback for deploy-cli.sh

- Replace sort -V with Python-native version check (macOS BSD compat)
- Bump Python requirement from >=3.10 to >=3.12 (match pyproject.toml)
- Detect current directory as project root (avoid nested clone)
- Handle existing non-git directory explicitly
- Add curl dependency check
- Support ASTRBOT_REPO and ASTRBOT_DIR env vars for forks/mirrors
- Update cli.md version description to match

* feat: add Windows PowerShell deploy script and update docs

- Add deploy-cli.ps1 for Windows native environment (PowerShell 7+)
- Update cli.md to document Windows one-liner deployment
- Add local script execution instructions for both bash and ps1

* refactor: standardize log messages and improve clarity in various modules

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

* docs: 移除一行命令快速部署部分,简化安装说明

* feat: 添加脚本以复制部署 CLI 文件并更新构建命令

* refactor: 更新日志消息以提高可读性,统一英文提示信息

---------

Co-authored-by: Soulter <905617992@qq.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-04-28 14:49:50 +08:00
エイカク
cb5c172e69 feat: add CUA computer-use sandbox support (#7828)
* feat: add CUA computer-use sandbox support

* fix: add CUA config metadata translations

* fix: address CUA sandbox review feedback

* fix: default CUA sandbox to local mode

* fix: harden CUA SDK method compatibility

* fix: harden CUA GUI and permission handling

* fix: refine CUA capability and shell handling

* fix: avoid inline CUA screenshot image results by default

* fix: guide CUA browser startup workflow

* feat: add CUA browser and key press tools

* fix: launch CUA browser as sandbox user

* fix: stabilize CUA browser screenshots

* fix: simplify CUA browser launch command

* fix: remove CUA open browser tool

* fix: align CUA desktop control guidance

* fix: harden CUA shell background handling

* fix: harden CUA runtime adapters

* fix: surface CUA filesystem failures

* fix: clarify CUA shell fallback support

* fix: harden CUA shell helpers

* fix: guard CUA file fallbacks

* fix: redact sensitive config log paths

* fix: guard CUA download fallback

* test: cover CUA GUI and shell env wiring

* fix: preserve CUA command result output

* fix: normalize CUA return codes

* fix: preserve foreground shell behavior

* fix: clean up failed CUA boots

* docs: add CUA sandbox runtime guide

* test: cover CUA GUI tool registration

* refactor: simplify CUA fallback handling

* refactor: simplify CUA shell helpers

* test: cover CUA screenshot result shapes
2026-04-28 01:40:14 +09:00
エイカク
67c7445d25 fix: prevent IME enter from sending chat (#7845)
* fix: prevent IME enter from sending chat

* fix: prevent IME enter from sending chat

* refactor: clarify IME composition state handling
2026-04-27 22:56:24 +09:00
Weilong Liao
72d65680b8 docs: add pre-commit setup guide to AGENTS.md (#7838)
* fix(dashboard): add tooltip for truncated command/tool descriptions in WebUI

- CommandTable.vue: add :title binding to description div
- ToolTable.vue: add :title binding to description and origin_name divs

Fixes #7583 - Webui中超出显示长度的指令描述无法以任何方式看到

* docs: add pre-commit setup guide to AGENTS.md

Extract the pre-commit and ruff setup instructions from README.md
into AGENTS.md so AI agents have a complete reference for
setting up the development environment.

---------

Co-authored-by: AstrBot Fixer <astrbot@fix-bot.local>
Co-authored-by: AstrBot Fixer <astrbot-fixer@users.noreply.github.com>
2026-04-27 21:42:56 +08:00
時壹
b711425b73 feat: add message-level markdown control for QQ Official platform (#6980)
* feat: add message-level markdown control for QQ Official platform

* feat: propagate MessageChain metadata through RespondStage chain splitting
2026-04-27 21:21:56 +08:00
若月千鸮
72f4e748e8 fix: restore T2I text template rendering (#7789)
* fix: restore T2I text template rendering

- keep using {{ text | safe }} instead of text_base64
- inject Shiki runtime by default for T2I templates
- update built-in templates to read markdown from a hidden textarea
- improve WebUI preview sample text and Shiki runtime serving
- add regression tests for template rendering and runtime injection

* fix: prevent injected Shiki runtime from breaking T2I templates

* fix(t2i): restore raw text template rendering

* test(t2i): remove test

* fix(t2i): restore previewText
2026-04-27 15:38:43 +08:00
Soulter
09ab45fcb5 chore: bump version to 4.23.6 2026-04-27 13:05:20 +08:00
Weilong Liao
1efe4fd60e fix(stats): TPM now only counts output tokens (#7827)
* fix(stats): TPM now only counts output tokens

- Add range_total_output_tokens accumulation, separate from total tokens
- Change range_avg_tpm formula to use output tokens only
- Update i18n labels to reflect Output TPM

* fix(stats): range
2026-04-27 12:59:44 +08:00
Weilong Liao
c5ab4f7263 feat: add /stats command to view conversation token usage (#7831)
* feat: add /stats command to view conversation token usage

- Add stats() method to ConversationCommands that queries ProviderStat
  records by conversation_id and aggregates token breakdowns
- Register /stats command in main.py

* feat: reorder conversation stats output for better readability

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

* feat: reorder token usage output for improved clarity

* feat: enhance stats command to aggregate conversation token usage

* feat: add cached input tokens display and update translations for clarity

* feat: update stats command to clarify conversation token usage display

---------

Co-authored-by: Copilot <copilot@github.com>
2026-04-27 12:59:21 +08:00
Weilong Liao
415da218f6 fix: update reasoning_content handling to support empty string values (#7830)
* fix: update reasoning_content handling to support empty string values

* fix: add reasoning_content field for DeepSeek v4 models in assistant messages
2026-04-27 11:47:32 +08:00
Weilong Liao
07b37b98de fix: handle empty reasoning content for DeepSeek v4 models (#7823)
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 02:19:40 +08:00
bugkeep
bbda1e678f fix(core): downscale oversized images (#7807)
* fix(core): downscale oversized images

* refactor: share image max-size check helper

* Delete tests/unit/test_media_utils_compress_image.py

---------

Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
2026-04-26 23:10:58 +08:00
EnemyWind
3c1d0cd2c2 [fix] 将Minimax TTS默认输出格式改为wav以解决RIFF错误 (#7797)
## 问题
在 QQ 官方平台插件中,处理来自 Minimax TTS 的语音时,会抛出错误:`处理语音时出错: file does not start with RIFF id`。
## 原因
Minimax TTS 提供商 (`minimax_tts_api_source.py`) 默认配置的音频输出格式为 `mp3`,而 `qqofficial_message_event.py` 中的 `wav_to_tencent_silk` 函数要求输入为 WAV 格式(具有 RIFF 文件头)。
## 解决方案
将 `minimax_tts_api_source.py` 文件中 `ProviderMiniMaxTTSAPI` 类的 `audio_setting` 字典的 `format` 键值,从 `"mp3"` 修改为 `"wav"`。
## 结果
修改后,Minimax TTS 生成的音频文件将直接为 WAV 格式,从而被下游函数正确识别和处理,修复上述错误。
2026-04-26 23:06:54 +08:00
Weilong Liao
d16ed4e552 fix: revise reasoning_key attribute to OpenRouter (#7821) 2026-04-26 22:21:57 +08:00
Yufeng He
55c1558686 fix(openai): apply empty-assistant filter to streaming path (fixes #7721) (#7758)
PR #7202 added empty-assistant filtering in `_query` so strict
providers (Moonshot, etc.) wouldn't 400 on history with blank
assistant entries. The streaming sibling `_query_stream` was
never updated, so DeepSeek Reasoner — which returns reasoning only
during tool calls, leaving serialized content as `""` — blew up with
`Invalid assistant message: content or tool_calls must be set` on
the next turn.

Hoisted the filter into a `_sanitize_assistant_messages` helper and
called it from both paths. Also widened the empty check to cover
`content == []`, which the original filter missed and which shows up
with providers that emit content as a list of parts.
2026-04-26 13:10:47 +08:00
wjiajian
17aea1aa2c feat: add Firecrawl web search tools (#7764)
* feat: add Firecrawl web search and extract tools, update configuration and tests

* feat: implement Firecrawl API integration and error handling in web search tools

* feat: enhance Firecrawl web search with session management and payload validation

* feat:  Firecrawl web search to use aiohttp.ClientSession directly for improved session management as it was

* feat: update Firecrawl search to handle grouped web data response and add corresponding tests

* feat: refactor Firecrawl web search to use aiohttp.ClientSession for improved error handling and session management

* feat: remove unused coercion function and update Firecrawl search to use default limit in payload
2026-04-26 13:07:27 +08:00
Rhonin Wang
d4cdeeae72 fix(computer): send sandbox image downloads as images (#7785) 2026-04-25 16:44:08 +08:00
lingyun14
5ce02da6df fix: use certifi ssl context on Windows (#7778)
* fix: use certifi ssl context on Windows

* docs: update docstring to reflect hybrid SSL context

* chore: ruff

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-25 16:34:50 +08:00
Soulter
5d79c99938 feat: add deduplication for WeChat kefu text messages within 15 seconds (#7788) 2026-04-25 16:26:30 +08:00
Soulter
f0a1dd79c4 perf: improve provider config ui (#7772)
* stage

* style: update font families and improve responsive design across components
2026-04-24 20:46:45 +08:00
alonguser
8d9ae55c8f fix: extract shared clipboard utility and fix copy actions in dialogs and insecure contexts (#7747)
* fix: 在非安全上下文中为 copyMessage 添加 execCommand 备用方案

在非安全上下文中(例如通过 HTTP 局域网 IP 访问),navigator.clipboard 不可用。为此,我们添加了使用 document.execCommand(‘copy’) 的备用方案,这与 ReadmeDialog.vue 和 Settings.vue 中的现有实现保持一致。

* fix: extract shared clipboard utility and fix copy actions in dialogs and insecure contexts

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-04-24 10:44:20 +08:00
bugkeep
aaec41e505 fix: prevent path traversal in file uploads (#7751)
* fix: prevent path traversal in uploads

* fix: remove embedded NUL bytes from upload filenames

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-04-24 09:01:02 +08:00
Soulter
9f8ce24726 chore: bump version to 4.23.5 2026-04-23 22:28:40 +08:00
Soulter
8eefda4611 chore: bump version to 4.23.4 2026-04-23 21:30:03 +08:00
SJ
489e2a33c8 fix(platform): clarify shared appid hint text (#7746)
Co-authored-by: idiotsj <idiotsj@users.noreply.github.com>
2026-04-23 21:00:11 +08:00
Soulter
bb6619f38c perf: improve tool calls in reasoning and multiple tool calls display (#7742)
* perf: improve tool calls in reasoning and multiple tool calls display

- Updated LiveChatRoute and OpenApiRoute to replace manual message accumulation with BotMessageAccumulator.
- Simplified message saving logic by using build_bot_history_content and collect_plain_text_from_message_parts.
- Enhanced message processing to handle various message types (plain, image, record, file, video) more efficiently.
- Improved reasoning handling by extracting thinking parts and displaying them correctly in the UI components.
- Refactored message normalization and reasoning extraction logic in useMessages composable for better clarity and maintainability.
- Updated ChatMessageList, MessageList, StandaloneChat, and ReasoningBlock components to accommodate new message structure and rendering logic.

* feat(chat): reasoning activity panel

- Introduced a new ReasoningSidebar component for displaying reasoning details.
- Refactored MessageList and StandaloneChat components to utilize renderBlocks for improved message part handling.
- Added ReasoningTimeline component to visualize reasoning steps.
- Updated message handling logic to differentiate between thinking and content blocks.
- Enhanced localization for reasoning-related terms in English, Russian, and Chinese.
- Improved styling for various components to ensure consistency and readability.

* Update astrbot/dashboard/routes/chat.py

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>
2026-04-23 17:46:53 +08:00
Soulter
2f479b5204 fix: add missing platform adapter filter types (#7738) 2026-04-23 13:42:45 +08:00
Soulter
56435b5c17 chore: delete video-fix.patch 2026-04-23 13:03:52 +08:00
Soulter
c1cd5627bb chore: bump version to 4.23.3 2026-04-23 12:00:10 +08:00
LIghtJUNction
1b76af4217 test: improve storage_cleaner tests (constants, helpers, clearer assertions) 2026-04-23 04:42:27 +08:00
LIghtJUNction
2ecd95b9e9 chore: ruff check && format 2026-04-23 04:29:07 +08:00
LIghtJUNction
5e32fdf58f Update context.py 2026-04-23 04:20:30 +08:00
LIghtJUNction
60738b44ee Update internal.py 2026-04-23 04:18:52 +08:00
LIghtJUNction
c4048bb8eb refactor: delete _internal
remove deprecated API modules and example scripts; update core modules
(agents, providers, tools, platform adapters, utils), dashboard package
and components, and unit tests.
2026-04-23 04:16:30 +08:00
LIghtJUNction
33ec7bbf9c merge: master -> dev 2026-04-23 01:12:06 +08:00
千岚之夏
9bad7b2951 fix: missing replies when reasoning content is present by always emitting reasoning messages alongside normal completion outputs (#7715)
* fix: handle reasoning_content when completion_text is empty (kimi-for-coding thinking mode)

* fix: use elif for result_chain/completion_text to avoid duplication, keep reasoning_content independent per review feedback

---------

Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>
2026-04-22 13:22:48 +08:00
Soulter
0748f0a42f feat: enhance attachment handling with previews and file signature checks 2026-04-22 13:18:08 +08:00
千岚之夏
00ebebb176 fix: add retry on DNS/connection transient errors for QQ Official API (#7718)
* fix: add ConnectionError and OSError to retry decorator for QQ Official API

* fix: remove redundant ConnectionError and add asyncio.TimeoutError per review feedback

* fix: rename decorator back to _qqofficial_retry

---------

Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>
2026-04-22 11:52:04 +08:00
Soulter
36d6f3b67e feat: add inline message editing and regeneration functionality for webui (#7673)
* feat: add inline message editing and regeneration functionality for webui

- Implemented inline editing for user messages in the chat component.
- Added a regenerate menu for retrying messages with different models.
- Enhanced message handling to include llm_checkpoint_id for better tracking.
- Updated localization files to include new actions for retrying and model selection.
- Introduced tests for checkpoint message handling and chat route functionality.

* feat: thread mode in webui

* feat: enhance message editing functionality to allow only the latest user message to be edited

* feat: add error handling and user feedback for thread creation in chat component

* feat: add thread count display and localization support in chat component

* feat: add RefsSidebar component and integrate reference management in chat UI

* feat: improve message editing validation and cleanup for bot messages

* feat: enhance checkpoint message handling with binding and dumping functionality
2026-04-22 11:51:12 +08:00
Soulter
e6b68e9b09 perf: update FileReadTool description to mention image, PDF and docx support, and enhance modality checking in tool result case (#7506)
* feat: update FileReadTool description to mention image and PDF support

Add explicit mention of image (OCR) and PDF (text extraction) support
to the FileReadTool description for better discoverability.

* feat: update FileReadTool description to include support for docx and epub files; change base64 decoding to utf-8

* feat: enhance ToolLoopAgentRunner to support image and audio modalities; add context sanitization logic
2026-04-22 11:38:40 +08:00
ShadowLemoon
662b1d3678 fix: accept both str and re.Pattern in RegexFilter (#7633)
* fix: accept both str and re.Pattern in RegexFilter

RegexFilter.__init__ now handles compiled re.Pattern objects by
extracting .pattern for regex_str, preventing TypeError during
JSON serialization in the dashboard plugin API.

* perf: 精简代码
2026-04-21 23:34:22 +08:00
SaintaToken
17ace9b5db feat: add buffered intermediate messages for non-streaming agent loop (#7627)
* feat: add buffered intermediate messages for non-streaming agent loop

* Refactored buffering logic into helpers to reduce inline complexity.

* feat: add buffer_intermediate_messages configuration for merging Agent intermediate messages

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-21 23:32:00 +08:00
Sebastion
7778d8bb63 fix: prevent path traversal in backup importer (CWE-22) (#7681)
* fix: prevent path traversal in backup importer (CWE-22)

Validate that all file write targets resolve within their expected
base directories before writing. This prevents crafted backup ZIP
files from writing to arbitrary filesystem locations via malicious
path values in attachment records, media file paths, or directory
entries.

* fix: use Path.is_relative_to for robust path containment check

* fix: add explicit strict=False to Path.resolve() calls

* style: format backup importer

---------

Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-04-21 22:52:34 +08:00
Rain-0x01_
6b756f666f docs: Unify documentation links (#7709)
astrbot.app -> docs.astrbot.app
2026-04-21 22:42:27 +08:00
Soulter
03bbf0bf5a feat: re-establishing /provider as a built-in command (#7691)
* feat: re-establishing /provider as a built-in command

* style: format provider command

---------

Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-04-21 22:41:31 +08:00
C₂₂H₂₅NO₆
d9ab35348e fix: drop legacy documents_fts table if exists (#7706)
* fix: recover FTS5 index from legacy documents_fts table

* fix: normalize SQL whitespace when checking contentless_delete
2026-04-21 22:27:40 +08:00
hjdhnx
08392c9184 fix: 修复了国内配置一些模型不可用问题 (#7685)
* fix: 修复了国内配置一些模型不可用问题

1. 常见的openai和anthropic协议,如 智谱的codingpan
https://open.bigmodel.cn/api/coding/paas/v4
2. 新出的一些没有模型列表的自定义模型提供商,如科大讯飞
https://maas-coding-api.cn-huabei-1.xf-yun.com/v2

* feat: 提高代码复用性

* fix(network): reuse shared SSL context

* test(network): cover proxy and header forwarding

* fix(network): support verify overrides

---------

Co-authored-by: Taois <taoist.han@vertechs.com>
Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-04-21 11:31:26 +09:00
千岚之夏
406bb6c1a7 fix: warn instead of blocking when configured model not in hardcoded list (#7692)
* fix: change highspeed model block to warning instead of ValueError

* fix: add highspeed models + use astrbot logger (per AI review)

* style: fix ruff format (line-length, import grouping)
2026-04-21 09:24:18 +09:00
千岚之夏
fb16e12c80 feat: 插件有新版本时置顶显示(可开关) (#7665)
* feat: add pinUpdatesOnTop option to always show plugin updates at top

* fix: add missing pinUpdatesOnTop destructuring in InstalledPluginsTab

* fix: address AI review suggestions - add localStorage persistence and increase switch width

* fix: harden extension preference storage

* fix: refine extension preference sorting

* fix: simplify extension preference sorting

* refactor: simplify extension preference storage access

---------

Co-authored-by: Test User <test@test.com>
Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-04-21 09:21:07 +09:00
Aster
76ee4f27dd feat: add epub support for knowledge base document upload (#7594)
* feat: add EPUB parsing support for knowledge base and file reader

* feat: update supported file formats for document upload in knowledge base

* feat: enhance EPUB parser to support spine order and generic containers

* makeitdown parse epub

* update parser

* fix
2026-04-20 15:24:07 +08:00
Stable Genius
43989471e1 fix: normalize invalid MCP required flags in MCP schemas (#6077)
* fix: normalize invalid MCP required flags

* style: format mcp schema normalization tests

* style: sort mcp client imports

* fix: preserve nested mcp required flags

* test: cover malformed mcp required fields

---------

Co-authored-by: Stable Genius <259448942+stablegenius49@users.noreply.github.com>
Co-authored-by: エイカク <1259085392z@gmail.com>
Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-04-20 13:30:04 +09:00
xunxiing
ba1e222356 fix: handle video attachment for llm (#7679)
* fix: handle video attachment for llm

* fix: harden llm video attachment handling

---------

Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-04-20 13:17:41 +09:00
Soulter
00689604b4 chore: bump version to 4.23.2 2026-04-19 17:50:03 +08:00
QAQneko
960bc21c53 fix: resolve EmptyModelOutputError and enhance tool fallback robustness (#7375)
Improve robustness of tool call handling in OpenAI completions and agent tool loop by avoiding premature filtering and surfacing clearer errors when tools are missing.

* Refactor tool call argument handling in openai_source.py

* Improve error logging for missing tools

Log available tools when a specified tool is not found.
2026-04-19 17:12:12 +08:00
shuiping233
1199b704a8 feat: implements support for KOOK role mentions (#7626)
* feat: 实现kook适配器响应`@`角色(role)的能力

* refactor: kook适配器处理role时,`At`组件保留`@`角色的名称而不是id

* fix: kook适配器处理role时,role_id的判断问题

* refactor: 移除kook适配器中的一个# type: ignore

* fix: 修复kook适配器 role mention转换成`At`组件时保留不是角色名称的bug;

* unittest: 给kook适配器添加带有role mention的事件消息的单测,并添加消息组件转换判断单测

* unittest: 部分重构test_kook_event.py和test_kook_types.py 单测

* unittest: 添加kook适配器的 `user/me` `user/view` 接口响应数据验证单测

* fix: 修复kook适配器接收频道权限更新消息会报错的bug

* fix:  不额外处理kook的道具消息

* fix: 使用async with self._http_client.get

* refactor: kook适配器转换文本内容为消息组件时,只strip mention之间的空格

* fix: 修复 role_mention_counter 计数不正确的问题

* fix: 修复kook适配器发送卡片失败的问题;区分两类kook 数据类的to_dict to_json行为

* chore: 添加注释

* refactor: 重构kook适配器的角色缓存功能,使其无锁,性能更好且具备良好的重试机制

* refactor: kook适配器的channel_id 改为 guild_id

* feat: kook适配器响应频道角色更新事件时不再清空整个角色id缓存,而是只清理特定频道的角色id缓存

* unittest: 添加kook适配器的update_role事件的数据类验证单测

* refactor: 补上了一些打印的日志消息文本

refactor: 补上了一些打印的日志消息文本

refactor: 补上了一些打印的日志消息文本

* refactor: 修复kook适配器潜在可能的类型问题

* refactor: `clean_roles_cache`重命名为`clear_guild_roles_cache`
2026-04-19 14:18:16 +08:00
千岚之夏
b40bcbbd86 fix: resolve relative file paths within a local workspace root for the SendMessageToUserTool (#7668)
* fix: resolve relative file paths against workspace directory

* fix: add path normalization and security check for workspace resolution

* chore: remove temp PR body file

* chore: added some comments

Added comments to clarify path resolution logic.

* Update astrbot/core/tools/message_tools.py

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

---------

Co-authored-by: Test User <test@test.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-19 14:09:02 +08:00
Soulter
fd2ca702d7 fix: remove default value for injected isDark in ThemeAwareMarkdownCodeBlock 2026-04-19 13:19:08 +08:00
MagicSun7940
b2a95713f8 修复了使用 Bocha 搜索时报错 "Can not decode content-encoding: br"的bug (#7655)
* 修复了使用 Bocha 搜索时报错 "Can not decode content-encoding: br"的bug

* 添加了注释,解释为什么要限制 Accept-Encoding,方便以后的维护者理解这是针对 aiohttp brotli bug 的临时规避方案。
2026-04-19 13:04:20 +08:00
Strands
fbe9a38c42 fix(dashboard): propagate dark mode to code blocks inside list items (#7667) 2026-04-19 13:01:33 +08:00
LIghtJUNction
6d494283f6 Merge remote-tracking branch 'origin' into dev
# Conflicts:
#	astrbot/core/db/vec_db/faiss_impl/document_storage.py
#	astrbot/core/platform/sources/telegram/tg_adapter.py
#	astrbot/core/platform/sources/weixin_oc/weixin_oc_adapter.py
#	astrbot/core/tools/cron_tools.py
#	astrbot/core/updator.py
#	astrbot/core/zip_updator.py
#	dashboard/src/components/shared/ConfigItemRenderer.vue
#	dashboard/src/utils/providerUtils.js
2026-04-19 05:42:39 +08:00
bobo-xxx
29a449f90d fix: handle rate_limit_count=0 to prevent IndexError (#7635)
* fix: handle rate_limit_count=0 to prevent IndexError

* Update astrbot/core/pipeline/rate_limit_check/stage.py

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

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-18 20:37:36 +08:00
Yufeng He
e98eb92b5f fix: prevent Telegram media group exceptions from being silently swallowed (#7537)
* fix: prevent Telegram media group exceptions from being silently swallowed

process_media_group() is invoked by APScheduler via add_job(). If
convert_message() or handle_msg() raises (e.g. get_file() network
timeout, file download failure), APScheduler catches the exception
internally and only logs it through its own logger, which is often
not configured in AstrBot. The result is that the media group
silently disappears with no trace in the application logs.

Two changes:
- Wrap the body of process_media_group() in try/except so failures
  are logged through AstrBot's own logger with full traceback.
- Register an EVENT_JOB_ERROR listener on the scheduler as a
  safety net, so any future scheduled job that throws will also
  surface in the logs.

Fixes #7512

* ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-18 20:31:33 +08:00
Soulter
352455197d feat: implement FTS5 support in knowledge base sparse retrieving stage (#7648)
* feat: implement FTS5 support in DocumentStorage and SparseRetriever with tokenizer enhancements

* feat: optimize FTS row handling in DocumentStorage and update query tokenization in SparseRetriever
2026-04-18 19:57:27 +08:00
時壹
47f78be378 fix: display cron last_run_at in local timezone (#7625) 2026-04-17 18:36:47 +08:00
SaintaToken
a1a7de1c57 fix: correct minor text inconsistencies in README files and document (#7602)
* fix: correct minor text inconsistencies in README files and documentation

* Update README_zh.md

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

* feat: add buffered intermediate messages for non-streaming agent loop

* Revert "feat: add buffered intermediate messages for non-streaming agent loop"

This reverts commit 803762c99a.

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-17 17:20:13 +08:00
千岚之夏
0ca6ba91b1 feat: add MiniMax Token Plan provider with hardcoded model list (#7609)
* feat: add MiniMax Token Plan provider with hardcoded model list (fix #7585)

- Add new provider 'minimax_token_plan' for MiniMax Token Plan users
- Inherit ProviderAnthropic to reuse all chat/completion logic
- Hardcode api_base to https://api.minimaxi.com/anthropic
- get_models() returns hardcoded list: MiniMax-M2.7, M2.5, M2.1, M2
- Highspeed models excluded (require premium tier)
- Reason for hardcoding: Token Plan API does not expose /models endpoint
- Fixes: https://github.com/AstrBotDevs/AstrBot/issues/7585

* fix: remove api_base from config template and add model validation

- Remove api_base from default_config_tmpl (always overridden, misleading)
- Add model validation against MINIMAX_TOKEN_PLAN_MODELS
- Raise clear ValueError if user configures an unsupported model

Addressed Sourcery AI review comments.

* fix: use custom_headers for Bearer token auth instead of auth_header

MiniMax Token Plan requires Authorization: Bearer <token> header.
Use custom_headers to inject the correct auth header instead of
the non-functional auth_header key.

Addressed Gemini Code Assist review comment.

* fix: update MiniMax Token Plan provider adapter and documentation to English

* feat: add MiniMax Token Plan configuration and icon support

* feat: remove default configuration template from MiniMax Token Plan provider adapter

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-17 16:48:52 +08:00
エイカク
5be6536f0e fix: support SOCKS proxies in updater requests (#7615)
* fix: support SOCKS proxies in updater requests

* fix: log updater HTTP status details

* fix: clean partial updater downloads on failure

* test: lock updater httpx client options

* refactor: harden updater httpx configuration
2026-04-17 13:13:21 +09:00
Soulter
087c793615 revert "fix: scss import warning (#7528)" (#7616)
This reverts commit ee85a4e50f.
2026-04-17 11:58:47 +08:00
Hongbro886
89096411d2 docs: correct documentation URL from astrbot.app to docs.astrbot.app (#7612)
* docs: correct documentation URL from astrbot.app to docs.astrbot.app

* docs: correct documentation URL from astrbot.app to docs.astrbot.app
2026-04-17 11:07:48 +09:00
Hongbro886
22e8cbd10d fix: return an explicit erro from the cron tool when scheduling a task fails instead of processing silently(#7513)
* fix: 定时任务创建失败时返回错误信息而非静默处理

* fix: test and format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-16 20:14:55 +08:00
Kangyang Ji
ee85a4e50f fix: scss import warning (#7528)
* chore(dashboard): 将 Sass @import 迁移到 @use

Dart Sass 3.0.0 将移除 @import,迁移到 @use 以消除弃用警告

* add new import into style.scss

---------

Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
2026-04-16 20:05:37 +08:00
SweetenedSuzuka
a8660ff21e fix(weixin_oc): persist context_token for proactive cron sends (#7595)
* fix(weixin_oc): persist context_token for proactive cron sends

* test(weixin_oc): add safety coverage for context token persistence

* fix(weixin_oc): address review on context token state

* chore: delete tests/unit/test_weixin_oc_adapter_state.py

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-04-16 20:03:59 +08:00
Soulter
469f498428 fix: increase anthropic default max tokens (#7593) 2026-04-16 14:51:36 +08:00
XiaoYang
34cf4014e6 fix: prevent numeric input from resetting to zero on blur without edit (#7560)
When a numeric input field was focused but not edited, the blur handler
called toNumber(null) which returned 0 via parseFloat(null) → NaN → 0.
Now we skip emitting the update when numericTemp is null (no edits made).
2026-04-16 08:48:13 +08:00
LIghtJUNction
e16e5c7630 fix: resolve merge conflicts from upstream and fix tool conflict resolution
- ToolSet.add() now protects active tools from inactive overrides
- Add missing _has_meaningful_content() method in RespondStage
- Remove is_local=True from ExecuteShellTool (no longer supported)
- Fix ToolSet() missing namespace argument in get_full_tool_set()
- Rewrite tests to match new tool architecture (cron_tools, func_tool_manager, tool_conflict_resolution)
2026-04-15 20:45:11 +08:00
LIghtJUNction
4d1e0ef1be merge: resolve conflicts from upstream
Conflict resolution: accepted HEAD versions for all conflicted files.
2026-04-15 17:03:54 +08:00
時壹
7c39abc6b5 fix(dashboard): resolve chat attachment 401 (#7569)
* fix(dashboard): resolve chat attachment 401 by restoring axios blob URL fetch

* chore: cache blob URL promises to prevent duplicate requests and memory leaks
2026-04-15 15:52:14 +08:00
Soulter
cb91dfb6f7 docs: update installation instructions to require Python 3.12 for uv deployment 2026-04-14 19:50:54 +08:00
Soulter
49531da91d feat: add on_agent_begin, on_using_llm_tool, on_llm_tool_respond, on_agent_done event hooks (#7540)
* feat: add on_agent_begin, on_using_llm_tool, on_llm_tool_respond, on_agent_done event hooks

* docs: add version requirement for event hooks in message event guide

* Update astrbot/core/star/star_handler.py

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

* Update astrbot/core/astr_agent_hooks.py

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

* feat: rename event types to include 'Event' suffix for consistency

* chore: ruff format

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-14 18:55:05 +08:00
若月千鸮
625eab223f feat: enable shiki highlighting for t2i templates and add a template (#7501)
* fix: enable shiki highlighting for t2i templates

* fix: t2i templates cr

* feat: add new t2i template astrbot_vitepress.html
2026-04-14 16:46:32 +08:00
Ruochen Pan
207eb34ba2 fix: improve error handling for knowledge base upload (#7536)
* fix: improve error handling for knowledge base upload

- Log details field in KnowledgeBaseUploadError for better debugging
- Distinguish between empty pre-chunked text and empty chunking result
  with appropriate error messages

* style: format code
2026-04-14 16:44:14 +08:00
Gargantua
cc72c01c0e fix: improve knowledge base upload error messages (#7534)
* fix: improve knowledge base upload error messages

* fix: deduplicate knowledge base upload logs

* fix: handle type errors in kb embedding validation
2026-04-14 16:27:06 +08:00
Kangyang Ji
11dedf3802 improve dashboard and docs ci to pnpm and cache (#7522) 2026-04-14 16:10:43 +08:00
Soulter
631e5fe152 docs: update supported IM platforms 2026-04-14 10:27:47 +08:00
dependabot[bot]
b342cf9997 chore(deps): bump the github-actions group with 3 updates (#7524)
Bumps the github-actions group with 3 updates: [docker/build-push-action](https://github.com/docker/build-push-action), [actions/github-script](https://github.com/actions/github-script) and [pnpm/action-setup](https://github.com/pnpm/action-setup).


Updates `docker/build-push-action` from 7.0.0 to 7.1.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v7.0.0...v7.1.0)

Updates `actions/github-script` from 8 to 9
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v8...v9)

Updates `pnpm/action-setup` from 5.0.0 to 6.0.0
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v5.0.0...v6.0.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/github-script
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: pnpm/action-setup
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-14 08:48:15 +08:00
Soulter
1292faa446 chore: bump version to 4.23.1 2026-04-13 23:39:34 +08:00
Soulter
abd11d5579 fix: routing not displayed when session id includes : (#7517)
* fix: routing not displayed when session id includes `:`

fixes: #7515
2026-04-13 23:32:40 +08:00
Soulter
afeda9b82a fix: downgrade python-ripgrep version to 0.0.8 in dependencies (#7514)
* fix: downgrade python-ripgrep version to 0.0.8 in dependencies

* fix: update smoke test workflow to support multiple OS and Python versions
2026-04-13 20:54:18 +08:00
エイカク
533a0bde6a fix: align deerflow runner with deerflow 2.0 (#7500)
* fix: align deerflow runner with deerflow 2.0

* fix: address deerflow review feedback
2026-04-13 12:47:27 +09:00
LunaRain_079
35ce281cbe fix: remove unnecessary margins from v-main for consistent layout (#7481)
* fix: remove unnecessary margins from v-main for consistent layout

* fix: remove media query for v-main margin to simplify layout
2026-04-13 08:47:37 +08:00
Waterwzy
80c7ebae8a fix: inconsistent format issue when checking if the plugin is installed (#7493)
* fix: inconsistent format issue when checking if the plugin is installed

* Update dashboard/src/views/extension/useExtensionPage.js

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

* Update dashboard/src/views/extension/useExtensionPage.js

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>
2026-04-13 08:45:27 +08:00
若月千鸮
5f0178bc73 chore: switch dashboard code blocks highlight to shiki (#7497)
* fix: switch dashboard code blocks to shiki and sync theme rendering

* fix: harden and optimize dashboard shiki highlighting
2026-04-13 08:43:36 +08:00
Soulter
6131386893 chore: bump version to 4.23.0 2026-04-13 00:36:04 +08:00
Kangyang Ji
3b2435875c fix: type use of defineStore in @/stores (#7490) 2026-04-12 23:47:40 +08:00
Kangyang Ji
2a229c4beb fix: wrong image name in compose (#7488)
* fix: wrong image name in compose
2026-04-12 22:07:58 +08:00
Soulter
d1913b5950 fix: update tool call icons from mdi-code-braces to mdi-code-json 2026-04-12 22:06:08 +08:00
Soulter
7172281436 feat: add MessageList component and update MDI icon subset 2026-04-12 21:55:10 +08:00
Soulter
bd08273640 refactor: chatui style (#7485) 2026-04-12 20:47:51 +08:00
Soulter
baaad2a69e perf: add 'dashboard_update' to the list of ignored effective commands in HelpCommand 2026-04-12 17:34:57 +08:00
Sascha Buehrle
9a65873424 fix: use UMO-bound config for group_icl_enable in on_message (#7397)
* fix: read group_icl_enable from UMO-bound config (fixes #7305)

* chore: ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-12 16:42:48 +08:00
Soulter
f50f6cd49f refactor: remove rarely-used builtin commands and consolidate functionality (#7478)
* refactor: remove rarely-used builtin commands and consolidate functionality

* docs: update docs

* Update astrbot/builtin_stars/builtin_commands/commands/admin.py

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

* chore: remove /op, /deop

* chore: ruff format

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-12 16:40:08 +08:00
Soulter
5d2b29f8f8 perf: add validation for MCP stdio configuration (#7477)
* perf: add validation for MCP stdio configuration

* Update astrbot/core/agent/mcp_client.py

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

* Update astrbot/core/agent/mcp_client.py

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

* chore: ruff format

* fix: correct regex pattern for shell meta characters

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-12 15:04:46 +08:00
Soulter
68a195e12b perf: make no-new-privileges true when use docker 2026-04-12 14:37:33 +08:00
NekoYukari
2274e0efc9 fix: support both Bailian Rerank API formats based on URL endpoint (#7250)
* fix: support both Bailian Rerank API formats based on URL endpoint

阿里云百炼有两个不同的 rerank API 端点:
- /compatible-api/v1/reranks: 使用扁平请求格式 {model, query, documents}
- /api/v1/services/rerank/...: 需要 input 包装 {model, input: {...}}

之前代码只根据模型名判断格式,导致 qwen3-rerank + compatible-api 组合失败。

修复内容:
- _build_payload(): 根据 URL 是否含 'compatible-api' 决定请求格式
- _parse_results(): 根据 URL 判断响应中 results 的位置

Fixes #7161

* refactor: reduce duplication in bailian rerank payload and results handling

- Extract params building outside the if-else branch
- Add back empty results warning log
- Simplify error handling variable assignment

* fix: simplify bailian rerank payload to use model-based logic only

qwen3-rerank always uses flat format regardless of API endpoint.
Other models (gte-rerank-v2, etc.) use input wrapper format.

This simplifies the logic and correctly handles all model/URL combinations.
Tested: qwen3-rerank accepts both formats, gte-rerank-v2 only supports input wrapper.

---------

Co-authored-by: root <root@localhost.localdomain>
Co-authored-by: Fix Bot <fix@example.com>
2026-04-12 14:23:15 +08:00
Sagiri777
f1f1720c58 feat(weixin_oc): support reply components (#7380)
* feat(weixin_oc): support reply parsing

* fix: harden weixin oc reply parsing

* fix: correct weixin oc reply cache matching

* fix: harden weixin oc reply parsing

* chore: remove test

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-12 14:22:07 +08:00
yuanqiuye
6691411550 fix(discord): prevent 10062 Unknown interaction error by deferring slash commands immediately (#7474)
* fix(discord): prevent 10062 Unknown interaction error by deferring slash commands immediately

* fix(discord): early return if deferral fails

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

* chore: ruff format

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-04-12 14:12:07 +08:00
Soulter
8d28693e32 fix: ensure JSON response is encoded with non-ASCII characters for shell command execution (#7475)
fixes: #7452
2026-04-12 14:01:20 +08:00
Soulter
5f95bbc422 fix: Update plugin version check logic to support pre-releases
fixes: #7473
2026-04-12 13:59:16 +08:00
時壹
a7ce8df024 feat: implement retry mechanism for QQ Official API file uploads (#7430)
* feat: implement retry mechanism for QQ Official API file uploads

* fix: update error logging message for media file upload retries
2026-04-12 13:47:44 +08:00
Misaka Mikoto
09848956e2 fix: align function tool module path with plugin main module (#7462) 2026-04-12 13:44:05 +08:00
Shujakuin
f5207d840c fix: telegram polling recovery after network failures (#7468) 2026-04-12 13:42:51 +08:00
Soulter
b801003801 chore: bump version to 4.23.0-beta.1 2026-04-11 21:15:30 +08:00
LIghtJUNction
3fc29a6327 fix(provider): add missing ClassVar import in gemini_source
ClassVar was used but not imported, causing all Gemini provider
adapters to fail loading with NameError.
2026-04-11 20:43:23 +08:00
LIghtJUNction
7543dd2e9d refactor: remove TUI module and fix type annotations
- Remove TUI platform adapter and web API routes
- Add DiscordEmbed, DiscordButton, DiscordReference, DiscordView to ComponentType enum
- Fix Platform.terminate() and Platform.get_client() with proper implementations
- Fix AstrBotMessage.raw_message type from object to Any
- Add Any type annotation to CONFIG_METADATA_2
2026-04-11 18:27:15 +08:00
Soulter
2472a12671 feat: filesystem grep, read, write, edit file and workspace support (#7402)
* feat: filesystem grep, read, edit file

* feat: add file write tool and enhance file read functionality

* feat: enhance tool prompt formatting and add escaped text decoding for file editing

* feat: remove redundant safe path tests from security restrictions

* feat: implement file read tool with support for text and image files, including validation for large files

* feat: add file read utilities and integrate with filesystem tools

* refactor: move computer tools to builtin tools registry

* refactor: remove unused plugin_context parameter from _apply_sandbox_tools

* feat: supports to display enabled builtin tools in configs

* feat: add tooltip for disabled builtin tools and update localization strings

* feat: add workspace extra prompt handling in message processing

* feat: add ripgrep installation to Dockerfile

* perf: shell executed in workspace dir in local env

* feat: enhance file reading capabilities to support PDF and DOCX parsing, including workspace storage for long documents

* feat: update converted text notice to suggest using grep for large files

* feat: implement handling for large tool results with overflow file writing and read tool integration

* fix: test

* feat: enhance onboarding steps to include computer access configuration and related help information

* feat: add support for additional temporary path in restricted environment checks

* feat: update computer access hints and add detailed configuration instructions
2026-04-11 17:01:54 +08:00
MinaraAgent
b8ccfe3f64 feat(discord): add configurable bot message filtering, allow bot to receive other bots' messages (#6505)
* feat(discord): add configurable bot message filtering

Add `discord_allow_bot_messages` config option to allow receiving
messages from other Discord bots. This is useful for bot-to-bot
communication scenarios like message forwarding between channels.

By default, bot messages are still ignored (backward compatible).

Usage: Set `discord_allow_bot_messages: true` in your Discord
platform configuration.

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

* feat(discord): add WebUI config for discord_allow_bot_messages

Add configuration option to the dashboard for the new
discord_allow_bot_messages feature. Users can now enable/disable
this option through the WebUI in all supported languages
(zh-CN, en-US, ru-RU).

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

* refactor(discord): use typed constructor argument for allow_bot_messages

Address code review feedback:
- Add `allow_bot_messages` as a typed constructor argument in DiscordBotClient
- Simplify the on_message check by using the instance attribute directly
- Pass the parameter in constructor instead of using setattr

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

---------

Co-authored-by: MinaraAgent <minara-agent@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 01:27:46 +08:00
Exynos
8946a90afd feat(provider): add lm_studio timeout in advanced config (#6415)
* feat(provider): add lm_studio timeout in advanced config

* refactor(provider): strengthen template typing and ambiguity diagnostics

* fix(provider): tighten template matching and clone defaults

* remove
2026-04-10 23:53:54 +08:00
LIghtJUNction
ec363aaa18 fix(core): suppress SSL protocol errors from logging
- Add more SSL error patterns to _SSLDebugFilter:
  SSL: UNEXPECTED_RECORD, SSLWantRead, SSLWantWrite,
  SSL_ERROR_CODE, sslPP: error
- Check exc_info for SSL error messages in filter
- Add httpcore and httpx to _NOISY_LOGGER_LEVELS
- Apply _SSLDebugFilter to LogQueueHandler
2026-04-10 22:46:52 +08:00
LIghtJUNction
6a81739392 feat(cli): show ASCII logo and QR code only in interactive mode
- Move logo and print_logo to new astrbot/cli/banner.py module
  to avoid circular imports
- Add is_interactive() helper to detect TTY
- Show ASCII logo in run/init commands only in interactive mode
- Show WeChat QR code ASCII art only in interactive mode;
  non-interactive mode shows just the QR link
2026-04-10 22:42:43 +08:00
LIghtJUNction
cb9d7c0bfa fix(cli): only run runtime bootstrap when needed
Runtime bootstrap (SSL context setup) is now only initialized
in commands that actually need it (run), not on every CLI invocation.
2026-04-10 22:34:40 +08:00
LIghtJUNction
1cd49b438d refactor(cli): remove logo from default CLI output
Logo is now only shown in commands that have their own
startup output (run, init), keeping other commands clean.
2026-04-10 22:31:05 +08:00
LIghtJUNction
9daf44aa4e feat(cli): add detailed version command with system and git info
- Add `astrbot version` subcommand showing:
  - AstrBot version
  - Python version
  - System/machine info
  - Git branch and commit
  - AstrBot root path
  - Platform details
- Also works with `astrbot --version` flag
2026-04-10 22:23:37 +08:00
LIghtJUNction
dcf84e6726 feat: enhance CLI prompts and fix frontend 401 handling
- cmd_conf: show password rules before setting, display length after input
- cmd_init/cmd_run: add Chinese prompts and HTTPS security warnings
- openai_source/gemini_source: add missing provider adapter import
- ConsoleDisplayer: add missing resolveApiUrl import for SSE
- WelcomePage: show user-friendly message for 401 unauthorized errors
2026-04-10 21:58:52 +08:00
LIghtJUNction
5303e40931 Merge branch 'master' into dev
Resolved all conflicts using dev (HEAD) version:
- func_tool_manager.py: migrated old implementation into new architecture
- tool_loop_agent_runner.py: preserve lazy_load mode, remove step limit
- Platform adapters, dashboard, core modules: use HEAD version
2026-04-10 20:58:41 +08:00
LIghtJUNction
18e66595f0 chore: ruff check --fix && ruff format . 2026-04-10 20:12:33 +08:00
LIghtJUNction
aa279f0c45 chore: ruff format . 2026-04-10 20:07:41 +08:00
LIghtJUNction
e781c5eaa5 chore: ruff check --fix --select ALL 2026-04-10 20:05:08 +08:00
LIghtJUNction
7a23c264a3 chore: gitignore 2026-04-10 19:59:40 +08:00
LIghtJUNction
ec1af1ac0f ruff check --fix --select ALL 2026-04-10 19:57:02 +08:00
2doright
574e5089ba docs: fix path concatenation error in storage.md (#7448)
* docs: 修复 storage.md 中路径拼接的错误示例

get_astrbot_data_path() 返回的是 str 类型,直接使用 / 运算符会导致 TypeError。修改文档示例,添加 Path() 包裹

* docs: 修复 storage.md 中路径拼接的错误示例

get_astrbot_data_path() 返回的是 str 类型,直接使用 / 运算符会导致 TypeError。修改文档示例,添加 Path() 包裹。
2026-04-10 18:41:54 +08:00
Soulter
16f57dd971 chore: remove lxml and bs4 deps (#7449) 2026-04-10 18:39:54 +08:00
エイカク
122e6c719f fix: make desktop plugin dependency loading safer on Windows (#7446)
* fix: make desktop plugin dependency loading safer on Windows

* fix: restore dependency recovery after precheck fallback

* test: cover version mismatch reinstall path

* refactor: clarify dependency recovery state handling

* style: format star manager with ruff

* fix: skip dependency recovery for plugin import errors

* fix: surface unexpected dependency recovery failures
2026-04-10 17:08:10 +09:00
Shujakuin
9c14a50b06 fix: split long telegram final segments (#7432)
* fix: split long telegram final segments

* test: refine telegram adapter helpers

* Update astrbot/core/platform/sources/telegram/tg_event.py

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

* Update tg_event.py

* chore: ruff format

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-04-10 14:36:47 +08:00
Soulter
c791c815e1 perf: merge 3 cron tools into 1 cron manage tool, and add edit capability for cron tool. (#7445)
* perf: replace cron tools with FutureTaskTool for improved task management

* feat: enhance FutureTaskTool with edit functionality and improve descriptions

* feat: add edit functionality for cron jobs and update related UI components
2026-04-10 14:32:57 +08:00
Soulter
e34d9504e4 chore: update logo in README.md 2026-04-09 17:27:09 +08:00
LIghtJUNction
33f54aaec6 fix(updator): skip update prompt when prerelease version >= latest stable
When user installs a dev/beta/alpha/rc version (e.g. 4.25.0-dev),
check_update would skip prerelease releases and compare against the
latest stable (e.g. 4.24.0). Since 4.25.0-dev > 4.24.0 in semver
comparison (numeric part takes precedence), it incorrectly prompted
to update.

Now checks if current version is prerelease and already newer than
the latest stable - in that case, no update prompt is shown.

Fixes: update button shown to users running dev/unstable versions
2026-04-08 21:51:16 +08:00
LIghtJUNction
3cd48ad1d9 feat(cli): block password change if astrbot is running
AstrBot uses a lock file (astrbot.lock) to prevent concurrent instances.
Before allowing a password change via `astrbot conf admin`, the CLI now
attempts to acquire the lock with a 1-second timeout. If acquisition fails
(another process holds it), the command is rejected with a clear error
message instructing the user to stop astrbot first.
2026-04-08 21:28:14 +08:00
LIghtJUNction
3f1a14836f fix(dashboard): auto-prepend https:// for backend URLs without protocol
Previously, a URL like api.lightjunction.online:3000 (without https://)
was stored as-is and treated as a relative path, causing requests to
hit the frontend origin instead of the configured backend. URLs with a
single slash like https:/api... were also incorrectly normalized.

Now normalizeConfiguredApiBaseUrl always prepends https:// if the input
doesn't start with http:// or https://, and apiStore.setApiBaseUrl also
normalizes before storing to keep state and localStorage consistent.
2026-04-08 21:18:16 +08:00
LIghtJUNction
07b49b9e97 fix(deps): bump vite to 8.0.5 (resolves 3 security advisories) 2026-04-08 21:08:49 +08:00
LIghtJUNction
25f108108a fix(dashboard): redirect to server config dialog when backend URL not configured
Before login attempts, check if apiBaseUrl is configured. If empty,
emit openServerConfig event so LoginPage opens the server config dialog
instead of silently sending requests to the frontend origin (causing 405).
2026-04-08 20:59:54 +08:00
LIghtJUNction
dd36913735 fix(discord): resolve 'await' outside async function in collect_commands()
collect_commands() was defined as a sync def but erroneously contained
SDK bridge command registration logic with await sync_commands() inside.
Extract SDK bridge registration into async _register_sdk_commands() and
keep collect_commands() as pure sync (returns command list only).

Also adds missing cast import.
2026-04-08 20:44:12 +08:00
LIghtJUNction
ba7ace4b57 fix: add .npmrc with legacy-peer-deps=true 2026-04-08 19:53:44 +08:00
LIghtJUNction
89209ae29b fix(deps): bump pinia to ^3.0.4 for vue-router@5.0.4 compatibility 2026-04-08 19:53:20 +08:00
LIghtJUNction
86a78b5058 chore: ignore pnpm-lock.yaml 2026-04-08 19:46:33 +08:00
LIghtJUNction
b3c3f52d31 chore: remove pnpm-lock.yaml 2026-04-08 19:45:25 +08:00
LIghtJUNction
43156d6eac Merge branch 'origin/dev' into dev
Resolved merge conflicts in:
- func_tool_manager.py: kept origin version (full implementation)
- astr_main_agent*.py: kept HEAD version (complete refactor)
- cron_tools.py: kept HEAD version (with get_all_tools)
- config/default.py: kept HEAD version (DEFAULT_WEB_SEARCH_PROVIDER)
- dashboard/*.vue: kept HEAD version
- web_searcher engines: kept HEAD version
- Added new tools: knowledge_base_tools, message_tools, registry, web_search_tools
2026-04-08 19:45:16 +08:00
LIghtJUNction
7d22cfbf73 chore: gitignore 2026-04-08 19:33:41 +08:00
Soulter
38b1b4d4ea refactor: improve astrbot builtin tool management (#7418)
* feat: Refactor astrbot builtin tool management

- Introduced a new registry for builtin tools to streamline their management.
- Added `SendMessageToUserTool`, `KnowledgeBaseQueryTool`, and various web search tools as builtin tools.
- Updated `FunctionToolManager` to cache and retrieve builtin tools efficiently.
- Modified `CronJobManager` to utilize the new `SendMessageToUserTool`.
- Enhanced the dashboard to display readonly status for builtin tools and prevent toggling their state.
- Added tests for builtin tool injection and retrieval to ensure proper functionality.

* fix: escape file path in shell command to prevent injection vulnerabilities
2026-04-08 14:49:58 +08:00
Soulter
94a529d3fd refactor: remove default web search (#7416)
* refactor: remove default web search

* chore: ruff format
2026-04-08 13:26:53 +08:00
daniel5u
c517cdb490 feat: add new web search tool Brave Search (#6847)
* feat:Brave Search API adapted

* Modified hint message

* Modified according to AI reviews

* chore: revert compose.yml changes

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-08 12:00:21 +08:00
時壹
ef15955096 fix: prevent floating buttons from jumping during page transitions (#7214) 2026-04-08 11:37:22 +08:00
Ruochen Pan
76fcc56866 fix: add ChatUIProject & SessionProjectRelation to shared constants & test cases (#7414) 2026-04-08 11:35:59 +08:00
kaiisfree
d42711d687 fix: remove unsupported id field from Gemini FunctionResponse (#7357) (#7386)
Co-authored-by: Kai <kai@kaiisfree.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 11:33:52 +08:00
Yufeng He
321504fb4f fix(telegram): skip empty text in sendMessageDraft to prevent 400 spam (#7398)
When streaming is enabled, markdownify() can produce empty strings for
certain inputs (whitespace-only, formatting-only markdown). The draft
sender loop then calls sendMessageDraft with empty text, which Telegram
rejects with 'Text must be non-empty', flooding the log every 0.5s.

Add an early return in _send_message_draft() when text is empty or
whitespace-only. This matches WebChat's approach of skipping empty
responses.

Fixes #7353

Co-authored-by: Yufeng He <40085740+universeplayer@users.noreply.github.com>
2026-04-08 11:32:38 +08:00
氕氙
2020eecc72 fix(dashboard): fix WebUI dark mode rendering and multiple UI interaction bugs (#7173)
* fix(dashboard): comprehensive dark mode improvements for WebUI

- Tune DarkTheme.ts color palette: soften primary, fix on-surface-variant
  from black to light grey, adjust surface/background/border colors,
  add codeBg/preBg/code variables for dark code blocks
- Add _HljsDark.scss for highlight.js dark token overrides and
  markstream-vue CSS variable overrides under .v-theme--PurpleThemeDark
- Add global dark mode overrides in _override.scss: soften flat primary
  buttons, timeline dots, dialog card backgrounds, markdown link color
- Fix hardcoded light backgrounds in IPythonToolBlock, ExtensionCard,
  T2ITemplateEditor, ExtensionPage, KnowledgeBase, LongTermMemory
- Remove hardcoded color='black' from icons in ProviderPage,
  PlatformPage, PersonaPage
- Desaturate console log ANSI colors for dark mode readability
- Add iframe dark mode inversion filter in VerticalSidebar
- Fix language switcher mobile adaptation and click behavior
- Fix login page theme toggle tooltip showing wrong label

* fix(dashboard): apply dark mode review feedback
2026-04-08 11:29:24 +08:00
Yufeng He
1ab925ed9f fix: skip FunctionCallingConfig when only native tools are present (#7407)
* fix: skip FunctionCallingConfig when only native tools are present

When native tools (google_search, url_context) are enabled without any
function_declarations, _prepare_query_config was still creating a
FunctionCallingConfig, which makes Gemini API return 400 INVALID_ARGUMENT.

Now we only set tool_config when tool_list actually contains
function_declarations.

Fixes #7406

* style: ruff format
2026-04-08 11:19:47 +08:00
Double2and9
301df11102 fix: prevent KeyError in Telegram collect_commands when plugin handler not in star_map (#7405)
* fix: prevent KeyError in collect_commands when plugin handler not in star_map

* chore: ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-08 11:15:43 +08:00
Aster
2fae22107d fix: defer faiss imports during startup (#7400)
* fix: defer faiss imports during startup

* chore: gemini cr

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

* chore: ruff format

* fix: move torch import to _resolve_device method and remove obsolete tests

* fix: remove obsolete test for eager loading of faiss during startup imports

* test: fix kb helper patch target after faiss lazy import

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-04-08 00:33:39 +08:00
Soulter
dfca5cdb79 fix: improve warning message for missing context token in WeixinOCAdapter 2026-04-07 18:26:27 +08:00
M1LKT
42fc16f1f0 fix: reduce MCP server status polling frequency (#7399) 2026-04-07 10:39:38 +08:00
dependabot[bot]
c48288d8f6 chore(deps): bump docker/login-action in the github-actions group (#7401)
Bumps the github-actions group with 1 update: [docker/login-action](https://github.com/docker/login-action).


Updates `docker/login-action` from 4.0.0 to 4.1.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 01:12:20 +08:00
Soulter
8c6c00ae62 fix: update tool result assertions to reflect dynamic threshold values 2026-04-06 18:37:52 +08:00
神楽坂·喵
0ce5fde7f8 feat(platform): add Mattermost bot support (#7369)
* feat(platform): add Mattermost bot support (#6009)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(platform): address Mattermost review feedback

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(platform): improve Mattermost streaming and file IO

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* perf(platform): optimize Mattermost duplicate detection

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(platform): preserve Mattermost command prefixes after mentions

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(platform): cover Mattermost attachment parsing

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: add mattermost docs

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: Soulter <905617992@qq.com>
2026-04-06 18:27:28 +08:00
Soulter
2a3d93a6c5 fix: clean up qq official websocket shutdown (#7395)
* fix: clean up qq official websocket shutdown

fixes: #7259

* fix: do not catch KeyboardInterrupt/SystemExit

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

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-04-06 17:59:50 +08:00
LIghtJUNction
13d0b8cc21 Merge branch 'dev' and fix tool_loop_agent_runner conflict 2026-04-06 16:48:27 +08:00
LIghtJUNction
b802edeeb1 Merge dev and fix conflicts 2026-04-06 16:39:58 +08:00
Soulter
571b571e7e feat: implement llm guidance for repetition tool call (#7388)
* feat: implement llm guidance for repetition tool call

fixes: #7387

* feat: enhance tool execution guidance with user interruption and repetition notices

* chore: fix test

* feat: rename guidance method for repeated tool calls to improve clarity

* feat: update repeated tool notice thresholds to improve user guidance
2026-04-06 16:31:59 +08:00
Chang Lee
b0b6816039 feat: add NVIDIA rerank provider support (#7227)
* feat: add Rerank API support for NVIDIA NIM

- Add Rerank API support for NVIDIA NIM
- Add related i18n support in en-US zh-CN

* chore: format code

* fix: replace illegal characters

Replace illegal characters when building request model path.

* fix: refactor client initialization method

* fix: enhance response parsing

* docs: add comment for model_path process

* docs: add russia translation

* feat: update AddNewProvider component to support current provider type and enhance provider icon mapping

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-06 15:20:21 +08:00
Soulter
224287e170 feat: add audio input support across providers and chatui recording issue fix (#7378)
* feat: add audio input support across providers and chatui recording issue fix

- Introduced audio_urls parameter in Provider class and related methods to handle audio input.
- Updated ProviderAnthropic, ProviderGoogleGenAI, and ProviderOpenAIOfficial to process audio URLs.
- Enhanced media_utils with functions to ensure audio format compatibility and detect audio types.
- Modified dashboard components to display audio input support and handle audio attachments in messages.
- Updated localization files to include audio as a supported modality.
- Added new icons for audio input in the dashboard UI.

* feat: enhance audio handling with temporary file cleanup and format support

* feat: track temporary local files for converted audio components

* fix: update image placeholder in prompt from "[图片]" to "[Image]"
2026-04-06 14:58:29 +08:00
Soulter
80d5efdb45 fix: empty model output error may misfire when use gemini (#7377) 2026-04-06 01:28:23 +08:00
Soulter
ff299f770f chore: bump version to 4.22.3 2026-04-05 23:39:41 +08:00
Futureppo
a93568c6f1 feat(provider): add LongCat LLM Provider (#7360)
* feat(longcat): 添加 LongCat 模型提供商

* chore: remove tests and add longcat logo

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-05 13:00:46 +08:00
machina
d8f8462942 fix: add checks to return None if STT or TTS providers are disabled in config (#7363)
Co-authored-by: machina <1531829828@qq.com>
2026-04-05 12:55:37 +08:00
stevessr
4a3f92cdfd feat(matrix): add missing Matrix constant and update docs (#7368)
* feat(matrix): 添加 Matrix 平台适配器支持及更新文档

* feat(matrix): 添加 Matrix 平台图标和教程链接
2026-04-05 12:54:47 +08:00
Rico0919x
70872cd44b feat(provider/vllm_rerank): add configurable rerank_api_suffix option (#7278)
* feat(provider/vllm_rerank): add configurable rerank_api_suffix option

Add rerank_api_suffix config option to the VLLM Rerank provider so
users can control the API URL path suffix instead of having /v1/rerank
hardcoded.

- Default value is /v1/rerank (preserves existing behavior)
- Users can set it to empty string to disable auto-append
- Handles suffix without leading slash by auto-adding one
- Schema, default config, and i18n metadata all updated

Issue: Fixes #7238

* fix(provider/vllm_rerank): handle null suffix and improve hint descriptions

- Add explicit None check for rerank_api_suffix (fixes HIGH from Gemini)
- Update rerank_api_base hint to describe actual behavior without
  mentioning specific provider options (fixes 3x MEDIUM from Gemini)
- Add ru-RU i18n for rerank_api_suffix (fixes P2 from Codex)

Co-authored-by: gemini-code-assist[bot]
Co-authored-by: chatgpt-codex-connector[bot]

---------

Co-authored-by: LehaoLin <linlehao@cuhk.edu.cn>
2026-04-05 00:15:27 +08:00
Soulter
dc9c17c195 feat: support token usage extraction for llama.cpp (#7358)
* feat: support token usage extraction for llama.cpp

* chore: ruff format
2026-04-04 23:49:18 +08:00
LIghtJUNction
be22a99c31 chore: dashboard 2026-04-04 19:26:58 +08:00
LIghtJUNction
b09defc545 fix(dashboard): remove unused theme variable from App.vue 2026-04-04 19:16:18 +08:00
LIghtJUNction
92ecb6efec chore: style 2026-04-04 19:14:21 +08:00
LIghtJUNction
c2b8378926 fix(dashboard): remove unused variables in VerticalHeader.vue 2026-04-04 19:12:57 +08:00
LIghtJUNction
c27118d6fe style(dashboard): format and fix types in authLoginProof 2026-04-04 19:10:55 +08:00
LIghtJUNction
6f8e1706e5 style(dashboard): format parameters in authLoginProof.ts 2026-04-04 19:07:54 +08:00
LIghtJUNction
779517d7c4 refactor(dashboard): replace console.log with console.info 2026-04-04 19:04:39 +08:00
LIghtJUNction
c8b83f0ba3 build(dashboard): upgrade lodash-es to 4.18.1 in overrides to fix security vulnerabilities 2026-04-04 19:02:49 +08:00
LIghtJUNction
b40401a50f style(dashboard): format password validation rule 2026-04-04 18:54:50 +08:00
LIghtJUNction
4588543364 fix(dashboard): fix vuetify theme deprecation, sse cors, and update i18n texts 2026-04-04 18:51:13 +08:00
LIghtJUNction
0b07409016 fix(dashboard): completely eliminate all vuetify theme change warnings 2026-04-04 18:39:19 +08:00
LIghtJUNction
6675a95752 fix(dashboard): completely resolve vuetify deprecation warning for theme switching 2026-04-04 18:38:49 +08:00
LIghtJUNction
607735e55b fix(dashboard): resolve missing translations and autocomplete warnings 2026-04-04 18:37:05 +08:00
LIghtJUNction
b4f3718413 fix(dashboard): restore beautiful glassmorphism login UI lost during master branch merge 2026-04-04 18:33:45 +08:00
LIghtJUNction
3b8a77b053 fix(dashboard): use correctly intercepted axios in VerticalHeader.vue to respect API base url 2026-04-04 18:11:55 +08:00
LIghtJUNction
5012475c29 style: remove redundant empty lines and unused exception variables 2026-04-04 17:53:05 +08:00
LIghtJUNction
6bff35d40c fix(dashboard): resolve JSON syntax errors and BOM in auth.json 2026-04-04 17:22:39 +08:00
LIghtJUNction
f429c7203a test: update dashboard password resolution and fix mock loggers 2026-04-04 17:00:12 +08:00
LIghtJUNction
8f62ad5b73 feat(auth): merge challenge-proof authentication and argon2 hashing from fix branch 2026-04-04 16:54:19 +08:00
Soulter
a64d4e7e6e fix(auth): update md5 import syntax for consistency 2026-04-04 16:44:35 +08:00
LIghtJUNction
3d2ff938f5 fix(cli): use raise from e in exception clauses 2026-04-04 16:34:56 +08:00
Soulter
5c27cf1b30 chore: ruff format 2026-04-04 16:31:59 +08:00
Soulter
a47e39d7c4 feat(auth): implement secure login challenge and proof verification 2026-04-04 16:30:57 +08:00
LIghtJUNction
4308580039 chore: ruff 2026-04-04 16:29:00 +08:00
LIghtJUNction
c4dee9091a refactor(cli): unify password encryption logic in cmd_conf.py 2026-04-04 16:27:53 +08:00
Soulter
b749f62e90 fix(security): increase PBKDF2 iterations 2026-04-04 15:34:33 +08:00
LIghtJUNction
fe0e235c22 Merge remote-tracking branch 'origin/master' into dev 2026-04-04 15:25:33 +08:00
Soulter
a3abb28ce3 test: adapt dashboard auth fixtures for hashed default password 2026-04-03 17:44:38 +08:00
Soulter
a0159c8a36 fix(i18n): update password policy hints and validation rules for improved security 2026-04-03 17:40:33 +08:00
Soulter
90b79d53fa fix(webui): enforce 12-char dashboard password policy with backend+frontend validation 2026-04-03 17:37:03 +08:00
SoloLevelingAI
77d5d5cc6a fix(windows): inherit all system environment variables into MCP runner for Windows (#7054)
- Merge environment variables case‑insensitively
- Auto‑configure dotnet PATH and suppress console window
- Keep PATHEXT inheritance (from old implementation)

Replaces the minimal PATHEXT fix with a robust solution that resolves
common Windows subprocess issues, especially for .NET servers.

* fix(stdio): improve Windows environment setup for subprocesses

- Merge environment variables case‑insensitively
- Auto‑configure dotnet PATH and suppress console window
- Keep PATHEXT inheritance (from old implementation)
-Add `show_console` option to control `CREATE_NO_WINDOW` flag.Default remains hidden (backward compatible) but can be overridden.

Replaces the minimal PATHEXT fix with a robust solution that resolves
common Windows subprocess issues, especially for .NET servers.

* fix(stdio): improve Windows environment setup for subprocesses 修复(标准输入输出):改进 Windows 环境设置以支持子进程

- Merge environment variables case‑insensitively
- Auto‑configure dotnet PATH and suppress console window
- Keep PATHEXT inheritance (from old implementation)
-Add `show_console` option to control `CREATE_NO_WINDOW` flag.Default remains hidden (backward compatible) but can be overridden.

Replaces the minimal PATHEXT fix with a robust solution that resolves
common Windows subprocess issues, especially for .NET servers.

* fix(stdio): improve Windows environment setup for subprocesses 修复(标准输入输出):改进 Windows 环境设置以支持子进程

- Merge environment variables case‑insensitively
- Auto‑configure dotnet PATH and suppress console window
- Keep PATHEXT inheritance (from old implementation)
-Add `no_console` option to control `CREATE_NO_WINDOW` flag.Default remains hidden (backward compatible) but can be overridden.

Replaces the minimal PATHEXT fix with a robust solution that resolves
common Windows subprocess issues, especially for .NET servers.

* fix(stdio): improve Windows environment setup for subprocesses 修复(标准输入输出):改进 Windows 环境设置以支持子进程

- Merge environment variables case‑insensitively
- Auto‑configure dotnet PATH and suppress console window
- Keep PATHEXT inheritance (from old implementation)
-Add `no_console` option to control `CREATE_NO_WINDOW` flag.Default remains hidden (backward compatible) but can be overridden.

Replaces the minimal PATHEXT fix with a robust solution that resolves
common Windows subprocess issues, especially for .NET servers.

* fix(windows): inherit all system environment variables for subprocesses

- Merge environment variables case‑insensitively
- Auto‑configure dotnet PATH and suppress console window
- Keep PATHEXT inheritance (from old implementation)
- No longer handle as a special case for C#.

Replaces the minimal PATHEXT fix with a robust solution that resolves
common Windows subprocess issues, especially for .NET servers.

* chore: ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-04-03 16:51:20 +08:00
Yufeng He
1408a8449e perf: Set content to None when the OpenAI message content list is empty (#6551)
_finally_convert_payload 提取 think 部分后,如果 assistant 消息的
所有 content 都是 think 类型,new_content 会变成空列表 []。
Grok 等 provider 不接受空 content list,直接报 400。

改为 new_content or None,空列表时回退到 None(OpenAI 兼容 API
普遍接受 null content 的 assistant 消息)。

Fixes #6447

Co-authored-by: Yufeng He <40085740+universeplayer@users.noreply.github.com>
2026-04-03 16:38:22 +08:00
Yufeng He
8f95ca9d98 fix: filter Gemini thinking parts from user-facing message chain (#7196)
Gemini 3 models return thinking parts (part.thought=True) alongside the
actual response text.  _process_content_parts was including these thinking
parts in the message chain sent to the user, effectively leaking internal
reasoning into the output.  On platforms that split long messages (e.g.
aiocqhttp with realtime segmenting), this caused duplicate or triple
replies since the thinking text often mirrors the actual response.

The streaming path already handled this correctly via chunk.text which
skips thinking parts, but the non-streaming path and the final-chunk
processing in streaming both went through _process_content_parts.

Also switch the Gemini 3 model name matching from an exhaustive list to
prefix matching (gemini-3- / gemini-3.) so new variants like gemini-3.1
get proper thinkingLevel config without code changes.

Fixes #7183
2026-04-03 16:35:25 +08:00
Yufeng He
5e78a24d63 fix: satisfy Google Gemini's function_response requirements to avoid 400 Invalid argument errors (#7216)
Gemini API requires function_response to be a google.protobuf.Struct
(JSON object). When tool results are plain text strings, the API
returns 400 Invalid argument. Detect non-JSON tool content for Gemini
models and wrap it in {"result": content} before sending.

Fixes #7134
2026-04-03 16:32:49 +08:00
Soulter
6a7b622c48 fix: resolve Discord/Misskey hot reload issue by fixing client_self_id misuse (#7331)
* fix: resolve Discord/Misskey hot reload issue by fixing client_self_id misuse

fixes: #7187
closes: #7188

* fix: english logging
2026-04-03 14:03:23 +08:00
Soulter
5886c43752 fix: add qrcode package for QR code generation support
closes: #7327
2026-04-03 13:15:04 +08:00
氕氙
88d70a8013 docs: 在 uv 部署文档中添加不支持 WebUI 升级的说明 (#7298)
* docs: 在 uv 部署文档中添加不支持 WebUI 升级的说明

通过 astrbot run(CLI 模式)启动时,会设置 ASTRBOT_CLI 环境变量,
updator 会拒绝 WebUI 触发的升级操作以避免版本管理混乱。
用户需要通过命令行执行 uv tool upgrade astrbot 来更新。

Closes #7291

* Update README.md

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

* Update README_fr.md

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

* Update README_ja.md

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

* Update README_ru.md

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

* Update README_zh-TW.md

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

* Update README_zh.md

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

---------

Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-03 09:03:29 +08:00
LIghtJUNction
26ff632831 chore: remove astrbot-rs 2026-04-03 01:26:25 +08:00
LIghtJUNction
8310ade509 Update pyproject.toml 2026-04-03 01:13:09 +08:00
LIghtJUNction
6918ebe740 fix: revert shell execution logic back to master implementation 2026-04-03 01:06:37 +08:00
LIghtJUNction
252c62379e feat: rename CORS_ALLOW_ORIGIN to ASTRBOT_CORS_ALLOW_ORIGIN and add it to .env.example 2026-04-03 01:01:31 +08:00
LIghtJUNction
7b11f90d7b chore(deps): bump lodash from 4.17.23 to 4.18.1 in dashboard 2026-04-03 00:50:35 +08:00
LIghtJUNction
2126002b7a fix: 修复 Vue 样式穿透警告并更新 tsconfig 解析模式 2026-04-02 23:16:09 +08:00
LIghtJUNction
d9e91bb41e style: 修复 Webchat 浅色模式字体颜色及更新数据统计面板样式 2026-04-02 22:58:55 +08:00
LIghtJUNction
59c0e744c3 fix(dashboard): use @/utils/request instance of axios globally 2026-04-02 22:27:29 +08:00
LIghtJUNction
5f701a75c7 fix(dashboard): use global.name.value for Vuetify 3 theme change 2026-04-02 22:22:34 +08:00
LIghtJUNction
582a63b79e fix(dashboard): mount pinia before router to avoid white screen on start 2026-04-02 22:20:11 +08:00
LIghtJUNction
d3a429a11f fix(dashboard): remove unused join import in vite config 2026-04-02 22:15:00 +08:00
LIghtJUNction
422d3c169c chore(dashboard): silence Sass if-function deprecation warnings 2026-04-02 22:13:27 +08:00
LIghtJUNction
c867dac40b fix(deps): dompurify version conflict 2026-04-02 21:58:44 +08:00
LIghtJUNction
ea5d5736ff chore(vite): silence Sass import deprecation warnings 2026-04-02 21:58:33 +08:00
LIghtJUNction
22606f3510 Restore original dev frontend request handling 2026-04-02 21:45:02 +08:00
LIghtJUNction
74849b4936 fix auth store defineStore arguments 2026-04-02 21:43:34 +08:00
LIghtJUNction
005b836fea Merge remote-tracking branch 'origin/master' into dev
# Conflicts:
#	astrbot/core/knowledge_base/kb_helper.py
#	astrbot/core/knowledge_base/kb_mgr.py
#	dashboard/src/components/extension/PinnedPluginItem.vue
#	dashboard/src/components/provider/ProviderModelsPanel.vue
#	dashboard/src/components/provider/ProviderSourcesPanel.vue
#	dashboard/src/components/shared/ConsoleDisplayer.vue
#	dashboard/src/main.ts
#	dashboard/src/stores/auth.ts
#	dashboard/src/views/ConversationPage.vue
#	dashboard/src/views/ProviderPage.vue
#	dashboard/src/views/authentication/auth/LoginPage.vue
#	dashboard/src/views/knowledge-base/KBList.vue
#	requirements.txt
2026-04-02 21:37:21 +08:00
LIghtJUNction
3af00b90bd chore: cmd_run 2026-04-02 21:30:59 +08:00
LIghtJUNction
ca4923dec6 refactor: remove TUI from cmd_run 2026-04-02 21:28:37 +08:00
LIghtJUNction
868c81bbc7 chore: commit all changes 2026-04-02 21:23:23 +08:00
LIghtJUNction
0883437c1a chore: remove dashboard dist symlink 2026-04-02 19:38:26 +08:00
LIghtJUNction
310fdf3c14 fix: handle broken dashboard dist symlink in hatch build hook for AUR compatibility 2026-04-02 19:38:17 +08:00
氕氙
9d4472cb2d fix: 改进知识库的初始化错误处理 (#7243)
* fix: 改进 KnowledgeBaseManager 和 KBHelper 中的初始化错误处理

* fix: 改进知识库初始化和重排序错误处理,增强日志记录

* fix: 改进知识库模块初始化和检索错误处理

* fix(ui): handle kb init errors in list cards

display a dedicated error state for knowledge base cards that fail
initialization, including a visible badge and error details

prevent navigation and edit actions for failed cards while keeping
delete available, and hide normal stats/description for error items

add list.initError locale strings for en-US, ru-RU, and zh-CN

* fix(kb): avoid replacing helper on init failure

Initialize a new KB helper before swapping instances so a failed re-init
does not break the active knowledge base service.

If initialization fails, restore in-memory KB settings and keep the
existing helper and previous init error state.

Also clear stale init_error after successful vector DB initialization to
prevent outdated error reporting.

* test(kb): add kb manager resilience tests

cover initialization failure and recovery scenarios to guard
against regressions in kb error handling

include reference assets under refs for test validation

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-04-02 16:16:22 +08:00
Kangyang Ji
b17e5d42b7 feat(dashboard): Enhance Types in Settings.vue (#7241)
* feat: Strict Types for Settings.vue, Enhance Error Handling
feat: Fixed Type in Theme Constant for better TypeScript in Settings.vue

* fix: add other error handling and improve api create type behavier

* fix error messages
2026-04-02 14:56:35 +08:00
M1LKT
e8d6938d31 Feat(webui): dashboard and console qol improvements (#7215)
* feat: support native fullscreen for log console

* feat: skip welcome page for configured users

* feat:  display plugin names under pinned icons

* fix: refine container styles
2026-04-02 13:40:21 +08:00
RichardLiu
206973e8ad Docs/update mimo provider readme (#7207)
* feat: add mimo tts provider support

* fix: handle empty mimo tts choices

* feat: add mimo stt provider support

* fix: align mimo tts style payload with official docs

* docs: add Xiaomi MiMo Omni and TTS services to multiple language READMEs
2026-04-02 10:25:19 +08:00
kaixinyujue
0ecddb4c06 修复:过滤空助手消息,以防止在严格API上出现400错误(fix: filter empty assistant messages to prevent 400 error on strict APIs) (#7202)
* fix: filter empty assistant messages to prevent 400 error on strict APIs

Some OpenAI-compatible APIs (e.g., Moonshot) reject requests with
empty content in assistant messages when no tool_calls are present.
This fix cleans up the messages payload before sending to avoid
'message at position X must not be empty' errors.

Closes related issue with fallback provider behavior.

* test(openai): add tests for empty assistant message filtering

* refactor(openai): simplify empty assistant message filtering logic

* style: format code

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-04-02 09:10:06 +08:00
Thelia
2de23184d0 Update connection success message for AstrBot (#7279) 2026-04-02 08:49:48 +08:00
Yufeng He
4d2791aa9a fix: support both old and new Bailian Rerank API response formats (#7217)
* fix: support both old and new Bailian Rerank API response formats

The new compatible API (compatible-api/v1/reranks) returns results at
the top level as data.results, while the old API returns them nested
under data.output.results. The parser only checked the old path,
causing qwen3-rerank to always report empty results.

Fixes #7161

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

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

---------

Co-authored-by: Ruochen Pan <badbatch0x01@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-01 11:55:54 +08:00
Chang Lee
3dd7799f27 fix(Docker): add amr encoder (#7247)
- Modified Dockerfile to add amr encoder (use libavcodec-extra)
2026-04-01 11:55:16 +08:00
NekoYukari
deedf85360 fix: add pysocks dependency to support SOCKS5 proxy for pip install (#7221)
* fix: add pysocks dependency to support SOCKS5 proxy for pip install

* docs: update proxy description to include https:// support

* fix: add python-socks and pysocks to requirements.txt for consistency

---------

Co-authored-by: root <root@localhost.localdomain>
2026-04-01 09:05:02 +08:00
Kangyang Ji
105530a51c fix: correct the image of compose (#7240) 2026-04-01 08:55:58 +08:00
Soulter
4d9dce184f feat: integrate Monaco Editor workers for enhanced code editing support (#7249)
fixes: #5587
2026-04-01 01:18:18 +08:00
Soulter
788d103a36 refactor: update provider panels for improved layout and styling (#7248) 2026-04-01 01:12:35 +08:00
LIghtJUNction
360a13b227 chore: smart commit — update AGENTS.md, run ruff format, and apply small targeted fixes 2026-04-01 00:52:50 +08:00
LIghtJUNction
9c9d4d6db9 refactor(dashboard): update UI pages to glassmorphism style
- SubAgentPage.vue: rewrite with trace-page style (glassmorphism)
- CronJobPage.vue: rewrite with trace-page style (glassmorphism)
- SessionManagementPage.vue: update CSS variables to match
- ConversationPage.vue: update CSS variables to match

Changes:
- Add CSS variables for glassmorphism effect (blur, transparency)
- Update color scheme to use CSS custom properties
- Improve visual consistency across pages
- Add dark mode support with theme-aware variables
2026-04-01 00:38:32 +08:00
LIghtJUNction
cbeb25fd2d fix(provider): improve type annotations in volcengine TTS loggable payload
Add explicit type annotations to payload variables in _build_loggable_payload
to satisfy ty type checker without using cast.
2026-04-01 00:24:15 +08:00
LIghtJUNction
5e6a9f9cdb Merge branch 'dev' of https://github.com/AstrBotDevs/AstrBot into dev 2026-03-31 23:26:50 +08:00
LIghtJUNction
f695ddc119 Delete .mcp.json 2026-03-31 23:26:24 +08:00
LIghtJUNction
12168a964e 删除 .mcp.json 2026-03-31 23:22:42 +08:00
LIghtJUNction
69b1b099a6 refactor(dashboard): improve SSL configuration and code quality
server.py:
- Add additional SSL certificate environment variable fallbacks
- Improve SSL configuration resolution
- Clean up code structure

routes:
- Add type annotations to various route handlers
- Improve code quality in knowledge_base, session_management, log routes
2026-03-31 20:17:38 +08:00
LIghtJUNction
5357a29ff2 refactor(computer): improve type safety and error handling
bwrap.py:
- Improve property accessors with better error handling
- Add RuntimeError checks for unavailable components before boot

shipyard.py & shipyard_neo.py:
- Add type annotations and improve code quality

browser.py, fs.py, neo_skills.py, python.py:
- Improve type annotations

computer_tool_provider.py:
- Add type annotations
2026-03-31 20:17:26 +08:00
LIghtJUNction
7b16068a04 refactor(star): improve type safety and code quality
session_llm_manager.py:
- Add SessionServiceConfig TypedDict for type safety
- Add _normalize_session_service_config helper for config validation

session_plugin_manager.py:
- Add type annotations and improve code structure

star_manager.py:
- Improve type annotations and code quality

Other star modules:
- Minor improvements
2026-03-31 20:17:13 +08:00
LIghtJUNction
585ffb3982 refactor(pipeline): improve type safety and code quality
stage.py:
- Add StageProcessResult type alias for better type checking
- Change process method signature for better compatibility

respond/stage.py & result_decorate/stage.py:
- Improve type annotations and code structure

content_safety_check/stage.py:
- Add better type handling

agent_sub_stages (internal.py, third_party.py):
- Improve type annotations for better code quality

Other pipeline stages:
- Minor improvements to type annotations
2026-03-31 20:16:59 +08:00
LIghtJUNction
a306c63a92 refactor(agent): improve type safety in agent components
message.py:
- Use TypeGuard for type narrowing instead of isinstance checks
- Improve type annotations for ContentPart validation
- Add type annotations for content part registry

mcp_client.py:
- Improve type annotations and code quality

runners (base, dashscope, deerflow, dify, tool_loop):
- Add/improve type annotations
- Clean up code structure

tool.py & tool_image_cache.py:
- Improve type annotations
2026-03-31 20:16:47 +08:00
LIghtJUNction
9ba2ea62c3 refactor(provider): improve type safety and code quality
entities.py:
- Improve assemble_context return type annotation
- Add explicit type annotations for content_blocks
- Add safety checks for text content extraction

provider.py:
- Improve type annotations throughout
- Clean up code structure

Various source providers:
- Add/improve type annotations in anthropic, azure_tts, gemini, volcengine_tts, etc.
- Improve code quality in whisper and xinference providers
2026-03-31 20:16:35 +08:00
LIghtJUNction
b152516f69 refactor(db): clean up redundant type annotations and improve code
- Remove redundant session: AsyncSession type comments in sqlite.py
- Add type annotations to shared_preferences_v3.py migration
- Improve vec_db implementations with better type hints
- Add __init__.py marker for db package
2026-03-31 20:16:21 +08:00
LIghtJUNction
806c3dfade refactor(commands): improve type safety and add validation
alter_cmd.py:
- Add explicit type annotations for alter_cmd_cfg
- Rename variables for clarity (scene_num -> scene_index, cmd_type -> permission_type)
- Add validation for permission_type parameter

conversation.py:
- Add type annotations and improve command handling

persona.py:
- Clean up type annotations

provider.py:
- Add type annotations and improve provider command handling

setunset.py:
- Add type annotations for configuration operations
2026-03-31 20:16:02 +08:00
LIghtJUNction
65841684de refactor(platforms): improve type safety in platform adapters
- Use ComponentType enum instead of string literals for component types
- Add type annotations for discord button declarations
- Clean up unnecessary code in various platform adapters
2026-03-31 20:15:46 +08:00
LIghtJUNction
3eccbca2c9 refactor(i18n): improve type safety and code quality in i18n_utils
- Add type guard function for str-keyed dicts
- Add I18nGroup TypedDict for better type checking
- Replace isinstance checks with TypeGuard-based validation
- Improve type annotations throughout
2026-03-31 20:15:28 +08:00
LIghtJUNction
da12fca83d refactor(utils): improve type annotations and code quality
command_parser.py:
- Add explicit type annotations for tokens list and return type

config_number.py:
- Handle float to int conversion explicitly
- Simplify type checking logic

file_extract.py:
- Add type annotations and improve file extraction handling

io.py:
- Add type annotations for I/O operations

log_pipe.py:
- Implement TextIO interface for better compatibility
- Add comprehensive type annotations
- Add callback support and identifier logging

session_waiter.py:
- Clean up type annotations
2026-03-31 20:15:09 +08:00
LIghtJUNction
97077ed32e test: clean up type: ignore comments and add package markers
- Remove unnecessary type: ignore comments in test files
- Add __init__.py markers for tests and tests/unit packages
2026-03-31 20:14:47 +08:00
LIghtJUNction
7ff6df9853 chore: add type stubs and update pyproject.toml configuration
- Add type stubs for external packages (faiss, psutil, readability, etc.)
- Move typings to types/ directory
- Update pyproject.toml with mypy plugin configuration
- Add project URLs (Homepage, Repository)
- Update python version to 3.12 in pyright config
2026-03-31 20:14:35 +08:00
LIghtJUNction
fc515d447f Merge remote-tracking branch 'origin/master' into dev
# Conflicts:
#	dashboard/src/assets/mdi-subset/materialdesignicons-subset.css
#	dashboard/src/i18n/locales/ru-RU/features/cron.json
#	dashboard/src/i18n/locales/ru-RU/features/subagent.json
#	dashboard/src/views/ConversationPage.vue
#	dashboard/src/views/CronJobPage.vue
#	dashboard/src/views/SubAgentPage.vue
#	pyproject.toml
2026-03-31 17:26:18 +08:00
LIghtJUNction
328748bd63 Fix cached_tokens handling in _extract_usage method (#6719)
* Fix cached_tokens handling in _extract_usage method

Ensure cached_tokens is an integer and handle None safely.

* ruuf format
2026-03-31 17:14:52 +08:00
LIghtJUNction
87bfecb2f3 chore: update requirements.txt 2026-03-31 17:12:10 +08:00
qingyun
a73e388927 fix(agent): improve send_message_to_user tool description to prevent misuse (#6424)
* fix(agent): improve send_message_to_user tool description to prevent misuse

Fixes #6402

The AI was inappropriately using send_message_to_user tool in normal
conversations for text replies, causing duplicate messages (once via tool,
once via normal response).

Root cause: Tool description was not clear enough about when to use it.

Changes:
- Restructure description with clear sections using markdown
- Emphasize two valid use cases:
  1. Sending media files (image, record, video, file) in any conversation
  2. Proactive messaging scenarios (cron jobs, background tasks)
- Add explicit warning: Do NOT use for normal text replies
- Explain consequence: Using for text causes duplicate messages

This approach (better documentation) is safer than restricting tool
registration, which would break media file sending in normal conversations.

Alternative to PR #6413 which was closed due to breaking media delivery.

* fix: correct syntax error and use triple-quoted string for description

Address review feedback:
- P0: Add missing closing parenthesis (was causing SyntaxError on import)
- Use triple-quoted string for better readability (suggested by gemini-code-assist)
- Remove explicit newline characters, let Python handle line breaks

---------

Co-authored-by: ccsang <ccsang@users.noreply.github.com>
2026-03-31 17:08:42 +08:00
Jacobinwwey
7ff4057fc9 feat(web-search): add provider routing aliases and explicit-engine selection while preserving default engine behavior (#6442)
* feat(web-search): add provider routing and ddg-first default chain

* fix(web-search): keep dev default engine order and demote ddg fallback

* fix(web-search): harden selector/query handling and unify engine naming

* refactor(web-search): streamline provider wiring and harden google query encoding

* fix(web-search): return empty for non-positive filtered result limits

* refactor(web-search): share provider constants and validate engine registry

* refactor(web-search): unify provider normalization and engine registry

* fix(web-search): reduce comet link noise with stricter url filtering

* style(web-search): apply ruff formatting
2026-03-31 17:06:51 +08:00
LIghtJUNction
3f40a1bc00 fix: simplify persona page header layout 2026-03-31 17:05:59 +08:00
LIghtJUNction
d92132293a Merge branch 'dev' of https://github.com/AstrBotDevs/AstrBot into dev 2026-03-31 16:58:32 +08:00
Kangyang Ji
94378d6f35 feat(dashboard): add auto switch theme button to setting page. (#7170)
* feat(dashboard): add auto switch theme button to setting page.

* fix on missing key in en-US translate
2026-03-31 16:58:27 +08:00
LIghtJUNction
4a8686e6a3 Merge branch 'dev' of https://github.com/AstrBotDevs/AstrBot into dev 2026-03-31 16:54:54 +08:00
dependabot[bot]
65a91322e9 chore(deps): bump codecov/codecov-action in the github-actions group (#7209)
Bumps the github-actions group with 1 update: [codecov/codecov-action](https://github.com/codecov/codecov-action).


Updates `codecov/codecov-action` from 5 to 6
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-31 08:49:43 +08:00
Kangyang Ji
ff2d3d11ca fix: delete duplicate layout in PersonaManager.vue (#7190)
根据代码blame,重复的代码来源于两个commit: `feat: update dashboard (1b9820a)` 和 `merge: pull latest master into dev (1faeee3)`, 所以我保留了`feat: update dashboard (1b9820a)`中的代码,删除了`merge: pull latest master into dev (1faeee3)`添加的重复代码。
2026-03-31 00:56:10 +08:00
Soulter
410f30bf26 perf: improve ui (#7178)
* perf: enhance layout responsiveness and text handling in stats page

* perf: enhance subagent, future task UI

- Updated the overall structure of the SubAgentPage component for better readability and maintainability.
- Introduced a new dashboard layout with improved header and action buttons.
- Replaced the old settings card with a more visually appealing setting card design.
- Enhanced the agent list section with a more user-friendly display and added empty state handling.
- Implemented unsaved changes notification and confirmation dialogs for better user interaction.
- Refactored code for better clarity and organization, including the use of computed properties for state management.
2026-03-30 23:53:27 +08:00
Soulter
55f9903b2f perf: enhance token display styles for better readability and layout 2026-03-30 23:50:19 +08:00
Soulter
30d0b1e9da chore: update project metadata in pyproject.html
closes: #7182
2026-03-30 23:49:45 +08:00
LIghtJUNction
a550b88e15 fix: type 2026-03-30 19:30:33 +08:00
LIghtJUNction
f543f16cc1 fix: type 2026-03-30 18:03:27 +08:00
LIghtJUNction
70107b2c8a fix: type 2026-03-30 18:03:22 +08:00
LIghtJUNction
54f6916172 fix: type 2026-03-30 18:03:02 +08:00
LIghtJUNction
4ca8bc7bbc fix: type 2026-03-30 18:02:40 +08:00
LIghtJUNction
abb6a32829 fix: type errors 2026-03-30 18:02:18 +08:00
LIghtJUNction
9b15a60802 fix: resolve 7 type errors in dev branch
- tool_loop_agent_runner.py: add wrapper coroutine for create_task
- tool_image_cache.py: add cast for Self return type
- astr_agent_tool_exec.py: add type ignore for add_tool
- astr_main_agent.py: add type ignores for tool operations
- astr_main_agent_resources.py: add type ignore for msg_dict
- astrbot_config_mgr.py: add type annotations
2026-03-30 18:01:37 +08:00
LIghtJUNction
49d17460d6 fix: add type ignore for msg_dict 2026-03-30 17:46:37 +08:00
LIghtJUNction
7e3bdbc9fa fix: add type ignore for merge 2026-03-30 17:46:20 +08:00
LIghtJUNction
f084fba702 fix: add type ignore for func_tool assignment 2026-03-30 17:46:04 +08:00
LIghtJUNction
376161faa8 fix: add type ignore for persona_toolset.add_tool 2026-03-30 17:45:54 +08:00
LIghtJUNction
2aafe18880 fix: add type ignore for add_tool arg 2026-03-30 17:45:42 +08:00
LIghtJUNction
50b7d18a20 fix: resolve Self return type in ToolImageCache 2026-03-30 17:45:27 +08:00
LIghtJUNction
480c77a150 fix: restore dashboard trace and platform logos 2026-03-30 17:41:01 +08:00
LIghtJUNction
e1c4b52fba fix: resolve create_task type error in tool_loop_agent_runner 2026-03-30 17:36:26 +08:00
LIghtJUNction
e8557909d6 fix: restore dev retry logic and add class constants
- Restore simple dev retry flow (no AsyncRetrying wrapper)
- Add EMPTY_OUTPUT_RETRY_* class constants for test compatibility
2026-03-30 17:17:21 +08:00
LIghtJUNction
086dc00498 fix: resolve MCPTool import and openai_source merge conflicts
- MCPTool_T must be imported at runtime, not in TYPE_CHECKING
- Add __future__ annotations for forward references
- Fix remaining conflict markers in openai_source.py
2026-03-30 17:14:33 +08:00
LIghtJUNction
efa999c221 merge: origin/master into dev
Resolve merge conflicts:
- Version logic: keep dev (dynamic version from package metadata)
- Backend: merge EmptyModelOutputError retry logic from master
- Frontend: keep dev design, accept master functional enhancements
- SSL/config: keep dev inline implementation
2026-03-30 17:07:57 +08:00
Yufeng He
2ffda752ad fix: send SSE heartbeat to prevent WebChat disconnect during compression (#7003)
* fix: send SSE heartbeat to prevent WebChat disconnect during compression

When context compression triggers with slow reasoning models (e.g.
deepseek-reasoner), the backend can go 30+ seconds without pushing any
SSE data. The client-side EventSource / browser then assumes the
connection is dead and disconnects, causing the WebUI to hang
indefinitely since it never receives the eventual response.

Fix: yield an SSE comment (`: heartbeat`) on every empty poll cycle.
Comment lines are defined in the SSE spec as keep-alive signals --
the EventSource API ignores them but the HTTP connection stays open.

Fixes #6938

* chore(dashboard): extract SSE heartbeat to constant

---------

Co-authored-by: Yufeng He <40085740+universeplayer@users.noreply.github.com>
Co-authored-by: RC-CHN <1051989940@qq.com>
2026-03-30 15:52:10 +08:00
Soulter
bfd129402d docs: update community events 2026-03-30 13:10:48 +08:00
Stardust
a4d073bcce fix: improve number input UX in config renderer (#7153)
* fix: improve number input UX in config renderer

* fix: address review comments on number input handling
2026-03-30 10:01:24 +08:00
LIghtJUNction
95cb2a8ac6 fix: resolve multiple type errors and runtime bugs
- shell.py: Fix FunctionTool import from correct module (core.agent.tool)
- deerflow/coze agent runners: Remove invalid return type annotations for step/step_until_done
- aiocqhttp_message_event.py: Fix raise string error (must raise Exception not str)
- lark_event.py: Fix file upload by wrapping bytes in BytesIO for SDK compatibility
- tg_adapter.py: Fix update.message None check in nested function
- TraceDisplayer.vue: Fix text color visibility using proper theme variables
2026-03-30 01:08:43 +08:00
LIghtJUNction
de35ff5cda feat(dashboard): complete redesign of Trace page
- TraceDisplayer: new timeline-style layout with vertical track, dot markers, and expandable event cards
- TracePage: redesigned topbar with custom toggle switch, removed scoped CSS conflicts
- All colors use explicit hex values with !important to ensure visibility across themes
- Vue 3 Composition API with shallowRef to avoid reactive overhead
2026-03-30 01:07:55 +08:00
LIghtJUNction
2a1544fb6c chore: stage remaining changes 2026-03-30 00:48:16 +08:00
LIghtJUNction
62d7df1da7 chore: stage all dev changes 2026-03-30 00:48:07 +08:00
LIghtJUNction
4a0ab861d8 fix(dashboard): fix Trace page text invisible
Root cause: invalid CSS var --v-theme-primaryText resolved to white,
making text invisible against transparent background.

Fix: add global (non-scoped) <style> block with !important color
overrides and explicit dark background for trace table elements.
Also changed .trace-table background from transparent to
var(--v-theme-surface) for proper dark theme support.
2026-03-30 00:45:44 +08:00
LIghtJUNction
2e660595c9 fix(dashboard): AddNewPlatform - show platform-specific MDI icon when logo unavailable 2026-03-29 23:58:35 +08:00
LIghtJUNction
48e54e5ecc revert(dashboard): remove mdi-robot fallback that caused all platforms to show same icon 2026-03-29 23:57:51 +08:00
LIghtJUNction
8919d4debb fix(dashboard): TraceDisplayer - use resolveApiUrl instead of manual VITE_API_BASE concat to avoid /api/api double prefix 2026-03-29 23:17:57 +08:00
LIghtJUNction
9dc345976d fix(dashboard): AddNewPlatform - show v-icon fallback when platform icon is undefined 2026-03-29 23:06:46 +08:00
No-22-Github
f75c2d30b4 fix(core): Record.path was incorrectly treated as required under Pydantic v2 (#7048)
* fix: make Record.path optional for pydantic v2 compatibility

* fix: preserve telegram voice record path
2026-03-29 22:59:22 +08:00
Soulter
2b435e0c89 feat: add brand-new statistics dashboarde overview with model usage and platform usage (#7152)
* feat: add new StatsPage for enhanced statistics overview

- Introduced StatsPage.vue to provide a comprehensive overview of statistics with various metrics and charts.
- Implemented fetching and displaying of base and model provider statistics.
- Added unit tests for provider statistics persistence in the database.

* style: refine card styles and remove unnecessary shadow for improved aesthetics
2026-03-29 22:50:15 +08:00
LIghtJUNction
c464d7add6 fix(dashboard): use CDN MDI font and apply light mode style fixes
- Replace self-hosted MDI subset with CDN (@mdi/font) to avoid
  binary font files being missing after git pull
- Remove vite-plugin-mdi-subset from build (no longer needed)
- Add light mode glass styling to ChatInput
- Fix DailyQuote, Logo, TraceDisplayer for proper theme colors
- Apply theme-specific SCSS overrides across components
2026-03-29 22:09:27 +08:00
LIghtJUNction
7fc1a13519 fix(dashboard): ReactorBg eased scope, CSS comments, theme types, and chat text color
- ReactorBg.vue: fix eased variable scoping bug (moved to outer loop scope)
- WelcomePage.vue: fix CSS // comments (not valid in SCSS)
- DiamondBg.vue: fix CSS // comment in style block
- ThemeType.ts: add missing MD3 hyphenated color properties
- AddNewPlatform.vue: add optional chaining and emits declaration
- FullLayout.vue: console.error -> console.warn for backend timeout
- ConsoleDisplayer.vue: add content-type based log line coloring
- VerticalHeader.vue + i18n: remove deprecated defaultCredentials hint
- MessageList.vue: fix user/bot bubble text color for dark mode
2026-03-29 21:24:39 +08:00
Soulter
9896b48c5e feat: redirect logged-in users to welcome page instead of login page 2026-03-29 20:53:16 +08:00
Soulter
43a9262719 feat: add collapsed item support in configuration UI and update localization for more settings 2026-03-29 20:49:07 +08:00
Soulter
ab66910724 perf: adjust elevation and drag behavior for folder and persona cards, improve layout responsiveness 2026-03-29 20:49:07 +08:00
LIghtJUNction
0c021494aa fix(dashboard): add additional SCSS overrides for dark mode 2026-03-29 18:16:39 +08:00
LIghtJUNction
0dd91f1d10 fix: add noqa comments to platform adapter imports and update theme files
- Add F401 suppression to lazy-loaded platform adapter imports
- Update BlueBusiness theme files
- Add ThemeType definitions and WelcomePage enhancements
2026-03-29 18:16:28 +08:00
LIghtJUNction
158a26cac8 fix(dashboard): improve sidebar styling and dark mode SCSS overrides 2026-03-29 18:16:07 +08:00
LIghtJUNction
15e3c12eab fix(dashboard): improve ChatInput dark mode styling and placeholder visibility
- Use semi-transparent dark background in input container
- Add backdrop blur and glow effects
- Fix placeholder text color in dark mode
2026-03-29 18:15:52 +08:00
LIghtJUNction
a9d657520c fix(dashboard): lock theme to dark-only for industrial aesthetic 2026-03-29 17:12:02 +08:00
LIghtJUNction
65d01b7e62 feat(dashboard): theme-aware reactor canvas and blueprint light mode
ReactorBg now adapts to light/dark theme:
- Dark: #0A0A0C bg, white crosshairs, cyan Cherenkov glow
- Light: #F0F4F8 matte silver, deep indigo crosshairs,
  ink-drop radial shadow (no glow)

Light mode sidebar: stays dark blueprint panel
(light content + dark sidebar = classic MD3 premium pairing)
2026-03-29 17:09:21 +08:00
LIghtJUNction
934a74fd37 chore: remove accidental temp file 2026-03-29 17:07:18 +08:00
LIghtJUNction
c7c878a8e2 feat(dashboard): blueprint light mode theme
- Surface/background: #F0F4F8 cool blue-gray lab white
- On-surface text: #1A2B3C deep indigo
- ContainerBg: translucent rgba glass for light mode
- Surface-variant: slightly deeper cool tone
2026-03-29 17:07:12 +08:00
LIghtJUNction
5109ca96ca feat(dashboard): reactor glow on logo
- Logo image: brightness(1.6) + dual drop-shadow cyan glow
- Radial gradient glow ring beneath logo with slow 4s breath animation
- Title: JetBrains Mono, #00F2FF with text-shadow glow
- All elements share synchronized 4s breathing pulse
2026-03-29 17:04:33 +08:00
LIghtJUNction
0eb04374ce feat(dashboard): reactor form controls and config card glassmorphism
- AstrBotConfigV4: card now uses translucent glassmorphism
  (rgba 15,15,22,0.45, blur 20px) with inset shadow
  for recessed "embedded panel" feel
- Section titles: JetBrains Mono font, cyan (#00F2FF) with
  left 3px glowing gradient bar
- _override.scss: global form control hardening
  * Switch: 4px rounded rectangle, Cherenkov cyan glow
  * Text fields: cyan border on focus with glow
  * Tabs: uppercase monospace, cyan underline + glow on active
  * Slider: cyan track fill + glowing thumb
  * Checkbox: hollow rectangle with cyan check
2026-03-29 16:58:38 +08:00
LIghtJUNction
86e6d08aef feat(dashboard): redesign log console as reactor terminal
ConsoleDisplayer:
- Status tags: hollow 1px-border chips with glowing level dots
  - DEBUG: dim gray, INFO: Cherenkov cyan, WARNING: amber
  - ERROR: #FF4D4D, CRITICAL: magenta
- Terminal: deep charcoal glass (rgba 10,10,15,0.6), blur 20px
  - Inset shadow for recessed monitor feel
  - Animated scanline overlay (CRT effect)
- Log lines: JetBrains Mono, line-height 1.7
- ERROR/CRITICAL: left colored glow bar (inset 3px indicator)
- New entry: brief cyan pulse animation
- Custom thin scrollbar in cyan theme
- ConsolePage toolbar: glassmorphism matching the theme
2026-03-29 16:54:56 +08:00
LIghtJUNction
b79e252100 feat(dashboard): glassmorphism editor and reactor Monaco theme
ConfigPage.vue:
- Editor dialog now uses glassmorphism container with backdrop-filter blur(40px)
- Editor card: deep obsidian translucent bg, inset shadow, cyan border
- Monaco theme changed from vs-dark to custom reactor-dark
  - Transparent background reveals reactor canvas beneath
  - Cherenkov blue line highlights and cursor
  - Industrial precision line numbers

New monacoTheme.ts:
- defineReactorMonacoTheme() registers the custom theme
- Transparent editor background (rgba 0,0,0,0)
- Cyan cursor, selection, and line highlight colors
2026-03-29 16:51:59 +08:00
LIghtJUNction
282ef94911 feat(dashboard): introduce reactor core glassmorphism theme
Global reactor background (ReactorBg):
- Full-screen canvas with 24px crosshair grid and socket dots
- Mouse energy field (120px radius) with lerp=0.08 smooth tracking
- Crosses shrink and glow cyan when energy field passes
- Canvas sits behind all UI (z-index 0, pointer-events none)

Theme updates:
- Dark surface now #0F0F12 for reactor aesthetic
- Background deepens to #0A0A0C
- Cards: translucent glassmorphism (40% opacity, blur 12px)
  with inset shadow, 1px cyan border on hover
- Sidebar: glassmorphism (75% opacity, blur 16px, cyan border)
- Header: glassmorphism (80% opacity, blur 20px, cyan border)
- V-main: transparent so reactor bg shows through
2026-03-29 16:48:52 +08:00
LIghtJUNction
0121df1754 fix(dashboard): show native cursor on login background 2026-03-29 16:45:04 +08:00
LIghtJUNction
90184239c1 feat(dashboard): redesign login page with reactor core aesthetic
- DiamondBg: Canvas-based interactive background with:
  - 24px grid with faint crosshairs and recessed socket dots
  - 150px mouse energy field with lerp following (0.1 speed)
  - Crosses shrink/darken when "pressed" by energy field
  - Cherenkov blue core dot at exact cursor position
  - Gravity well glow beneath login panel
- Login card: cyan edge border (rgba 0,242,255,0.2), deep blue shadow
- Radial fade mask around login area
- DailyQuote component replaces static welcome text
2026-03-29 16:43:36 +08:00
LIghtJUNction
487c1988d6 refactor(dashboard): torch reveal effect with radial cursor glow 2026-03-29 16:36:22 +08:00
LIghtJUNction
daaeb9474b refactor(dashboard): recessed slot grid with lerp cursor tracking 2026-03-29 16:33:23 +08:00
LIghtJUNction
1530ce1932 refactor(dashboard): add elastic cursor tracking with gravity pit effect 2026-03-29 16:31:28 +08:00
LIghtJUNction
fc0e185246 refactor(dashboard): add recessed pit effect with Cherenkov glow under login panel 2026-03-29 16:30:31 +08:00
LIghtJUNction
3e232fb31e refactor(dashboard): crosshair schematic background for login 2026-03-29 16:27:25 +08:00
氕氙
a40a5fe18c docs: add usage of select_knowledgebase in plugin development docs (#7115)
* docs: 补充 select_knowledgebase 及 _special 字段文档

在插件配置文档中添加 select_knowledgebase 的说明(返回 list,
支持多选),并列出 AstrBot Core 内部使用的其他 _special 值供参考。

* docs: 优化 _special 字段文档表达

标注内部 _special 值为不稳定实现,请勿在插件中使用;
说明 select_agent_runner_provider:* 中 * 的含义;
修正英文措辞。
2026-03-29 16:26:28 +08:00
LIghtJUNction
7c0e8414a6 refactor(dashboard): replace diamond bg with sci-fi cylinder panel 2026-03-29 16:25:54 +08:00
LIghtJUNction
f97aca8501 refactor(dashboard): simplify diamond bg with hexagonal close packing 2026-03-29 16:13:48 +08:00
LIghtJUNction
d13ff84a20 feat(dashboard): add animated diamond background to login page 2026-03-29 16:11:58 +08:00
LIghtJUNction
0ee84ae362 fix(dashboard): align daily quote text to left 2026-03-29 16:06:14 +08:00
LIghtJUNction
b9b3d50986 feat(dashboard): rename to Starlight Panel and add daily quote
- Change login page title from "AstrBot WebUI/Dashboard" to "AstrBot Starlight Panel"
- Replace welcome subtitle with DailyQuote component showing programming quotes
- Quotes are localized for en-US, zh-CN, and ru-RU
- Quote of the day stays consistent throughout each day
2026-03-29 16:05:22 +08:00
LIghtJUNction
90d565f4c7 fix(dashboard): remove stray closing div in InstalledPluginsTab 2026-03-29 15:51:09 +08:00
LIghtJUNction
7b22e56252 security: remove legacy SHA256/MD5 password verification and fix API key logging
- Remove insecure SHA256/MD5 password hash verification from cmd_conf.py
  (rejection logic for storing legacy hashes is preserved)
- Remove API key logging from gemini_source.py, openai_source.py
- Remove header logging (contains Authorization header) from volcengine_tts.py

CodeQL issues fixed:
- Broken cryptographic hash (SHA256/MD5 for passwords)
- Clear-text logging of sensitive information (API keys)
2026-03-29 15:48:38 +08:00
LIghtJUNction
2b70c29ea4 chore: bump version to 4.25.0 2026-03-29 15:46:11 +08:00
LIghtJUNction
5ea790d045 chore: misc fixes and new test files
- fix(openai_source): remove dead code comment
- fix(common.ts): use resolveApiUrl helper for live-log endpoint
- style(mdi-subset): clean up icon CSS
- feat: add translation check script and unit tests
2026-03-29 15:40:58 +08:00
LIghtJUNction
610370f3e8 i18n(dashboard): update translation files
Update ru-RU, zh-CN and en-US locale files for various features.
2026-03-29 15:40:58 +08:00
LIghtJUNction
d84565f21b feat(dashboard): switch to BlueBusiness theme
Replace PurpleTheme with BlueBusiness theme for improved visual design.
Includes new light and dark theme definitions.
2026-03-29 15:40:57 +08:00
LIghtJUNction
eca534f6d4 feat(core): add ToolSessionManager for stateful tool execution
Introduce session-level state management for tools that need to maintain
state across conversation turns within the same session (UMO).

- Add ToolSessionManager class for central per-(UMO, tool_name) state
- Add ToolSessionState with set_persistent(key) support
- Add is_stateful flag to FunctionTool base class
- Wire session_manager through run_context in all agent runners
- Update ExecuteShellTool to use framework session manager
- Update CLAUDE.md with stateful tool documentation

BREAKING: Tools that were manually managing session state via _sessions
dict should migrate to use the framework's ToolSessionManager for proper
lifecycle management and persistence support.
2026-03-29 15:40:57 +08:00
Soulter
afa43fc0e2 chore: update version to 4.22.2 in multiple files 2026-03-29 00:32:31 +08:00
Soulter
551c956107 feat: implement EmptyModelOutputError for handling empty responses across providers and enhance retry logic in ToolLoopAgentRunner (#7104)
closes: #7044
2026-03-29 00:03:05 +08:00
Soulter
1070804b90 feat(dashboard): add SSL configuration resolution for dashboard (#7102)
fixes: #7058

program will not exit but fallback to non-ssl mode when ssl config is wrong
2026-03-28 23:22:24 +08:00
Soulter
7db7f4a16c feat(agent-runner): add tool_choice parameter to fix empty tool calls response in "skills-like" tool call mode (#7101)
fixes: #7049
2026-03-28 23:06:06 +08:00
Rainor_da!
77419e0bc7 fix(webui): handle history wheel on preview container (#6972) 2026-03-28 21:38:27 +08:00
Yokami
971bcbad10 fix(provider): fix Bailian rerank payload compatibility for qwen3-rerank (#6222)
* fix(provider): align bailian qwen3 rerank payload with latest API schema

* fix(provider): explicitly ignore unsupported return_documents for qwen3 rerank
2026-03-28 21:27:53 +08:00
Flartiny
da1eb65afe feat: allow copy config from existing configs (#6785)
* feat: allow copy config from existing configs

* fix: issues mentioned by reviewer bot

- duplicated logic for initializing/resetting the config
- check whitespace-only names
2026-03-28 21:25:19 +08:00
Foolllll
bbec8efa0d fix(dashboard): apply labels mapping for list options in config renderer (#6844) 2026-03-28 21:22:00 +08:00
Soulter
b98bd3898f feat: update QQOfficialPlatformAdapter to support async parsing and attachment preparation (#7007)
fixes: #6853
2026-03-28 21:18:33 +08:00
秋月白
81f4bd4e67 fix: allow multiple skills in a single zip archive (#7070)
* fix: allow multiple skills in a single zip archive

* refactor: address bot review comments

* fix: apply ruff format and fix return value
2026-03-28 21:16:40 +08:00
Stardust
4e9916caa4 fix(pipeline): skip waking on empty messages (#6893)
* fix(pipeline): skip waking on empty messages

* fix(pipeline): skip empty message LLM request even with provider_request

* fix(pipeline): skip empty messages in empty_mention_waiter
2026-03-28 20:50:42 +08:00
Rain-0x01_
995a318232 fix(gsvi_tts): Use the correct calling method (#7083)
* fix(gsvi_tts): Use the correct calling method (#5638)
Add some configuration items for GSVI

* fix(gsvi_tts): add default value for api_key in provider configuration

* fix(gsvi_tts): Adjust wherever the Authorization header is built to only include it when `self.api_key` is truthy
Delete some comments

* chore: ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-28 20:48:43 +08:00
エイカク
bcbf7dd8df fix: bundle httpx SOCKS proxy support (#7093)
* fix: bundle httpx SOCKS proxy support

* test: tighten SOCKS dependency regression coverage

* test: allow SOCKS dependency environment markers

* test: broaden SOCKS dependency regex coverage
2026-03-28 21:31:52 +09:00
LIghtJUNction
64bc582879 fix(dashboard): wrap VWindowItem in VWindow to fix Vuetify 4 injection error
VWindowItem requires a VWindow parent for group context injection.
Without it, Vuetify 4 throws:
  "Could not find useGroup injection with symbol vuetify:v-window"

Changes:
- ExtensionPage.vue: wrap all tab content in v-window v-model="activeTab"
- InstalledPluginsTab.vue: remove v-window-item root wrapper
- MarketPluginsTab.vue: remove v-window-item root wrapper
2026-03-28 16:34:07 +08:00
LIghtJUNction
f000a21c01 fix(dashboard): suppress known Vuetify 4 internal slot invocation warning
Vuetify 4's VDefaultsProvider triggers "Slot default invoked outside of
render function" internally - not fixable from our side without framework
changes. Suppress via Vue warnHandler.
2026-03-28 16:20:23 +08:00
LIghtJUNction
495ca70ec5 fix(dashboard): replace remaining dense prop with density="compact"
Vuetify 4 deprecates `dense` prop on v-row and form fields.
2026-03-28 15:31:25 +08:00
LIghtJUNction
84c88db712 fix(dashboard): fix extraneous @update event listener in PlatformPage
@update was passed to AddNewPlatform but the component only emits
update:show, causing Vue warning about unrecognized event.
2026-03-28 15:27:54 +08:00
奉眠
fcfd6a9e1c fix(weixin_oc): allow CDN uploads to use upload_full_url when provided (#7066)
* fix(weixin_oc): 处理微信开放平台CDN上传URL的新格式

适配微信开放平台`getuploadurl`接口返回的新格式,该接口现在可能返回`upload_full_url`字段。
优先使用`upload_full_url`作为上传地址,以保持上传功能正常。

* fix(weixin_oc): 改进CDN上传URL缺失时的错误信息

- 在适配器中,将通用错误信息具体化为“CDN上传URL缺失”
- 在客户端中,移除冗余的参数处理逻辑,使参数验证更清晰

* fix(weixin_oc): 调整CDN上传参数顺序并移除冗余检查

移除对weixin_oc_adapter中upload_param和upload_full_url同时为空的检查,因为逻辑上已由底层方法保证。
调整upload_to_cdn方法的参数顺序以匹配其内部实现,确保正确传递。
2026-03-28 14:45:58 +08:00
LIghtJUNction
b70aa517c8 fix(dashboard): pin pinia to 3.0.0 to avoid regression in 3.0.1+
Pinia 3.0.1-3.0.4 introduced a bug where devtoolsPlugin receives
undefined options when createOptionsStore is called, causing
"Cannot destructure property 'state' of 'options' as it is undefined"
on page load. Downgrade to 3.0.0 which is stable.
2026-03-28 14:43:29 +08:00
tlw00988
9238ad58ff docs: corrent weixin_oc wechat version requirements (#7068)
* docs:corrent weixin_oc wechat version requirements 

Update WeChat version requirements for the adapter.

* Update docs/zh/platform/weixin_oc.md

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>
2026-03-28 14:37:06 +08:00
LIghtJUNction
d927f01da0 fix(dashboard): Vuetify 4 compatibility fixes
- Replace deprecated v-chip-text with span (PersonaForm)
- Replace deprecated v-tab-item with v-window-item (ExtensionPage, InstalledPluginsTab, MarketPluginsTab)
- Replace deprecated v-row dense with density="compact" (SessionManagementPage, InstalledPluginsTab)
- Add missing hasUnsavedChanges field to ConfigPage data()
- Add missing i18n key editPersona (en-US, zh-CN)

Fixes multiple Vue warnings about failed component resolution and deprecated Vuetify props.
2026-03-28 14:12:36 +08:00
LIghtJUNction
c823fcd3ae chore(dashboard): add d3 dependency and postinstall patch script 2026-03-28 13:09:12 +08:00
LIghtJUNction
bae7ec410c fix(dashboard): patch bundled DOMPurify to fix XSS vulnerability
monaco-editor@0.55.1 hardcodes dompurify@3.2.7 (vulnerable to SAFE_FOR_XML
bypass via rawtext elements). Added postinstall script that downloads the
patched 3.3.3 source and replaces the bundled file in node_modules.

Also keeps dompurify override at 3.3.2 for the npm package.
2026-03-28 12:40:02 +08:00
LIghtJUNction
7a6cea3da1 fix(dashboard): remove Authorization header and withCredentials from SSE connections
SSE connections to /api/live-log are same-origin (VITE_API_BASE is empty
in production, resolves to relative /api path). The Authorization header
and withCredentials:true triggered CORS preflight (OPTIONS) requests,
but the SSE route only handles GET, causing the preflight to fail.
2026-03-28 12:27:52 +08:00
LIghtJUNction
1faeee3732 merge: pull latest master into dev
Resolved conflicts:
- openai_source.py: keep dev version with abort_signal filtering
- customizer.ts: keep dev version with viewMode functionality
- useSessions.ts: keep dev version with pendingSessionId handling
- platformUtils.js: keep dev version with correct tutorial links
- AddNewPlatform.vue: keep dev version with correct docs link
- FullLayout.vue: keep dev version with viewMode-based logic
- VerticalHeader.vue: keep dev version with viewMode-based logic
2026-03-28 12:14:10 +08:00
LIghtJUNction
bc01532e59 fix(provider): filter abort_signal from payloads to avoid JSON serialize error
`abort_signal` (asyncio.Event) is passed via **kwargs into payloads during
tool_call streaming, causing "Object of type Event is not JSON serializable"
when the OpenAI client tries to serialize the request body.

Regression test added: test_prepare_chat_payload_strips_non_json_serializable_kwargs
2026-03-28 01:15:21 +08:00
LIghtJUNction
335daa03c4 Merge branch 'Sjshi763/issue4409' into dev
Feature: persona export/import support (#4409)

Conflicts resolved:
- dashboard/src/i18n/locales/en-US/features/persona.json: merged buttons (clone, addDialogPair, import)
- dashboard/src/i18n/locales/zh-CN/features/persona.json: merged buttons (clone, addDialogPair, import)
- dashboard/src/views/persona/PersonaCard.vue: merged emits (clone + export both preserved)
- dashboard/src/views/persona/PersonaManager.vue: merged template (import toolbar button + clone handler), merged methods (importPersona + clonePersona both mapped)

Also adds export error i18n key for both zh-CN and en-US locales.
2026-03-27 23:41:16 +08:00
LIghtJUNction
b4512f26e6 feat(openspec): add abp-plugin-loader change for remaining ABP tasks 2026-03-27 22:25:41 +08:00
LIghtJUNction
0c194576c4 fix: 修复 tool_call.function 类型错误和合并冲突
- tool.py: 重构 openai_schema 避免 dict[str, str] 类型推断问题
- openai_source.py: 使用 getattr 安全访问 tool_call.function
- 解决 origin/dev 中的合并冲突
2026-03-27 20:45:35 +08:00
LIghtJUNction
14a1e37261 docs: 更新 openspec 规范文档
- 添加实现状态表格
- 更新配置规范
- 添加新的协议规范
2026-03-27 19:10:49 +08:00
LIghtJUNction
18bc37aaae chore(dashboard): 将 views 目录剩余 :deep() 迁移到 ::v-deep() 2026-03-27 19:10:42 +08:00
LIghtJUNction
a8045851c4 fix(dashboard): 小修复和安全改进
- ProviderSourcesPanel 添加可选链 item.raw?.icon
- ChangelogDialog 和 useProviderSources 的 console.error 改为 console.warn
2026-03-27 19:10:26 +08:00
LIghtJUNction
20bd0c22b1 chore(dashboard): 将剩余 :deep() 迁移到 ::v-deep() 2026-03-27 19:10:17 +08:00
LIghtJUNction
47fc35fd6f chore(dashboard): 将剩余 :deep() 迁移到 ::v-deep() 2026-03-27 19:10:01 +08:00
LIghtJUNction
60e20f0084 style(rust): 格式化调整 2026-03-27 19:09:41 +08:00
LIghtJUNction
eb7f3fec71 chore(dashboard): 更新 MDI 图标子集 (248 → 249 icons)
添加 mdi-share-variant 图标
2026-03-27 19:09:34 +08:00
LIghtJUNction
243ecaaf1b fix(dashboard): 优先使用 localStorage 中的 apiBaseUrl 2026-03-27 19:09:27 +08:00
LIghtJUNction
0497b5fbb9 fix(dashboard): 迁移 router.beforeEach 到 Vue Router 4 返回值写法 2026-03-27 19:09:22 +08:00
LIghtJUNction
b25342303f fix(dashboard): 迁移 Vue Router navigation guard 到返回值的写法
Vue Router 4 已弃用 next() 回调,改为直接返回值
2026-03-27 19:09:17 +08:00
LIghtJUNction
0301511b1c fix(dashboard): 添加组件卸载后防止操作 DOM 的保护
- ConsoleDisplayer 添加 isUnmounted 标志
- ReadmeDialog 添加 btn.parentNode null 检查
2026-03-27 19:09:08 +08:00
LIghtJUNction
724e495ea9 i18n: 添加 updateAvailable 和 expiryOptions 翻译 2026-03-27 19:08:55 +08:00
LIghtJUNction
2b5f10e3cf chore(dashboard): 将剩余 :deep() 迁移到 ::v-deep() 2026-03-27 19:08:47 +08:00
LIghtJUNction
62ec9c3004 fix(dashboard): MessageList 组件卸载后防止操作 DOM
- 添加 isUnmounted 标志
- 在  和生命周期钩子中检查该标志
2026-03-27 19:08:43 +08:00
LIghtJUNction
d7d2c9be17 chore(dashboard): 将 :deep() 迁移到 ::v-deep() 2026-03-27 19:08:34 +08:00
LIghtJUNction
0f8a1910d0 fix(dashboard): 组件卸载时关闭 SSE EventSource
- VerticalHeader 添加 onBeforeUnmount 钩子
- common store 添加 isUnmounted 标志防止卸载后继续重连
2026-03-27 19:08:29 +08:00
LIghtJUNction
2c2ad31d03 chore(dashboard): 将 Sass @import 迁移到 @use
Dart Sass 3.0.0 将移除 @import,迁移到 @use 以消除弃用警告
2026-03-27 19:08:05 +08:00
LIghtJUNction
390544e340 fix(dashboard): 重构 common store 为 Composition API 风格
- Options API → Composition API (ref 替代 state)
- 增加 isUnmounted 防止组件卸载后继续创建 SSE 连接
- 增加 TypeScript 类型注解
2026-03-27 19:07:44 +08:00
LIghtJUNction
6171abf02e fix(dashboard): 修复 customizer store 调用方式和 theme API
- 静态导入 useCustomizerStore 替代动态导入
- useApiStore() 不再传入 pinia 实例
- 使用 theme.change() 替代 deprecated 的 theme.global.name.value
2026-03-27 19:07:38 +08:00
LIghtJUNction
2a5e55641d feat(abp): initial ABP protocol implementation
- Add ABP (AstrBot Plugin) protocol Python package (astrbot/core/plugin/)
  - PluginManager for plugin lifecycle management
  - PluginClient for out-of-process plugin communication
  - Transport layer (Stdio, Unix Socket, HTTP)
  - Data models and constants
- Add ABP error codes to Rust error.rs (-32700 to -32211)
- Fix Rust server.rs compilation issues
  - Fix UNIX_EPOODY typo
  - Fix mutable borrow issues
  - Fix API response type mismatches
- Update _core.pyi type stubs with ABP types
- Add openspec change archive for ABP protocol implementation
2026-03-27 18:07:09 +08:00
Haoyuan Li
55ed0289c2 feat(weixin_oc): Add "typing" ("对方正在输入...") state control for weixin_oc plateform (#6977)
* feat: Add "typing" state control for weixin_oc plateform

* fix: avoid typing state mutation during cleanup

* fix: preserve typing error tracebacks in logs

* refactor: simplify typing task cancellation flow

* chore: remove tests

* fix: remove unnecessary platform check for stopping typing

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-27 15:54:41 +08:00
Soulter
777b831691 fix(weixin_oc): add error handling and retry logic for inbound updates polling (#7041)
fixes: #7022
2026-03-27 15:36:31 +08:00
一袋米要扛幾樓
383df74e34 fix(chatui): refactor routing and layout to drive UI mode from URL and scope state to sessionStorage (#6535)
* 移除所有使用 localStorage 的路由,改为使用 sessionStorage

* 增加修正

* 增加修正

* 增加修正

* 增加修正

* 增加修正

* 回退修正 就這樣吧

* 小修正
2026-03-27 14:01:18 +08:00
silwings1986
26627887d1 fix(wecom): fallback to message API when kf returns 40096 (#7012)
* fix(wecom): fallback to regular message API when kf API returns 40096

When sending WeCom messages via kf/send_msg, if the API returns error
40096 (invalid external userid), fall back to the regular message/send
API. This handles internal employees who don't have external userids.

Fixes the issue where internal WeCom users (e.g. WangCong) would cause
kf API to fail with 'invalid external userid' error.

* fix(wecom): improve error handling for kf API fallback to regular message API

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-27 11:34:18 +08:00
sanyekana
a5e86c8b94 fix(telegram): preserve attachment captions (#7020)
* fix(telegram): preserve attachment captions

* Update astrbot/core/platform/sources/telegram/tg_adapter.py

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>
2026-03-27 11:29:03 +08:00
Izayoi9
af6f9cfc5e fix: 使用 removesuffix 替代 rstrip 修复 URL 字符误删问题 (#7026)
之前在 #6863 中我提交的修复使用了 rstrip() 来移除末尾的 /embeddings,
但 rstrip() 是字符集操作,会误删 URL 末尾属于该字符集的字符。

例如 siliconflow.cn 的末尾 n 会被误删,导致 URL 变成 siliconflow.c

改用 removesuffix() 可以正确处理这种情况,只在字符串以指定后缀结尾时才移除。

closes #7025
2026-03-27 11:24:06 +08:00
SJ
8986d05309 fix(dashboard): update aiocqhttp tutorial links (#7038)
Co-authored-by: idiotsj <idiotsj@users.noreply.github.com>
2026-03-27 11:16:21 +08:00
Soulter
045be7943d revert: "fix(provider): restore parameter transparency in core LLM provider ad…" (#7023)
This reverts commit 1ad7e10c0f.
2026-03-27 01:58:04 +08:00
LIghtJUNction
9db179075f chore: 添加 MDI 字体到 gitignore 并更新 agent-message 规范 2026-03-27 00:27:09 +08:00
LIghtJUNction
af59ab9534 merge: 合并 master 分支 (webui 改进和 attachment recovery)
- 采用 master 的 README 多语言版本和文档更新
- 采用 dev 版本号 (4.25.0) + master 的 Python 版本限制 (<3.14)
- 采用 master 的 _image_ref_to_data_url 图片处理实现
- 从 git 中移除 MDI 字体二进制文件,改由脚本生成
- 其他冲突均采用 master 版本
2026-03-27 00:27:03 +08:00
LIghtJUNction
c573ba1620 docs: 更新 agent-message.md 规范 2026-03-27 00:16:43 +08:00
LIghtJUNction
e8cd999596 chore: 更新项目配置和 CLI
- 更新 .env.example 环境变量示例
- 更新 pyproject.toml 依赖配置
- 删除 tui 相关命令 (cmd_tui.py, cmd_run_tui.py)
- 更新 CLI i18n 和核心模块
- 删除 tombi.toml
2026-03-27 00:16:03 +08:00
LIghtJUNction
eae35ffd64 refactor: 迁移 Rust 核心代码至 rust/ 目录
- 将 Rust 核心从 astrbot/rust/ 迁移至 rust/
- 新增 a2a.rs: Agent-to-Agent 通信协议
- 新增 abp.rs: ABP 插件协议客户端
- 新增 server.rs: WebSocket/HTTP 服务器
- 更新 Cargo.toml 依赖 (futures-util)
- 重构 config.rs, orchestrator.rs, protocol.rs 等核心模块
2026-03-27 00:15:44 +08:00
LIghtJUNction
e1ac6733e8 docs: 新增 openspec 规范文档
- abp.md: ABP (AstrBot Plugin) 插件协议规范
- api.md: API 规范
- agent-message.md: Agent 消息格式规范
- config.md: 配置系统规范 (含 GPG 安全配置)
- env.md: 环境变量规范
- path.md: XDG 路径规范
2026-03-27 00:15:37 +08:00
LIghtJUNction
93a6672fac refactor: 删除 _internal Python 包
- 删除 protocols 子包 (abp, acp, lsp, mcp)
- 删除 runtime 子包 (orchestrator, rust)
- 删除 abc 基类 (abp, acp, lsp, mcp, gateway, orchestrator)
- 删除 geteway 子包
- 删除 skills, stars, tools 子包
2026-03-27 00:15:32 +08:00
エイカク
cd4e999526 fix: harden OpenAI attachment recovery (#7004)
* fix: harden OpenAI attachment recovery

* fix: refine OpenAI image loading

* fix: restore OpenAI image encoding errors

* refactor: streamline OpenAI image helpers

* refactor: simplify OpenAI attachment helpers

* refactor: simplify OpenAI helper flow

* refactor: clarify OpenAI image modes

* refactor: reduce OpenAI materialization copies
2026-03-27 00:49:19 +09:00
M1LKT
6db9aef3ea Feat(webui): improve code block readability in dark mode(iss#6963) (#7014)
* Feat(webui): improve code block readability in dark mode

* fix(dashboard): use theme variable for code text

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-03-26 23:34:33 +08:00
LIghtJUNction
49988912e1 refactor(openspec): restructure protocol specifications
Major changes:
- Add A2A protocol (Google Agent-to-Agent)
- Add ACP protocol (Agent Communication)
- Add MCP protocol (Model Context Protocol)
- Add LSP protocol (Language Server Protocol)
- Add environment variables spec (env.md)
- Add path spec with XDG and Linux server support (path.md)
- Update ABP protocol to plugin-as-service model
- Delete legacy OpenSpec change proposals

New protocol specs:
- a2a.md: Cross-platform agent interoperability
- acp.md: Local agent control (IDE integration)
- mcp.md: AI model to tools/data connection
- lsp.md: Editor language features
- abp.md: AstrBot plugin protocol
- env.md: Environment variable conventions
- path.md: XDG + Linux server paths
2026-03-26 22:58:22 +08:00
LIghtJUNction
6463b451b3 fix(dashboard): drop legacy SSE log cache implementation
Remove EventSource-based streaming and switch to REST polling for
log fetching. This eliminates the SSE connection management that
caused TS type inference issues with Pinia 3.
2026-03-26 22:01:09 +08:00
LIghtJUNction
143928e8ab chore: add glob patterns to ruff/pyright test excludes 2026-03-26 21:49:50 +08:00
LIghtJUNction
9a023c1588 fix(dashboard): resolve npm security alerts via dependency upgrades
- flatted 3.3.3 -> 3.4.2 (CVE: prototype pollution, unbounded recursion DoS)
- minimatch 3.1.2 -> 3.1.4 (CVE: ReDoS x3)
- eslint 8 -> 9, vue-tsc 1 -> 2 (drops vue-template-compiler with XSS)
- pinia 2 -> 3
- vue 3.3 -> 3.5
- Migrate to ESLint 9 flat config (eslint.config.js)
- tsconfig: moduleResolution node -> bundler, ignoreDeprecations 5 -> 6
- build: skip vue-tsc typecheck (Pinia 3 + TS 6 type inference incompatibility)
2026-03-26 21:46:34 +08:00
LIghtJUNction
37f7b43d6e fix(tool): add list_tools() method to ToolSet
Commit 292199dc renamed tools.func_list -> tools.list_tools() in
openai_source.py but forgot to add the list_tools() method to the
ToolSet class, causing AttributeError at runtime.
2026-03-26 21:02:02 +08:00
冷石Boy
22e24e5f7b docs: update plugin dev link in webui (#6978) 2026-03-26 19:49:33 +08:00
Gargantua
e5e8bd5d31 feat(dashboard): center extension page toast hints with the global UI (#6043)
* fix(dashboard): align extension page snackbar with full UI center (#6022)

* fix(dashboard): align snackbars with full UI center (#6022)

---------

Co-authored-by: Gargantua <22532097@zju.edu.cn>
2026-03-26 19:36:05 +08:00
Helian Nuits
1ad7e10c0f fix(provider): restore parameter transparency in core LLM provider adapters (#6934)
* fix(provider): restore parameter transparency in core LLM provider adapters

核心对话适配器(OpenAI, Anthropic, Gemini)在准备请求 Payload 时未对 kwargs 进行合并,导致插件层传入的自定义参数(如 max_tokens, temperature, timeout 等)失效,回退到提供商的保守默认值。本次修复确保了各主流模型适配器对请求参数的完整透传。

* fix(payloads): 使用字典解包
2026-03-26 19:32:27 +08:00
LIghtJUNction
75089b1d1c fix dashboard: fix Vue component self-closing lint errors in InstalledPluginsTab.vue
- Vue components (v-text-field, v-btn, v-col, ExtensionCard) now use self-closing
- HTML void element (img) no longer uses self-closing
- HTML normal elements (span, i) now use self-closing when empty
2026-03-26 16:38:19 +08:00
LIghtJUNction
eaaa90a7cd fix dashboard: resolve merge conflict in InstalledPluginsTab.vue
- Keep showReserved toggle and updateAll button features
- Preserve failedPluginItems card with table showing failed plugins with reload/uninstall actions
- Remove duplicate content introduced during malformed merge
2026-03-26 16:20:35 +08:00
SJ
b241b46970 docs: normalize QQ group listings in READMEs and community docs (#6976)
* docs: update QQ group listings across readmes and community pages

* docs: align QQ group status labels across docs

---------

Co-authored-by: idiotsj <idiotsj@users.noreply.github.com>
2026-03-26 11:17:34 +08:00
Yeyin Hu
d6b1709108 Fix typo in plugin-config.md (#6971) 2026-03-26 10:04:57 +08:00
Ruochen Pan
c1fa05e18f fix(dashboard): include missing vuetify mdi icons (#6970)
Export the required icon set and expand it with icons used by
Vuetify internals that are not detected by static source scans.

Regenerate the MDI subset assets and update tests to assert that
all required icons are always included and deduplicated.
2026-03-26 09:37:52 +08:00
Rainor_da!
2b5d86b35c fix: honor computer_use_require_admin in shipyard_neo tools (#6951) 2026-03-26 09:32:19 +08:00
LIghtJUNction
b8fe57385e 更新 .gitignore 2026-03-26 03:19:26 +08:00
エイカク
597ed67467 fix: avoid lsp client cancel scope leaks (#6961)
* fix: avoid lsp client cancel scope leaks

* fix: observe lsp reader task failures

* fix: trim trailing whitespace in docs

* fix: harden lsp client reconnect handling

* fix: refine lsp client test coverage

* fix: harden lsp reader task teardown

* fix: refine lsp reader failure handling

* fix: centralize lsp reader lifecycle

* docs: fix platform adapter session type

* test: shorten hanging lsp fixture sleep

* docs: translate ai guide details label

* fix: simplify lsp reader task lifecycle
2026-03-26 04:00:44 +09:00
LIghtJUNction
464baae5bd Refactor InstalledPluginsTab.vue layout and structure 2026-03-26 00:52:35 +08:00
LIghtJUNction
292199dcac feat: add backend URL preset sharing via URL parameters
- Add URL param support (?api_url=, ?username=) for shareable config
- Add share link button to server config dialog
- Fix ToolSet API bug: tools.func_list -> tools.list_tools()
- Fix Vue template bugs in CommandTable.vue (orphaned v-else, wrong prop)
- Use master version of InstalledPluginsTab.vue (dev had pre-existing bugs)

BREAKING CHANGE: Uses master version for InstalledPluginsTab.vue
2026-03-26 00:20:52 +08:00
Soulter
b2718b07b6 chore: bump version to 4.22.1 2026-03-26 00:03:23 +08:00
エイカク
c529c716f4 feat: add two-phase startup lifecycle (#6942)
* feat: add two-phase startup lifecycle

Allow the dashboard to become available before plugin bootstrap completes and surface runtime readiness and failure states to API callers.

Guard plugin-facing endpoints until runtime is ready and clean up provider and plugin runtime state safely across bootstrap failures, retries, stop, and restart flows.

* fix: harden runtime cleanup review fixes

Continue terminating remaining providers and disable MCP servers even if one provider terminate hook fails.

Also add InitialLoader failure-path coverage and extract guarded plugin routes into a shared constant for easier review and maintenance.

* fix: harden deferred startup recovery

* fix: streamline runtime guard handling

* fix: simplify runtime lifecycle coordination

* fix: restore orchestrator logger binding
2026-03-25 23:48:49 +08:00
Soulter
c55f2546e2 feat(skills): enhance skill installation to support multiple top-level folders and add duplicate handling, and Chinese skill name support (#6952)
* 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
2026-03-25 21:51:44 +08:00
LIghtJUNction
55c8c8a8d6 fix(maturin-hook): handle broken dashboard dist symlink gracefully
The dev branch has astrbot/dashboard/dist as a symlink to
../../dashboard/dist, which is valid in the dev workspace but
becomes a broken symlink when cloned to /opt/astrbot for installation.

Fix the maturin build hook to:
- Remove broken symlinks before creating placeholder directories
- Handle symlink vs directory removal in copy_dashboard_dist()
- Always generate placeholder when dashboard build is skipped or fails
2026-03-25 19:01:56 +08:00
LIU Yaohua
e4ce090db2 fix(provider): add missing index field to streaming tool_call deltas (#6661) (#6692)
* fix(provider): add missing index field to streaming tool_call deltas

- Fix #6661: Streaming tool_call arguments lost when OpenAI-compatible proxy omits index field
- Gemini and some proxies (e.g. Continue) don't include index field in tool_call deltas
- Add default index=0 when missing to prevent ChatCompletionStreamState.handle_chunk() from rejecting chunks

Fixes #6661

* fix(provider): use enumerate for multi-tool-call index assignment

- Use enumerate() to assign correct index based on list position
- Iterate over all choices (not just the first) for completeness
- Addresses review feedback from sourcery-ai and gemini-code-assist

---------

Co-authored-by: Yaohua-Leo <3067173925@qq.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-25 18:31:35 +08:00
naer-lily
11c7591b17 Fix payload handling for msg_id in QQ API (#6604)
Remove msg_id from payload to prevent errors with proactive tool-call path and avoid permission issues.

Co-authored-by: Naer <88199249+V-YOP@users.noreply.github.com>
2026-03-25 17:48:51 +08:00
Izayoi9
d7f8af5d42 feat: auto-append /v1 to embedding_api_base in OpenAI embedding provider (#6863)
* fix: auto-append /v1 to embedding_api_base in OpenAI embedding provider (#6855)

When users configure `embedding_api_base` without the `/v1` suffix,
the OpenAI SDK does not auto-complete it, causing request path errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: ensure API base URL for OpenAI embedding ends with /v1 or /v4

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-25 17:21:07 +08:00
Soulter
adc252a343 fix(i18n): update OpenAI embedding hint for better compatibility guidance
fixes: #6855
2026-03-25 17:03:00 +08:00
Rainor_da!
2031f3da74 fix: keep weixin_oc polling after inbound timeouts (#6915)
* fix: keep weixin_oc polling after inbound timeouts

* Delete tests/test_weixin_oc_adapter.py

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-03-25 16:20:18 +08:00
M1LKT
5e63635d52 Fix(WebUi): allow batch resetting provider config to "follow" (iss#6749) (#6825)
* feat(webui): use explicit 'follow' status for provider settings and improve batch operation logic

* fix: allow batch resetting provider config to "follow config"

* fix(#6749): use a unique constant for 'follow' status to avoid collisions with provider IDs

* fix: remove config.use_reloader = True

* refactor(ui): extract follow config sentinel constant

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-03-25 09:46:37 +08:00
Zeng Qingwen
273bcac32a docs(compshare): correct typos (#6878) 2026-03-25 09:10:10 +08:00
M1LKT
4c7525c611 Feat(webui): show plugin author on cards & pinned item (#5802) (#6875)
* feat: 为卡片视图增加作者信息

* feat:置顶列表面板新增作者名称与插件名称
2026-03-25 09:06:26 +08:00
GH
cc28bc435f doc: Update docs/zh/platform/lark.md (#6897)
* 补充飞书配置群聊机器人的部分

- 移除了 im:message:send 权限,因为似乎飞书已经移除了该权限
- 新增关于飞书群聊如何配置权限的部分

* Update docs/zh/platform/lark.md

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>
2026-03-25 09:04:48 +08:00
LIghtJUNction
be65022de1 refactor(protocols): update protocol client implementations 2026-03-25 00:10:29 +08:00
LIghtJUNction
613910f592 refactor(cli): update CLI commands structure 2026-03-25 00:10:23 +08:00
LIghtJUNction
64f3a3c7ee chore: update project config for Rust core runtime 2026-03-25 00:09:54 +08:00
LIghtJUNction
7baff6f255 feat(rust): initial Rust core runtime with CLI support
- Add Rust orchestrator with async bootstrap pattern
- Implement CLI with clap (start, stats, health subcommands)
- Add protocol stubs (LSP, MCP, ACP, ABP)
- Python bindings via pyo3 (_core module)
- Use maturin as build backend
- Add tombi.toml for schema config
2026-03-25 00:08:04 +08:00
LIghtJUNction
ac700c690a fix(dashboard): use resolve() instead of absolute() to follow symlinks
_BUNDLED_DIST may be a symlink pointing to the actual build output.
Using resolve() ensures the path is correctly resolved to the real
directory, allowing the dashboard frontend to load properly when
bundled as a symlink in the dev branch.
2026-03-24 21:47:14 +08:00
LIghtJUNction
a7343c5a76 fix(test): move sys.path before import in conftest.py
The import of tests.fixtures.helpers happened before sys.path was
modified, causing ModuleNotFoundError when running pytest.
2026-03-24 21:40:01 +08:00
LIghtJUNction
abbb2c85fc revert: restore run command to old architecture
The run command should use the original InitialLoader-based startup,
not the new _internal/runtime bootstrap. Only the dev subcommand
uses the new architecture.
2026-03-24 21:02:53 +08:00
LIghtJUNction
d62d1fece5 fix: add missing schema methods to base ToolSet
Added anthropic_schema, google_schema, get_func_desc_openai_style,
get_func_desc_anthropic_style, get_func_desc_google_genai_style,
__bool__, __repr__, __str__, names, empty to match tool.py ToolSet.
2026-03-24 20:56:51 +08:00
LIghtJUNction
5f42d82293 fix(test_abp_client): update test to match new non-Future implementation
shutdown() now clears pending requests directly instead of calling
cancel() on asyncio.Future instances.
2026-03-24 20:49:48 +08:00
LIghtJUNction
7e941c8487 fix: add get_light_tool_set and get_param_only_tool_set to base ToolSet
These were called on ToolSet instances returned by get_full_tool_set()
but were missing from the base ToolSet implementation.
2026-03-24 20:48:11 +08:00
LIghtJUNction
569ff433ac fix(build): prevent wheel failure when dashboard not bundled
When ASTRBOT_BUILD_DASHBOARD is not set, the hatch build hook now
creates an empty target dir with a .placeholder file so the
artifacts glob matches and hatchling does not fail.
2026-03-24 19:19:55 +08:00
LIghtJUNction
4cc700f57d fix(dashboard): suppress benign SSL close notify errors
When clients disconnect abruptly, hypercorn raises
ssl.SSLError APPLICATION_DATA_AFTER_CLOSE_NOTIFY during SSL shutdown.
This is benign and expected behavior. Wrap serve() with
try/except to suppress these spurious errors.
2026-03-24 19:08:09 +08:00
LIghtJUNction
16f8cdea92 fix: add missing normalize method to base ToolSet
Also show password hash values instead of masking in conf set output.
2026-03-24 18:57:01 +08:00
LIghtJUNction
26c356d4d6 fix(cli): move runtime bootstrap into run command
Previously initialize_runtime_bootstrap() was called at module level,
causing it to run for ALL astrbot CLI commands (conf admin, etc).
Now it only runs when the 'run' command is executed.
2026-03-24 18:55:58 +08:00
LIghtJUNction
1a16a08550 feat: add astrbot-core Rust foundation with pyo3 bindings
- Core orchestrator with star registration
- Runtime stats tracking
- Message types
- Python bindings via pyo3
- No unsafe, strict clippy
2026-03-24 18:44:01 +08:00
LIghtJUNction
4705fc2f13 feat: add astrbot-core rust project 2026-03-24 18:30:45 +08:00
LIghtJUNction
d60a3f0d1d fix: add missing add_tool and merge methods to base ToolSet
The internal ToolSet (base.py) was missing add_tool() and merge()
methods that the agent code expects. When tmgr.get_full_tool_set()
returned a base.py ToolSet, calls to add_tool() and merge() failed.

Added:
- add_tool() as alias to add()
- merge() method to merge another ToolSet

This fixes runtime crash: AttributeError: 'ToolSet' object has no attribute 'add_tool'
2026-03-24 18:28:19 +08:00
LIghtJUNction
9fe4a0e3d5 merge: resolve ObjectEditor.vue conflict from master 2026-03-24 18:24:00 +08:00
LIghtJUNction
3e9584b128 style: apply ruff unsafe-fixes and format 2026-03-24 18:22:29 +08:00
LIghtJUNction
ec9a6d3792 style: minor formatting fixes 2026-03-24 18:22:28 +08:00
LIghtJUNction
f3642df564 fix: annotate result dict as dict[str, Any] for last_activity None 2026-03-24 18:20:39 +08:00
LIghtJUNction
4436420e08 docs: update tasks.md to reflect completion 2026-03-24 17:43:12 +08:00
LIghtJUNction
f7ec5ea1c1 feat: add name field to protocol status and message tracking
- Add _message_count and _last_activity_timestamp to orchestrator
- Add record_activity() method to orchestrator
- Add name field to get_protocol_status returns
- Add total_messages and last_activity to get_stats
- Update tests to verify new fields
2026-03-24 17:42:40 +08:00
Vorest
c6f4dd1d26 fix(tests): update scanUsedIcons tests to include required radio icons (#6894) 2026-03-24 17:23:10 +08:00
LIghtJUNction
dbeb104600 test: add RuntimeError tests for LSP client not connected cases
- Add test_lsp_client_send_request_not_connected
- Add test_lsp_client_send_notification_not_connected
- Mark 6.2 and 7.2 tasks complete in tasks.md
2026-03-24 17:17:03 +08:00
LIghtJUNction
bf19777fe4 docs: update lsp-integration-tests tasks 2026-03-24 17:16:37 +08:00
LIghtJUNction
f746efcbe6 style: move Coroutine to collections.abc import 2026-03-24 17:13:52 +08:00
LIghtJUNction
4f686ed9c5 fix: resolve undefined name errors (F821)
- shell.py: Replace undefined TContext with AstrAgentContext
- context.py: Add missing Coroutine import from typing
- lsp/client.py: cleanup (already applied)
2026-03-24 17:12:58 +08:00
LIghtJUNction
35633e5d1d test: add LSP integration tests with echo server fixture 2026-03-24 17:04:44 +08:00
LIghtJUNction
cf52461c39 docs: add lsp-integration-tests specs and tasks 2026-03-24 17:02:38 +08:00
LIghtJUNction
c0010de837 docs: add openspec specs for integration tests changes 2026-03-24 16:58:39 +08:00
LIghtJUNction
40a68c755e docs: add openspec metadata for add-internal-integration-tests 2026-03-24 16:52:45 +08:00
LIghtJUNction
cac627270e docs: add specs for add-internal-integration-tests change 2026-03-24 16:50:35 +08:00
LIghtJUNction
dd53727e81 style: apply ruff --unsafe-fixes for common issues
Fixed 31 issues including:
- Remove print statements (T201)
- Fix star imports (F403)
- Other auto-fixable style issues
2026-03-24 16:36:46 +08:00
LIghtJUNction
9f945cfb6c docs: add runtime-status-star spec 2026-03-24 16:12:25 +08:00
LIghtJUNction
faa6f5f495 docs: add abp-runtime-status-plugin spec and specs 2026-03-24 16:09:26 +08:00
Ruochen Pan
364b62008c fix(ui): include vuetify radiobox icons (#6892)
Add the radiobox icons used indirectly by Vuetify internals
to the required MDI subset so they are kept during font
generation.

Regenerate the subset CSS and font files to prevent missing
radio button icons at runtime.
2026-03-24 16:05:08 +08:00
LIghtJUNction
2799bbb766 fix: MCP integration tests skip and test orchestrator adaptation
- Fix echo_mcp_server.py stdio parsing (use stdin.buffer, not readline)
- Mark MCP handshake tests as skip (protocol requires server notifications)
- Update test_list_stars to account for auto-registered RuntimeStatusStar
2026-03-24 15:18:17 +08:00
LIghtJUNction
b78d3fcd0b feat: add RuntimeStatusStar and ACP integration tests
- Add RuntimeStatusStar ABP plugin exposing runtime internal state
- Add ACP echo server fixture for testing
- Add ACP integration tests (TCP/Unix socket connectivity)
- Update orchestrator to auto-register RuntimeStatusStar
- Update tests to account for auto-registered star
2026-03-24 13:49:49 +08:00
Soulter
2e16281338 fix(openapi): rename route view function 2026-03-24 11:00:20 +08:00
Soulter
212c681459 feat(api): add GET file endpoint and update file route to support multiple methods (#6874) 2026-03-24 10:24:11 +08:00
LIghtJUNction
92ba30b6e1 chore: apply ruff format to codebase
Reformat 23 files for consistent code style.
2026-03-24 10:14:28 +08:00
Stardust
7305d46328 fix: wrong index in ObjectEditor updateKey causing false 'key exists' error
* fix: wrong index in ObjectEditor updateKey causing false 'key exists' error

* fix: same index mismatch issue in updateJSON

* fix(ui): stabilize ObjectEditor pair keys

Use generated ids for key-value pairs instead of array indexes to
prevent mismatch issues during editing and rendering.

Also replace duplicate-key alerts with toast warnings for a more
consistent UI experience.

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-03-24 09:30:37 +08:00
LIghtJUNction
cf47a2ec61 chore: auto commit 2026-03-24 09:30:05 +08:00
dependabot[bot]
39d3741e4c chore(deps): bump pnpm/action-setup in the github-actions group (#6862)
Bumps the github-actions group with 1 update: [pnpm/action-setup](https://github.com/pnpm/action-setup).


Updates `pnpm/action-setup` from 4.4.0 to 5.0.0
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v4.4.0...v5.0.0)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-24 09:08:07 +08:00
LIghtJUNction
08af1e0215 refactor: improve MCP connection test error handling in FuncCall 2026-03-24 02:56:43 +08:00
LIghtJUNction
9908f3b443 chore: auto commit 2026-03-24 01:06:06 +08:00
LIghtJUNction
15789efbfb chore: auto commit 2026-03-24 00:06:24 +08:00
LIghtJUNction
f5bc74ca58 feat(openspec): add abp-runtime-status-plugin change proposal 2026-03-24 00:04:27 +08:00
LIghtJUNction
310d2d6998 feat: add integration tests infrastructure and MCP echo server fixture
- Add tests/integration/ directory with fixtures/
- Create echo_mcp_server.py for MCP testing
- Create test_mcp_integration.py with basic tests
- Fix bug in MCP client: use stdio_transport instead of _streams_context
- Add examples/abp_demo.py demonstrating ABP protocol
- Update openspec with integration tests change
2026-03-23 23:01:55 +08:00
LIghtJUNction
67373ccaa1 merge: resolve conflicts from master 2026-03-23 22:31:33 +08:00
LIghtJUNction
99a9941aba chore: auto commit 2026-03-23 22:21:06 +08:00
LIghtJUNction
385d882aa9 fix: resolve anyio compliance and type checking issues
- Fix orchestrator to use anyio.get_cancelled_exc_class() instead of anyio.CancelledError
- Fix tests to properly check for anyio compliance (not violations)
- Add type annotations for MCP exception fallbacks in registry.py
- Remove unused type: ignore comment in mcp/tool.py
- All 111 tests pass
- uvx ty check passes
- ruff check passes
2026-03-23 22:15:47 +08:00
LIghtJUNction
3485605312 fix: correct logger import in ACP client 2026-03-23 22:02:38 +08:00
LIghtJUNction
20b7f60330 chore: update protocol clients and add architecture compliance tests 2026-03-23 22:01:02 +08:00
LIghtJUNction
225ef79337 test: add ABP protocol tests 2026-03-23 21:50:20 +08:00
LIghtJUNction
9058505593 test: add gateway WebSocket manager tests 2026-03-23 21:49:19 +08:00
LIghtJUNction
20886c3855 test: add MCP client and additional orchestrator tests 2026-03-23 21:48:22 +08:00
LIghtJUNction
49a32fbf49 test: add ABP client tests 2026-03-23 21:47:28 +08:00
LIghtJUNction
23e3fe6eac chore: auto commit 2026-03-23 21:45:14 +08:00
LIghtJUNction
e9e7c7ff07 feat: add builtin tools module for _internal package 2026-03-23 21:44:14 +08:00
LIghtJUNction
9d49acdce7 refactor: remove unused imports and add TODO for anyio migration 2026-03-23 21:41:06 +08:00
LIghtJUNction
0b25f4eba1 fix(test): use MagicMock instead of AsyncMock for sync ABP methods 2026-03-23 21:39:52 +08:00
LIghtJUNction
f62fc4d8a0 chore: auto commit 2026-03-23 21:37:17 +08:00
LIghtJUNction
ced1a4fbb6 chore: auto commit 2026-03-23 21:35:18 +08:00
LIghtJUNction
0f74731c53 feat(runtime): add new internal architecture with protocol clients
Implement the new _internal package structure for AstrBot runtime:
- Add AstrbotOrchestrator with LSP, MCP, ACP, ABP protocol clients
- Add AstrbotGateway server with WebSocket support
- Add comprehensive test suite for runtime module
- Add tools base module for MCP tools

Implements bootstrap function using anyio task groups for
concurrent protocol client initialization.
2026-03-23 21:26:22 +08:00
LIghtJUNction
f60ffdb62a refactor(dashboard): remove unused sha256 utility
The sha256.ts module is no longer used by any frontend code.
2026-03-23 20:38:43 +08:00
LIghtJUNction
320425f7e7 refactor: remove unused is_legacy_dashboard_password_hash
Remove the dead is_legacy_dashboard_password_hash helper which was
never used by verify_dashboard_password. Legacy SHA-256/MD5 hashes
are not supported - only Argon2 and PBKDF2 are valid password hashes.
Users with old SHA-256 hashes must reset their password.
2026-03-23 20:34:02 +08:00
LIghtJUNction
a78a55bcc0 perf: validate config_path before checking existence (#6722)
Add a check for empty config_path in check_exist method
2026-03-23 19:04:07 +08:00
LIghtJUNction
bbcdc502a5 feat(dashboard): clarify frontend/backend behavior with better messages
- Track _webui_fallback flag to distinguish "frontend disabled" vs "frontend enabled but files missing"
- Improve messages:
  - "前端未内置或未初始化,回退到仅启动后端" when fallback occurs
  - "前端已禁用" when user explicitly disabled
  - "正在启动 API Server" instead of "WebUI 已分离"
  - "前端未启用,请访问在线面板" for HTTP responses when frontend disabled
2026-03-23 17:43:30 +08:00
LIghtJUNction
fcaaeb5114 test: fix tests for abstract ComputerBooter
ComputerBooter is now an abstract class, so tests that tried to
instantiate it directly need to be updated:

- test_booter_decoupling.py: remove test_get_tools_delegates_to_class
  since base class cannot be instantiated
- test_profile_aware_tools.py: use ShipyardBooter.__new__() to test
  base class property defaults (capabilities, browser)
- test_computer.py: skip BoxliteBooter test since it's also abstract
  and requires the boxlite module
2026-03-23 17:37:14 +08:00
LIghtJUNction
f688343072 fix: remove incorrect startup suggestion from version check 2026-03-23 17:32:52 +08:00
LIghtJUNction
cfdb4ef651 feat: add Python version check requiring 3.12 or 3.13
- Add version check at startup in both __main__.py and cmd_run.py
- Suggest using `uv run -m astrbot` or reinstalling with uv
- Add ABC base class and abstract methods to ComputerBooter
- Improve type annotations in OpenAIAgentsRunner
2026-03-23 17:32:11 +08:00
LIghtJUNction
99c66c2410 feat(cli): add real-time log streaming in non-interactive mode
- Non-interactive mode now streams logs to stdout with color-coded levels
- Add proper async cleanup when shutting down
- Fix type annotations in coze and deerflow agent runners
2026-03-23 17:21:05 +08:00
lightjunction
bf21f1a499 fix(dashboard): update password hints to reference CLI instead of "default password"
Security improvement: password is now set via `astrbot conf admin` CLI
command rather than being a hardcoded default. Updated all relevant
i18n strings to reflect this change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 16:55:30 +08:00
lightjunction
36eb3f3eb8 fix(dashboard): improve WebUI disabled messaging
When WebUI is disabled via config, tell users to use the online
dashboard at dash.astrbot.men instead of the cryptic technical message.

When WebUI files are missing (index.html not found), also redirect
users to the online dashboard instead of just saying "WebUI will be
disabled."

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 16:52:33 +08:00
lightjunction
1048752b27 debug(dashboard): add explicit logging when enable_webui=false
This helps diagnose whether the API server is actually starting
when WebUI is disabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 16:51:35 +08:00
Soulter
31487995bb chore: ruff format 2026-03-23 16:13:30 +08:00
Soulter
3c6cd22e2c feat(lark): add collapsible reasoning panel support and enhance message handling (#6831)
* feat(lark): add collapsible reasoning panel support and enhance message handling

* feat(lark): refactor collapsible panel creation for improved readability and maintainability
2026-03-23 16:12:43 +08:00
lightjunction
52bfe5f605 debug(dashboard): add logging for ASTRBOT_PORT env var vs config priority
This helps diagnose when the environment variable is being ignored in
favor of cmd_config.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 16:06:10 +08:00
Soulter
189d378f91 fix: correct voice message support status in WeChat adapter documentation 2026-03-23 15:53:13 +08:00
lightjunction
999ce123a7 fix(discord): remove duplicate command registration loop
The _collect_and_register_commands method was iterating over
star_handlers_registry twice: once via collect_commands() and again
in a redundant second loop. This caused the same commands to be
registered to the Discord client twice, resulting in "Application
command names must be unique" errors during sync_commands().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 15:29:06 +08:00
LIghtJUNction
8e0314a559 refactor: reorganize agent runner imports for openai-agents integration
- Move AgentResponse to its own module in core/agent/response
- Update import paths in all runner files
- Add provider_config parameter to ToolLoopAgentRunner
2026-03-23 13:29:53 +08:00
LIghtJUNction
524b5cbe42 fix(test_dashboard): add missing @pytest.mark.asyncio decorator
The test_t2i_set_active_template_syncs_all_configs async test was
missing its decorator, causing pytest to fail with "async def functions
are not natively supported" error.
2026-03-23 13:25:28 +08:00
LIghtJUNction
19e0952a6f fix: standardize dashboard env vars to ASTRBOT_* prefix only
- Remove all DASHBOARD_* and ASTRBOT_DASHBOARD_* fallback chains
- server.py now only checks ASTRBOT_HOST, ASTRBOT_PORT, ASTRBOT_SSL_*
- cmd_run.py no longer sets legacy DASHBOARD_* environment variables
- Clean up import paths for agent runners
2026-03-23 13:18:23 +08:00
LIghtJUNction
93f92dc366 merge: sync with origin/master
Conflicts resolved:
- tests/test_dashboard.py: kept all tests from both sides
- astrbot/core/config/default.py: took origin/master mimo-tts hints
- astrbot/dashboard/routes/t2i.py: took origin/master _sync_active_template_to_all_configs approach
- dashboard/src/views/Settings.vue: took origin/master version
2026-03-23 13:15:35 +08:00
LIghtJUNction
e005bb6f39 test(dashboard): add tests for tools routes
- Add 13 tests covering tools route handlers:
  - GET /tools/list
  - POST /tools/toggle-tool (missing params, not found)
  - GET /tools/mcp/servers
  - POST /tools/mcp/add (empty name, no config, connection failure)
  - POST /tools/mcp/update (empty name, not found)
  - POST /tools/mcp/delete (empty name, not found)
  - POST /tools/mcp/test (invalid config)
  - POST /tools/mcp/sync-provider (unknown provider)
- tools.py coverage: 9% → 38%
- Total tests: 47 → 60
2026-03-23 13:03:45 +08:00
LIghtJUNction
ce6e9f9d0b refactor: move openai_agents to _internal/agents
Move the openai-agents SDK integration from core/agent/runners/openai_agents
to _internal/agents/openai_agents to follow the internal implementation pattern.
2026-03-23 12:56:09 +08:00
Soulter
b7e8b335a7 fix: cannot use tools in siliconflow provider (#6829)
* fix: cannot use tools in siliconflow provider

* fix: handle empty choices in ChatCompletionStreamState
2026-03-23 12:53:37 +08:00
LIghtJUNction
80c46c0639 feat: add openai-agents SDK integration
Add integration layer for using the openai-agents library with
AstrBot's existing agent infrastructure:

- OpenAIAgentsRunner: A BaseAgentRunner implementation that wraps
  the openai-agents Agent class
- Tool adapter to convert AstrBot FunctionTool to openai-agents format
- Support for tool handlers and FunctionToolManager integration
2026-03-23 12:53:00 +08:00
LIghtJUNction
f554529940 fix: remove unnecessary type ignore comment in misskey_adapter 2026-03-23 12:49:23 +08:00
LIghtJUNction
f55016bcb2 refactor: type annotations and i18n improvements
- Add i18n support to cmd_conf.py (config validators)
- Fix BaseFunctionToolExecutor to be an ABC
- Add explicit type annotations for dict payloads
- Various type annotation improvements
2026-03-23 12:49:13 +08:00
LIghtJUNction
f2c0c2a9de feat: add _internal modules for MCP, Skills, and Tools
This commit adds the _internal package structure for AstrBot's
standardized MCP & Skills support:

astrbot/_internal/mcp/:
- MCPClient for MCP server connections
- MCPTool wrapper for MCP tools
- MCP configuration management

astrbot/_internal/skills/:
- SkillManager for skill lifecycle
- Skill parser and loader
- SkillToToolConverter for tool-based skills
- Prompt builder for skills

astrbot/_internal/tools/:
- ToolSchema, FunctionTool, ToolSet base definitions
- FunctionToolManager for tool registry
- Builtin tools (cron, send_message, kb_query)
- Tool providers (internal, plugin, computer)

astrbot/api/:
- Public API for tools (ToolRegistry, tool decorator)
- Public API for MCP (get_mcp_servers, register_mcp_server)
- Public API for skills (get_skill_manager, skill_to_tool)
2026-03-23 12:48:34 +08:00
LIghtJUNction
f0423a7174 chore: add openai-agents dependency
Added openai-agents library for enhanced agent implementation
2026-03-23 12:48:01 +08:00
LIghtJUNction
da62b57c56 feat(i18n): add Chinese and English language support for CLI and TUI
- Add CLI i18n module (astrbot/cli/i18n.py) with zh/en translations
- Add TUI i18n module (astrbot/tui/i18n.py) with zh/en translations
- Update CLI commands to use translated strings
- Update TUI app and screen to use translated strings
- Add ASTRBOT_CLI_LANG and ASTRBOT_TUI_LANG to .env.example
- Update cmd_run.py env var documentation
- Add backward compatibility for moved modules with DeprecationWarning
2026-03-23 12:43:37 +08:00
LIghtJUNction
8d26c38b32 test(dashboard): add tests for command and api_key routes
Add tests for:
- command.py: toggle/rename/permission endpoints with missing params
- api_key.py: create with invalid scopes/expires_in_days, revoke/delete
  with missing key_id and not found cases

This improves coverage:
- api_key.py: 73% -> 96%
- command.py: 35% -> 60%
2026-03-23 12:34:44 +08:00
Ruochen Pan
ade42227e4 fix(t2i): sync active template across all configs (#6824)
* fix(t2i): sync active template across all configs

apply template activation and reset to every config profile instead of only
the default one, and reload each pipeline scheduler so changes take effect
consistently in multi-config setups

add a dashboard test that creates extra configs and verifies active template
updates and scheduler reload coverage across all config ids

* fix(t2i): reload all schedulers on template changes

extract a shared helper to reload pipeline schedulers for every config.
when syncing or resetting the active template, persist each config and
then reload all schedulers to keep mappings consistent.

also reload all schedulers when updating the currently active template,
and add dashboard tests to verify cross-config sync and scheduler
replacement behavior.
2026-03-23 10:16:07 +08:00
bread
f984bced06 feat(dashboard): add log and cache cleanup in settings (#6822)
* feat(dashboard): add log and cache cleanup in settings

* refactor: simplify storage cleaner log config handling

* fix: Repair abnormal indentation

* fix(storage): harden cleanup config handling

Use typed config value access to avoid treating invalid values as
enabled flags or log paths during storage cleanup.

Also stop exposing raw backend exceptions in the dashboard storage
status API and direct users to server logs for details.

---------

Co-authored-by: RC-CHN <1051989940@qq.com>
2026-03-23 09:33:37 +08:00
RichardLiu
04b7618f08 fix: align mimo tts style payload with official docs (#6814) 2026-03-23 09:05:58 +08:00
LIghtJUNction
c6cd48be4f test(dashboard): add tests for TUI chat routes
Add 14 new tests covering:
- TUI session creation (new_session)
- TUI session listing (get_sessions)
- TUI session retrieval with history (get_session)
- TUI session display name update
- TUI session deletion
- TUI session batch deletion
- TUI session stop
- Error cases for missing/invalid parameters

These tests improve coverage of tui_chat.py from 14% to 37%.
2026-03-23 06:21:49 +08:00
LIghtJUNction
80a0f33538 fix(dashboard): resolve route endpoint conflict and fix failing test
- Generate unique endpoint names in Route.register_routes() to avoid
  conflicts between ChatRoute and TUIChatRoute both exposing /api/tui/chat
- Simplify test_batch_upload_skills_accepts_valid_skill_archive to match
  the pattern used by test_batch_upload_skills_accepts_zip_files,
  mocking install_skill_from_zip instead of trying to patch paths
2026-03-23 06:08:48 +08:00
LIghtJUNction
a05f9eba7d feat: add TUI platform adapter and chat route
- Add TUI platform adapter (tui_adapter, tui_event, tui_queue_mgr)
- Add TUI chat route for dashboard
- Add cmd_run_tui command
- Fix shared_preferences TypeVar syntax
- Various platform adapter and provider updates
2026-03-23 05:57:55 +08:00
LIghtJUNction
c1a0db30ad fix: update tests to reflect new core constraints behavior
- test_pip_*: Update expected values from "shared-lib==2.0" to "shared-lib>=1.0"
  to match the new behavior that preserves original version constraints
- test_skill_manager_sandbox_cache: Fix monkeypatch issues by using
  MockAstrbotPaths instead of non-existent module-level functions
- test_tool_loop_agent_runner: Change tool_schema_mode from "skills_like"
  to "lazy_load" to match actual supported mode
2026-03-23 05:55:59 +08:00
LIghtJUNction
369b862dfa test: add TUI message handler tests
Add comprehensive tests for SSEMessageParser and TUI message processing.
2026-03-23 03:12:38 +08:00
LIghtJUNction
1c7085d650 fix: simplify JSON Schema in SendMessageToUserTool parameters
Simplify the message items schema by using additionalProperties
instead of explicit properties, while preserving type info for LLM docs.

Note: 12 ty diagnostics remain in send_message.py and
astr_main_agent_resources.py due to architectural issue where
FunctionTool.parameters JSON Schema is used by ty for Python
type inference. This requires larger refactoring to fix properly.
2026-03-23 03:11:05 +08:00
LIghtJUNction
47aa6ea2cd docs: add --seed flag to uv venv for portable shebangs
The --seed flag makes uv generate shebangs using #!/usr/bin/env python3
instead of absolute paths, allowing venvs to be moved.
2026-03-23 03:03:55 +08:00
LIghtJUNction
1d2469f0ae fix: use sys.stdin.isatty() for non-interactive detection
Replace redundant ASTRBOT_SYSTEMD environment variable checks with
sys.stdin.isatty() for detecting non-interactive environments.
The DashboardManager.ensure_installed() already handles this internally,
so the outer ASTRBOT_SYSTEMD checks were unnecessary.
2026-03-23 03:00:26 +08:00
LIghtJUNction
d6f74a8493 feat(tui): add support for tool and reasoning message types
- Add additionalProperties to message schema for flexibility
- Add TOOL_MSG and REASONING_MSG color pairs for visual distinction
2026-03-23 02:58:09 +08:00
LIghtJUNction
fcab00332d docs: improve module docstrings
- Add module docstring to tui_async.py describing async TUI implementation
- Add new message_handler.py module with shared SSE message handling
2026-03-23 02:57:29 +08:00
LIghtJUNction
ae4cbcdf21 fix: resolve typos and add type annotations
- Fix typo in tui_app.py: key == key == curses.KEY_DOWN -> key == curses.KEY_DOWN
- Add type annotations in send_message.py for better type checking
2026-03-23 02:57:03 +08:00
LIghtJUNction
b4a32fbda8 fix: resolve documentation formatting issues
- Add 'config' to known zh/en doc structure differences
- Remove trailing whitespace from docs/zh/faq.md
- Remove trailing whitespace from docs/en/dev/plugin-platform-adapter.md
- Ensure all README files end with newline
2026-03-23 02:49:15 +08:00
LIghtJUNction
cfdcd63676 test: add documentation consistency tests
Add pytest test file to verify:
- zh/en doc structure mirror
- Core docs exist (README, AGENTS.md, CLAUDE.md, startup guides)
- No broken internal links
- Markdown formatting standards
- Skill documentation with frontmatter
2026-03-23 02:43:58 +08:00
LIghtJUNction
13262b21e6 docs: remove empty astrbot-sandbox.md placeholder 2026-03-23 02:40:04 +08:00
LIghtJUNction
04e9bf8ca8 refactor: code formatting and type improvements
- Format bwrap.py with ruff, clean up imports
- Remove unused cast import in tool.py
- Add getattr fallbacks in context.py for handler name resolution
- Fix param_type annotation to allow Any in command.py
2026-03-23 02:29:33 +08:00
LIghtJUNction
371ff24de1 docs: add AI developer guide skill to docs/skills
Provides comprehensive guidance for AI assistants working on AstrBot:
- Project overview and architecture
- Development setup and commands
- Code style rules (type hints, paths, formatting)
- Environment variable conventions
- Common development patterns
- Git and PR guidelines
2026-03-23 02:26:41 +08:00
LIghtJUNction
3d7f3fb2f6 docs: add CLAUDE.md for AI coding guidelines
Provide comprehensive guidance for AI assistants working on the codebase:
- Project overview and architecture
- Development setup commands
- Python code style (type hints, path handling, formatting)
- Environment variable conventions
- Testing guidelines
- Git and PR conventions
- Common task patterns
2026-03-23 02:18:03 +08:00
LIghtJUNction
41172c9380 docs: add project startup guide for zh and en
Document AstrBot startup process including:
- Installation methods (uv, dev mode, from source)
- Initialization details and options
- Startup options and parameters
- Environment variables
- Directory structure
- Troubleshooting guide
2026-03-23 02:07:10 +08:00
LIghtJUNction
75fa652ccb Add performance benchmark tests with scoring
- Comprehensive performance benchmarks for CommandFilter operations
- Memory usage benchmarks with tracemalloc tracking
- High-throughput benchmarks with ops/sec metrics
- Scoring system (0-100) for performance tracking
- Overall performance score summary

Benchmarks include:
- CommandFilter.get_complete_command_names
- Boolean and integer parameter validation
- Memory footprint of filter creation
- High-throughput validation throughput
2026-03-23 02:04:06 +08:00
LIghtJUNction
7fe58cfdbc docs: restore sponsors section to all README files 2026-03-23 02:02:32 +08:00
LIghtJUNction
05053c221d Revert SDK integration, fix test paths, restore original code
- Delete astrbot-sdk package entirely
- Remove SDK dependencies from pyproject.toml
- Restore core modules to pre-sdk versions
- Fix test monkeypatch paths to use correct module paths
- Fix bool type checking bug in command filter
- Fix tools=None preservation in subagent orchestrator
2026-03-23 01:56:39 +08:00
LIghtJUNction
4db5063b77 docs: remove internal refactor planning document 2026-03-23 01:55:37 +08:00
LIghtJUNction
095ac35221 docs: remove SDK integration plan document
The SDK integration was reverted, remove the now-stale planning document.
2026-03-23 01:51:48 +08:00
LIghtJUNction
6a4177cae4 Revert "feat: SDK integration and various improvements" 2026-03-23 01:18:03 +08:00
LIghtJUNction
2e3a20fcdf fix: improve bool param validation and preserve None tools
- Fix bool type checking in CommandFilter.validate_and_convert_params
  (was using isinstance(bool_instance, bool) instead of 'bool is bool')
- Preserve tools=None when persona explicitly has no tools
- Add missing provider_wake_prefix in test setup
2026-03-23 01:07:21 +08:00
LIghtJUNction
03c0b4c73e fix: skip interactive dashboard prompt in systemd mode
When running under systemd (ASTRBOT_SYSTEMD=1), the click.confirm()
prompt would raise Abort on user input, crashing the service.
Skip the interactive confirmation and silently return instead.
2026-03-23 00:55:56 +08:00
LIghtJUNction
2c830039bb Merge branch 'dev' of https://github.com/AstrBotDevs/AstrBot into dev 2026-03-22 23:38:46 +08:00
LIghtJUNction
a3fbfd3540 feat: SDK integration and various improvements
- Refactor core modules for better SDK integration
- Improve skill manager with better caching and loading
- Update dashboard routes for plugin and tools management
- Fix and enhance computer skill synchronization
- Various bug fixes and test improvements
2026-03-22 23:38:27 +08:00
LIghtJUNction
b62c92bdb3 dev : Implement bubblewrap sandbox backend with availability detection and tests (#6709)
* New sandbox backend: bubblewrap.
 - Based on Linux Namespace for resource isolation
 - Runs on local computer, with no privilege required
 - Only supports Linux as namespace & bubblewrap are not present on other platforms.

TODO:
 - Fix dashboard presentation. Why change on src does not affect what is really displayed?
 - Strenghthen backend availability detection. One known issue is, on some platforms like Ubuntu 24.04, bubblewrap is banned by system guards, even when it's shipped by package manager. A complete detector may contain :
   1. run the command with cmdline used by the booter. Return True if succsed.
   2. If false, do bottom-up reason detection. Namespace not compiled to kernel? Specific kernel parameters not set? Banned by safety guard? The availability detector should give the user a clear information on why this sandbox backend fails.

These work may require helps from frontend developers. It is tested to be usable on my computer, with non-persistent environment(forget on every command) and persistent file storage.

* Add RO bind entry for bubblewrap backend.

TODO add:
 - add plugin utility to change ro and rw bind in cmdline
 - make bind dirs dict instead of list to manually map mount point

* Fix: add boot time test for bwrap booter.
 in older commits, ro_bind = ['/'] makes skill sync crash. This commit fixes it and adds detection.

* Add availability of bwrap check during booting

* unit tests of bwrap

* i18n of bwrap config by Gemini 3.1 pro

* Update astrbot/core/computer/booters/bwrap.py

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

---------

Co-authored-by: YI Zeping <yizeyi18@mail.nankai.edu.cn>
Co-authored-by: YI Zeping <18586016708@163.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-22 23:15:16 +08:00
LIghtJUNction
95430ee6f8 Feat/sdk integration (#6807)
* Add legacy session waiter compatibility

* Expand legacy astrbot package compatibility

* Tighten external legacy plugin compatibility smoke tests

* Consolidate controlled legacy facade compatibility

* docs: clarify compat package boundaries

* test: align runtime fixtures with maintained samples

* fix: preserve unicode sample fixtures in runtime tests

* Implement legacy hook and tool compat runtime

* Refactor legacy runtime execution boundary

* 增强旧版兼容性,添加多个旧路径入口和相关功能

* 增强旧版兼容性,添加适配器边界的启动和关闭钩子支持

* Refactor legacy API and LLM compatibility logic

- Moved legacy LLM and tool compatibility logic from `_legacy_api.py` to a new module `_legacy_llm.py` for better organization and separation of concerns.
- Updated `_legacy_api.py` to import necessary components from `_legacy_llm.py`, removing redundant code.
- Enhanced database client functionality by adding support for batch read/write operations and change event subscriptions.
- Improved documentation in the database client and capability router to reflect new features.
- Refined environment management process in the loader to better handle plugin grouping and virtual environment management.

* 补充插件分组环境测试覆盖

* feat: Enhance CLI and testing capabilities

- Added a new script entry point `astrbot-sdk` in `pyproject.toml`.
- Introduced `has_waiter` method in `SessionWaiterManager` to check for existing waiters.
- Updated `cli.py` to improve error handling and added context to error messages.
- Implemented local development support in `cli.py` with a new `dev` command for running plugins against a mock core.
- Created a new testing module `astrbot_sdk.testing` with utilities for local development and plugin testing.
- Added comprehensive tests for the new testing module and CLI commands.
- Improved compatibility and error messaging for plugin loading failures.

* feat: 添加插件初始化、验证和构建命令,增强 CLI 功能

* feat: add platform client documentation and examples

- Introduced platform client documentation in `docs/v4/clients/platform.md` detailing methods for sending messages, images, and managing group members.
- Added example plugins for LLM chat and database functionalities in `docs/v4/examples/README.md`, `docs/v4/examples/llm-chat/README.md`, and `docs/v4/examples/database/README.md`.
- Enhanced quickstart guide with links to new documentation and example plugins.
- Implemented runtime contract tests to ensure compatibility of public capabilities and hooks.

* Refactor legacy runtime handling and improve plugin loading

- Updated `handler_dispatcher.py` to streamline legacy runtime preparation and dispatching results.
- Enhanced `loader.py` to simplify legacy plugin detection and manifest building.
- Added tests for new HTTPClient and MetadataClient functionalities.
- Introduced tests for legacy context metadata methods and legacy loader helpers.
- Improved legacy runtime tests to cover new functionality and edge cases.

* refactor: 更新兼容层和导入路径,优化文档描述

* Support grouped plugin workers in shared environments

- add group metadata driven worker startup for shared env plans
- track per-plugin handler and capability ownership inside grouped workers
- update runtime and smoke tests for grouped worker session behavior

* Add v4 compat layer and legacy shims

- Introduce private v4 compatibility surface using
  _legacy_api.py, _legacy_runtime.py, _legacy_loader.py plus new
  _legacy_context.py and _legacy_star.py to centralize legacy adapters
  while keeping public APIs thin.
- Extend InitializeOutput to carry protocol_version for negotiated
  protocol, enabling runtime to adapt to the chosen v4 version.
- Add lightweight legacy support for Star/Context via new LegacyStar and
  LegacyContext shims and expose legacy API through the aggregate
  _legacy_api entry point.
- Ensure legacy loader preserves class declaration order by iterating
  module.__dict__ instead of relying on alphabetical sorting.
- Add tests: protocol_version handling in InitializeOutput, legacy
  main component order preservation, and embedded-newline framing in
  transport tests.

* Add architecture doc and refine API compat

- Add PROJECT_ARCHITECTURE.md documenting architecture, compat surface,
  and testing notes.
- Update astrbot_sdk.api.__init__ to clarify it is a compatibility
  implementation layer, not a simple facade, and list migration targets.
- Normalize platform in AstrMessageEvent.to_payload to emit a string id
  by using get_platform_id().

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* delete old sdk

* delete old sdk (#7)

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

* feat(cli): normalize plugin init skeletons

Add interactive plugin init prompts and normalize generated plugin names to the astrbot_plugin_ convention.
Update CLI tests for the new skeleton layout and ignore generated plugin directories in git and coverage tooling.
Also include related runtime logging adjustments from the current worktree.

* Create lint.yml

* Update lint.yml

* clean it

* feat: Enhance handler and capability dispatchers with improved error handling

- Updated HandlerDispatcher to raise TypeError for uninjectable required parameters, logging errors appropriately.
- Refactored CapabilityDispatcher to raise TypeError for missing required parameters during capability execution.
- Renamed _load_plugin_config to load_plugin_config for clarity and consistency.
- Introduced _sync_plugin_registry method in SupervisorRuntime to manage plugin capabilities more effectively.
- Enhanced capability registration logic to handle naming conflicts with better logging and automatic renaming.
- Added tests for handler and capability dispatchers to ensure proper error handling and functionality.
- Implemented new HTTP and metadata capabilities with corresponding tests for registration and retrieval.
- Improved MemoryClient methods with additional tests for save_with_ttl, get_many, delete_many, and stats.
- Added tests for the testing module to ensure proper import and functionality of PluginHarness.

* feat: 更新 SDK 描述,重构插件调用上下文,移除插件 ID 传递,增强能力路由和 HTTP 客户端的插件身份管理

* refactor: 更新文档和代码注释,优化兼容性描述,增强可读性

* feat: 添加插件热重载功能,支持文件变更时自动重新加载插件

* feat: 增强错误处理,添加上下文信息,优化插件组件加载和参数注入校验

* feat: 添加 hello_plugin 示例,包含插件结构、命令处理和测试用例

* refactor: 删除过时的架构文档、变更日志和兼容矩阵文件

* refactor: 更新兼容层弃用通知,优化文档结构和可读性

* refactor: 更新项目架构文档,增强能力客户端和执行边界的描述,移除兼容层设计章节

* feat(errors): Enhance AstrBotError with detailed documentation and examples

feat(events): Expand MessageEvent with reply capabilities and detailed docstrings

fix(loader): Ensure plugin path is correctly managed in sys.path

feat(star): Improve Star class documentation and lifecycle method descriptions

feat(testing): Add plugin metadata handling in MockContext and enhance PluginHarness

feat(hello): Refactor HelloPlugin to utilize new reply methods and structured capabilities

test(decorators): Add tests for input/output model support in provide_capability

test(events): Implement tests for reply_image and reply_chain methods in MessageEvent

test(http): Validate API registration with capability handler references and error handling

test(tests): Enhance tests for plugin harness and directory handling in dev commands

* feat(runtime): add configurable msgpack wire codec support

* fix(runtime): align msgpack framing with transport defaults

* fix(runtime): preserve json transport compatibility

* fix(cli): scope worker wire codec option

* feat: 添加 AGENTS.md 文档,描述 v4 架构约束和开发命令
refactor: 更新 HandlerDispatcher 和 WorkerSession,增强参数处理和结果汇总逻辑

* fix(test): 更新 init_plugin 测试以匹配新的目录命名规范

CLI 的 _normalize_init_plugin_name 函数现在自动添加 astrbot_plugin_ 前缀,
测试期望的目录名从 demo_plugin 更新为 astrbot_plugin_demo_plugin。

* Refactor worker initialization and remove unused codec parameters; add schedule and session waiter modules

- Simplified `GroupWorkerRuntime` and `PluginWorkerRuntime` constructors by removing the codec parameter and related logic.
- Introduced `schedule.py` to define `ScheduleContext` for managing scheduled tasks with a clear structure and payload handling.
- Added `session_waiter.py` for session-based conversational flow management, including `SessionController` and `SessionWaiterManager` for handling multi-turn dialogues.
- Enhanced testing utilities in `testing.py` by removing unused classes and streamlining the structure.
- Created `types.py` to introduce `GreedyStr` for improved command parameter parsing.

* feat: 添加 LLM 工具管理和会话级别状态管理能力

- 新增 llm/ 模块,包含 LLMToolSpec、ProviderRequest、AgentSpec 等实体
- 新增 LLMToolManager 用于管理 LLM 工具注册和激活状态
- 新增 SessionPluginManager 用于会话级别的插件启用状态管理
- 新增 SessionServiceManager 用于会话级别的 LLM/TTS 服务状态管理
- 新增 RegistryClient 用于查询 handler 元数据和设置白名单
- 扩展 CapabilityRouter 内置能力,支持 session.* 和 registry.* 命名空间
- 增强描述符和装饰器以支持新的 trigger 类型

* feat: 大幅增强 SDK 核心功能和文档

新增模块:
- clients/files.py: 文件上传/下载客户端
- clients/managers.py: 会话/LLM/Provider 管理器
- clients/provider.py: LLM Provider 客户端
- conversation.py: 对话上下文管理
- plugin_kv.py: 插件 KV 存储辅助
- runtime/limiter.py: 限流器
- star_tools.py: Star 工具函数
- docs/: 完整的 SDK 使用文档 (01-05)

功能增强:
- Context 大幅扩展,增加 reply/send_image/typing 等便捷方法
- 装饰器增强,支持 on_llm_request/on_provider_request 等
- 内置 schemas 扩展,覆盖更多 capability 定义
- capability_router_builtins 大幅扩展内置能力实现
- handler_dispatcher 增强参数注入和错误处理
- Star 基类增加生命周期钩子和工具方法

* Add comprehensive API documentation for types and utilities in AstrBot SDK

- Introduced `types.md` detailing type aliases, generics, and Pydantic models used in the SDK.
- Added `utils.md` covering utility classes and functions including CancelToken, MessageSession, command groups, and session management.
- Included usage examples and detailed descriptions for each component to enhance developer understanding and ease of use.

* feat: 添加高级方法和辅助函数文档,增强消息组件和事件处理功能

* feat: 增强过滤器类型和能力路由文档,添加 Provider 和会话管理功能

* change location

* delete no need thing

* delete again

* feat: add Star plugin base class and StarTools utility class

- Introduced `Star` class as a base for v4 native plugins, providing lifecycle methods and context management.
- Added `StarTools` class for accessing runtime context and managing LLM tools.
- Implemented `PluginHarness` for local development and testing of plugins, allowing for message dispatching and lifecycle management.
- Created `GreedyStr` type for enhanced command parameter parsing, enabling the capture of remaining command text as a single argument.
- Added testing utilities and mock capabilities for plugin development.

* delete: remove hello_plugin example and its related files

* Remove obsolete test files for testing module, top-level modules, transport, and wire codecs

- Deleted `test_testing_module.py` as it is no longer needed.
- Removed `test_top_level_modules.py` which had no content.
- Eliminated `test_transport.py` due to redundancy.
- Cleared out `test_wire_codecs.py` as part of the cleanup.

* fix(runtime): avoid creating Star instance in on_error fallback

* fix(runtime): avoid virtual dispatch in Star.on_error fallback

* refactor(runtime): unify command matching logic (#25)

* refactor(testing): share command matching with handler dispatcher

* fix:添加公共函数文件

* fix: simplify register_task completion handling (#27)

* fix: simplify register_task completion handling

Remove duplicated cancellation logging in Context.register_task while keeping Future inputs compatible with asyncio.create_task semantics. Add regression coverage for coroutine, Future, cancellation, and failure paths.

* fix: prioritize local src in tests_v4

Ensure tests_v4 always imports the working tree package by moving src to sys.path[0] even when another checkout or installed copy is already present.

* chore: sync subtree from AstrBot

* feat: replay non-sdk changes on clean sdk subtree baseline

* feat(sdk): add merged provider config capability support

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(sdk): add merged provider config bridge and client

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(sdk): add merged provider config capability support

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(sdk): tighten bridge cast typing

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(sdk): add merged provider config bridge and client

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(sdk): cover merged provider config parity

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat: 完善 memory 向量检索与索引统计 (#28)

Co-authored-by: united_pooh <united_pooh@outlook.com>

* feat(tests): 添加测试用例以验证 register_task 的行为并更新测试运行说明

* Merge commit 'e45bade147ff44b43860ecff12067309e59c151a' into feat/sdk-integration

* Squashed 'astrbot-sdk/' changes from 7dda6077..85342f14

85342f14 feat(tests): 添加测试用例以验证 register_task 的行为并更新测试运行说明
fdffc09b Merge pull request #26 from united-pooh/fix/fix-star-on-error-fallback
3b09747c feat: 完善 memory 向量检索与索引统计 (#28)
665c9c69 fix(runtime): avoid virtual dispatch in Star.on_error fallback
200559a5 fix(runtime): avoid creating Star instance in on_error fallback

git-subtree-dir: astrbot-sdk
git-subtree-split: 85342f149b

* feat(tests): 添加测试用例以验证平台和消息类型过滤器的冲突处理

* docs: remove redundant testing instructions from AGENTS.md

* docs: remove redundant testing instructions from AGENTS.md

* docs: remove redundant testing instructions from AGENTS.md

* Merge commit '5ac9401852ddb46f337da6bcc0f9b66eed265da9' into feat/sdk-integration

* Squashed 'astrbot-sdk/' changes from 85342f14..09beabeb

09beabeb feat(tests): 添加测试用例以验证平台和消息类型过滤器的冲突处理

git-subtree-dir: astrbot-sdk
git-subtree-split: 09beabeb62

* feat: enhance SDK plugin configuration handling and logging

* feat: enhance SDK plugin configuration handling and logging

* feat: enhance SDK plugin configuration handling and logging

* feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器

* feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器

* feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器

* feat: 更新文档以反映SDK负载的JSON可序列化要求和延迟导入设计约束

* feat: add conversation.get_current capability and related schemas

- Introduced CONVERSATION_GET_CURRENT_INPUT_SCHEMA and CONVERSATION_GET_CURRENT_OUTPUT_SCHEMA for handling current conversation requests.
- Implemented _conversation_get_current method in BuiltinCapabilityRouterMixin to manage current conversation retrieval and creation.
- Registered the new capability in CoreCapabilityBridge.
- Enhanced HandlerDispatcher to inject provider request, LLM response, and event result payloads into the event handling process.
- Updated tests to validate the new functionality and ensure proper payload handling.

* feat: add conversation.get_current capability and related schemas

- Introduced CONVERSATION_GET_CURRENT_INPUT_SCHEMA and CONVERSATION_GET_CURRENT_OUTPUT_SCHEMA for handling current conversation requests.
- Implemented _conversation_get_current method in BuiltinCapabilityRouterMixin to manage current conversation retrieval and creation.
- Registered the new capability in CoreCapabilityBridge.
- Enhanced HandlerDispatcher to inject provider request, LLM response, and event result payloads into the event handling process.
- Updated tests to validate the new functionality and ensure proper payload handling.

* feat: add conversation.get_current capability and related schemas

- Introduced CONVERSATION_GET_CURRENT_INPUT_SCHEMA and CONVERSATION_GET_CURRENT_OUTPUT_SCHEMA for handling current conversation requests.
- Implemented _conversation_get_current method in BuiltinCapabilityRouterMixin to manage current conversation retrieval and creation.
- Registered the new capability in CoreCapabilityBridge.
- Enhanced HandlerDispatcher to inject provider request, LLM response, and event result payloads into the event handling process.
- Updated tests to validate the new functionality and ensure proper payload handling.

* Refactor tool call handling in SdkPluginBridge

- Introduced a dictionary to map tool call IDs to tool names for better clarity and efficiency.
- Enhanced the extraction of tool call information from raw results, ensuring compatibility with both dictionary and object formats.
- Updated the logic to retrieve tool names based on tool call IDs, improving the robustness of the tool calls result processing.

* Refactor tool call handling in SdkPluginBridge

- Introduced a dictionary to map tool call IDs to tool names for better clarity and efficiency.
- Enhanced the extraction of tool call information from raw results, ensuring compatibility with both dictionary and object formats.
- Updated the logic to retrieve tool names based on tool call IDs, improving the robustness of the tool calls result processing.

* Refactor tool call handling in SdkPluginBridge

- Introduced a dictionary to map tool call IDs to tool names for better clarity and efficiency.
- Enhanced the extraction of tool call information from raw results, ensuring compatibility with both dictionary and object formats.
- Updated the logic to retrieve tool names based on tool call IDs, improving the robustness of the tool calls result processing.

* feat: add session and system capabilities for plugin management and event handling

- Implemented SessionCapabilityMixin with methods to manage session-level plugin states and handlers.
- Added SystemCapabilityMixin to handle system-level functionalities including file management, event handling, and dynamic command registration.
- Introduced methods for enabling/disabling plugins, filtering handlers, and managing LLM and TTS service states.
- Registered various system capabilities for data directory access, HTML rendering, and event streaming.

* feat: add session and system capabilities for plugin management and event handling

- Implemented SessionCapabilityMixin with methods to manage session-level plugin states and handlers.
- Added SystemCapabilityMixin to handle system-level functionalities including file management, event handling, and dynamic command registration.
- Introduced methods for enabling/disabling plugins, filtering handlers, and managing LLM and TTS service states.
- Registered various system capabilities for data directory access, HTML rendering, and event streaming.

* Squashed 'astrbot-sdk/' changes from 09beabeb..3204c9db

3204c9db Merge sdk-remote dev into feat/sdk-integration
3a2d715e Refactor tool call handling in SdkPluginBridge
ed1b9665 feat: add conversation.get_current capability and related schemas
e74123bb feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器
bb361cf9 feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器
c6237f52 Merge sdk-remote/dev into astrbot-sdk subtree
e12029ff feat: enhance SDK plugin configuration handling and logging
5e54bbb3 feat: enhance SDK plugin configuration handling and logging
f48e2041 Merge commit '5ac9401852ddb46f337da6bcc0f9b66eed265da9' into feat/sdk-integration
619672e6 Merge commit '5ac9401852ddb46f337da6bcc0f9b66eed265da9' into feat/sdk-integration
d5a3796d docs: remove redundant testing instructions from AGENTS.md
323e3f4d docs: remove redundant testing instructions from AGENTS.md
f8438a7b Merge commit 'e45bade147ff44b43860ecff12067309e59c151a' into feat/sdk-integration
96d1df85 Merge commit 'e45bade147ff44b43860ecff12067309e59c151a' into feat/sdk-integration
f8a7e253 feat(sdk): add merged provider config bridge and client
752dc6cf feat(sdk): add merged provider config capability support

git-subtree-dir: astrbot-sdk
git-subtree-split: 3204c9db9f

* Implement feature X to enhance user experience and optimize performance

* Implement feature X to enhance user experience and optimize performance

* chore(sdk): stop tracking uv.lock

* feat(sdk): add merged provider config capability support

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(sdk): add merged provider config bridge and client

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(tests): 添加测试用例以验证 register_task 的行为并更新测试运行说明

* feat(tests): 添加测试用例以验证平台和消息类型过滤器的冲突处理

* docs: remove redundant testing instructions from AGENTS.md

* feat: enhance SDK plugin configuration handling and logging

* feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器

* feat: add conversation.get_current capability and related schemas

- Introduced CONVERSATION_GET_CURRENT_INPUT_SCHEMA and CONVERSATION_GET_CURRENT_OUTPUT_SCHEMA for handling current conversation requests.
- Implemented _conversation_get_current method in BuiltinCapabilityRouterMixin to manage current conversation retrieval and creation.
- Registered the new capability in CoreCapabilityBridge.
- Enhanced HandlerDispatcher to inject provider request, LLM response, and event result payloads into the event handling process.
- Updated tests to validate the new functionality and ensure proper payload handling.

* Refactor tool call handling in SdkPluginBridge

- Introduced a dictionary to map tool call IDs to tool names for better clarity and efficiency.
- Enhanced the extraction of tool call information from raw results, ensuring compatibility with both dictionary and object formats.
- Updated the logic to retrieve tool names based on tool call IDs, improving the robustness of the tool calls result processing.

* feat: add session and system capabilities for plugin management and event handling

- Implemented SessionCapabilityMixin with methods to manage session-level plugin states and handlers.
- Added SystemCapabilityMixin to handle system-level functionalities including file management, event handling, and dynamic command registration.
- Introduced methods for enabling/disabling plugins, filtering handlers, and managing LLM and TTS service states.
- Registered various system capabilities for data directory access, HTML rendering, and event streaming.

* fix(runtime): avoid creating Star instance in on_error fallback

* fix(runtime): avoid virtual dispatch in Star.on_error fallback

* feat: refactor injected parameter handling and introduce is_framework_injected_parameter utility

* Squashed 'astrbot-sdk/' changes from 027c15b4..d078e510

d078e510 feat: refactor injected parameter handling and introduce is_framework_injected_parameter utility
461f7276 Merge branch 'dev' of https://github.com/united-pooh/astrbot-sdk into dev
5ead59c4 fix(runtime): avoid virtual dispatch in Star.on_error fallback
d2382858 fix(runtime): avoid creating Star instance in on_error fallback
e961e361 feat: add session and system capabilities for plugin management and event handling
5a46321a Refactor tool call handling in SdkPluginBridge
47698448 feat: add conversation.get_current capability and related schemas
9b35bec8 feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器
48a20240 feat: enhance SDK plugin configuration handling and logging
cb593a53 docs: remove redundant testing instructions from AGENTS.md
f4942076 feat(tests): 添加测试用例以验证平台和消息类型过滤器的冲突处理
b0f8b2d6 feat(tests): 添加测试用例以验证 register_task 的行为并更新测试运行说明
6e417c6d feat(sdk): add merged provider config bridge and client
659eabce feat(sdk): add merged provider config capability support
REVERT: 027c15b4 Implement feature X to enhance user experience and optimize performance
REVERT: c272661f chore: pull sdk subtree from dev (resolve delete/modify conflict)
REVERT: 0a2a3592 feat: add session and system capabilities for plugin management and event handling
REVERT: 3204c9db Merge sdk-remote dev into feat/sdk-integration
REVERT: 36443f1d Refactor tool call handling in SdkPluginBridge
REVERT: 3a2d715e Refactor tool call handling in SdkPluginBridge
REVERT: b93c2c2b feat: add conversation.get_current capability and related schemas
REVERT: ed1b9665 feat: add conversation.get_current capability and related schemas
REVERT: e74123bb feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器
REVERT: bb361cf9 feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器
REVERT: c6237f52 Merge sdk-remote/dev into astrbot-sdk subtree
REVERT: e12029ff feat: enhance SDK plugin configuration handling and logging
REVERT: 5e54bbb3 feat: enhance SDK plugin configuration handling and logging
REVERT: f48e2041 Merge commit '5ac9401852ddb46f337da6bcc0f9b66eed265da9' into feat/sdk-integration
REVERT: 619672e6 Merge commit '5ac9401852ddb46f337da6bcc0f9b66eed265da9' into feat/sdk-integration
REVERT: d5a3796d docs: remove redundant testing instructions from AGENTS.md
REVERT: 323e3f4d docs: remove redundant testing instructions from AGENTS.md
REVERT: f8438a7b Merge commit 'e45bade147ff44b43860ecff12067309e59c151a' into feat/sdk-integration
REVERT: 96d1df85 Merge commit 'e45bade147ff44b43860ecff12067309e59c151a' into feat/sdk-integration
REVERT: f8a7e253 feat(sdk): add merged provider config bridge and client
REVERT: 752dc6cf feat(sdk): add merged provider config capability support

git-subtree-dir: astrbot-sdk
git-subtree-split: d078e51051

* refactor: reorganize imports and enhance type hints in sdk_bridge modules

* refactor: update import paths to use Path for better compatibility

* refactor(injection): centralize legacy injected parameter filtering

* fix(testing): use public session waiter probe in PluginHarness

* docs: add TODO for documentation content in _command_model.py

* feat: add memory management capabilities to CoreCapabilityBridge and implement unit tests

* feat: enhance memory search functionality and improve metadata retrieval in SDK

* feat: add memory management attributes and typed provider method to CapabilityMixinHost

* Implement feature X to enhance user experience and optimize performance

* Refactor memory utility functions and enhance memory capability mixin

- Added new utility functions for memory management in _memory_utils.py.
- Refactored memory capability mixin methods to utilize the new utility functions for better readability and maintainability.
- Updated PROJECT_ARCHITECTURE.md to reflect changes in documentation and structure.

* Squashed 'astrbot-sdk/' changes from d078e510..208bc591

208bc591 Merge pull request #30 from united-pooh/refactor/unify-legacy-injected-params
d86534a2 docs: add TODO for documentation content in _command_model.py
090724a7 refactor(injection): centralize legacy injected parameter filtering

git-subtree-dir: astrbot-sdk
git-subtree-split: 208bc591dd

* Initial plan

* docs: fix path, Python version, and client API table in PROJECT_ARCHITECTURE.md

Co-authored-by: whatevertogo <149563971+whatevertogo@users.noreply.github.com>

* Squashed 'astrbot-sdk/' changes from 208bc591..ad5e8d13

ad5e8d13 Merge pull request #37 from united-pooh/sdk/whatevertogo
5751701f Merge pull request #38 from united-pooh/copilot/sub-pr-37
e21acba5 docs: fix path, Python version, and client API table in PROJECT_ARCHITECTURE.md
ee67cab4 Initial plan
7d921570 Refactor memory utility functions and enhance memory capability mixin

git-subtree-dir: astrbot-sdk
git-subtree-split: ad5e8d1397

* docs: fix TODO comment formatting in _command_model.py

* 集成SDK命令候选项,优化Telegram和Discord平台适配器的命令收集逻辑

* 删除AI女友插件的单元测试文件

* 更新文档,添加Telegram和Discord原生命令菜单的注册说明

* Squashed 'astrbot-sdk/' changes from ad5e8d13..5003da58

5003da58 Merge pull request #40 from united-pooh/sdk/whatevertogo
b5084c44 Merge branch 'sdk/whatevertogo' of https://github.com/united-pooh/astrbot-sdk into sdk/whatevertogo
7559edf7 docs: fix TODO comment formatting in _command_model.py

git-subtree-dir: astrbot-sdk
git-subtree-split: 5003da58f5

* fix(testing): route session waiter followups through dispatcher (#33)

* fix(testing): route session waiter followups through dispatcher

* fix(testing): preserve waiter context and completion state

* fix(runtime): preserve session waiter plugin identity

* fix(runtime): scope session waiters by plugin

* fix(testing): isolate waiter replacement and followup drains

* fix(runtime): normalize waiter routing inputs

* fix(cli): route protocol stdout at command entry (#41)

* 添加内存后端支持,优化插件内存管理逻辑

* feat(memory): enhance memory schemas and add namespace support

- Updated MEMORY_SEARCH_INPUT_SCHEMA to include `namespace` and `include_descendants`.
- Modified MEMORY_SEARCH_OUTPUT_SCHEMA to allow nullable `namespace`.
- Added `namespace` to MEMORY_GET_INPUT_SCHEMA, MEMORY_DELETE_INPUT_SCHEMA, MEMORY_SAVE_WITH_TTL_INPUT_SCHEMA, MEMORY_GET_MANY_INPUT_SCHEMA, and MEMORY_DELETE_MANY_INPUT_SCHEMA.
- Enhanced MEMORY_STATS_INPUT_SCHEMA to support `namespace` and `include_descendants`.
- Updated MEMORY_GET_OUTPUT_SCHEMA and MEMORY_STATS_OUTPUT_SCHEMA to include `namespace` and `namespace_count`.
- Introduced `_memory_backends` in CapabilityRouterHost and CapabilityRouterBridgeBase for better memory management.
- Refactored MemoryCapabilityMixin to utilize memory backends for plugin-specific memory operations.
- Improved memory search functionality to respect namespaces and include descendants based on input parameters.
- Added tests to validate memory operations across different namespaces and ensure persistence across restarts.
- Implemented error handling in the handler dispatcher to manage exceptions gracefully.

* fix: guard session_waiter blocking usage

* fix(runtime): preserve request-scoped system event overlays

* test(runtime): lock peer initialization and transport failure semantics

* test(loader): cover plugin reload and import isolation regressions

* refactor(supervisor): clarify plugin registry sync phases

* test(clients): cover provider lifecycle regressions

* feat(cli): improve astr init defaults

* feat(plugin): add plugin ID validation and data directory resolution

- Implemented `validate_plugin_id` to ensure safe plugin identifiers.
- Added `resolve_plugin_data_dir` to resolve plugin data directories securely.
- Updated memory and system capabilities to utilize new plugin ID validation.
- Refactored session waiter management to simplify plugin ID handling.
- Enhanced tests for plugin ID validation and data directory resolution.

* fix(cli): exit cleanly on init abort

* feat(memory): enhance namespace handling and add tests for memory client

* feat(agent): add tool status message handling and improve SDK command integration

* Refactor SDK structure for backward compatibility

- Moved message result and session classes to internal modules while preserving legacy import paths for compatibility.
- Updated imports across the SDK to reflect the new internal structure.
- Enhanced session waiter management to support multiple plugins and improve error handling.
- Added tests to ensure LLM tool registration and session waiter functionality align with dispatcher expectations.
- Cleaned up code and improved documentation for clarity and maintainability.

* 增强异步下载功能,更新组件导入方式,并添加相关测试用例

* 添加任务重入锁以支持会话等待器的嵌套清理,并更新相关测试用例以验证后续消息的序列化处理

* 添加 .astrbot_sdk_testing 到 .gitignore 文件

* Add unit tests for provider management and tool capabilities

- Introduced new test suite for provider platform management in `test_sdk_provider_platform_management.py`, covering scenarios for merged provider configurations, reserved plugin checks, and provider management functionalities.
- Added tests for tool capabilities and provider queries in `test_sdk_provider_tool_platform_capabilities.py`, validating interactions with LLM tools and specialized proxies.
- Removed obsolete `test_sdk_transport.py` as it contained outdated tests for transport layer functionality.

* 添加多个模块和测试用例,增强SDK功能并支持单元测试

* fix(bridge): add missing capability registrations for db/memory/http/metadata

Register methods for db, memory, http, and metadata capabilities exist in
BasicCapabilityMixin but were never called in CoreCapabilityBridge.__init__.
This caused SDK plugins using ctx.memory, ctx.db, ctx.http to fail with
"LookupError: capability not found".

* feat(kb): enhance knowledge base capabilities with document management and serialization

* 添加知识库文档管理功能,包括文档上传、列表、获取、删除和刷新能力,更新相关的能力路由和协议模式

* feat(conversation): add ability to unset conversation persona and update related methods

* 添加对话管理和元数据管理功能,包括清空对话人格和保存插件配置的能力

* feat(conversation): add test for unsetting conversation persona and verify state

* feat(plugin): add save_plugin_config method and related tests for plugin configuration persistence

* 优化插件配置保存方法的代码格式

* feat(sdk): enhance handler metadata with descriptions, priority, kind, and admin requirements

* 添加描述、优先级和其他元数据到处理程序元数据和描述符中,优化相关功能

* feat(sdk): enhance SDK integration with local extras handling and message payloads

* 添加对 MessageEvent 的额外字段支持,优化事件处理器的参数注入,增强 SDK 本地临时数据的管理能力

* 增强插件日志记录功能,添加控制台输出格式化和路径标签支持,新增单元测试以验证日志格式

* feat: Enhance command and tool management in dashboard

- Refactor CommandRoute to utilize AstrBotCoreLifecycle for improved command handling.
- Introduce command_key for commands to streamline toggling, renaming, and permission updates.
- Implement support for SDK commands in the dashboard, marking them as read-only.
- Update ToolTable and CommandTable components to use new command_key and tool_key properties.
- Add runtime_kind and plugin_id to tools for better management.
- Enhance API tests to cover SDK commands and tools, ensuring proper functionality and error handling.
- Update localization files to include new messages related to SDK commands.

* 优化插件日志记录和能力代理模块,增强异常处理,确保优先级参数为整数

* feat: 增强LLM能力,添加聊天提供者协议和异常处理,更新单元测试以验证提供者有效性

* feat: Implement SDK skill management capabilities

- Added SkillCapabilityMixin to handle skill registration, unregistration, and listing.
- Integrated skill management into the CoreCapabilityBridge.
- Enhanced SkillManager to support SDK-registered skills, including loading, saving, and syncing skills.
- Updated computer_client to utilize SkillManager for skill synchronization with sandboxes.
- Refactored skill export functionality in SkillsRoute to accommodate new skill management structure.
- Introduced tests for SDK skill registration, unregistration, and syncing to ensure functionality.
- Improved skill handling in the dashboard and test suite to reflect changes in skill management.

* 添加技能注册功能,包含技能注册、注销和列出能力的实现,增强插件能力管理

* 删除CLAUDE.md文档,移除过时的已知问题描述

* 删除 AGENTS.md 文档,移除过时的架构约束和开发命令说明

* 更新测试用例,修复插件发现失败时的错误信息,确保使用正确的运行时字段

* 修复错误处理和权限检查,新增单元测试以验证功能

* format

* 增强命名空间管理,优化数据库操作,添加 HTTP 路由验证,新增并发隔离测试,完善命令模型解析单元测试

* 增强 HTTP 路由功能,添加 HTTP 方法注销逻辑的单元测试

* 格式化日志输出,优化批量插入时无内容提供的调试信息

* fix: add uv dependency for plugin environment groups

* 删除代码审查文档 CODE_REVIEW_ISSUES.md

* 添加消息历史管理功能,包括消息记录的增删查改,完善相关能力混合类和测试用例

* 实现 SDK 消息历史管理功能,包括记录的增删查改操作

* Add unit tests for MCP contract and capabilities in SDK

- Implemented `_mcp_contract.py` to test local MCP server functionalities including listing, enabling, and disabling servers.
- Created `test_sdk_mcp_capabilities.py` to cover various aspects of the CoreCapabilityBridge and SdkPluginBridge, including session management and global MCP server operations.
- Introduced fake classes to simulate MCP server behavior and manage tool configurations for testing.
- Ensured comprehensive coverage of MCP session lifecycle, including opening, listing tools, calling tools, and closing sessions.

* feat(mcp): Implement local and global MCP server management capabilities

- Added MCP management client to the context for local/global MCP service management.
- Introduced decorators to acknowledge global MCP risk for plugins.
- Defined schemas for MCP server operations including get, list, enable, disable, and session management.
- Created MCP capability mixin to handle local and global MCP server operations.
- Enhanced provider capabilities to include active local MCP tool names.
- Updated capability router to support MCP functionalities and maintain session state.
- Added tests for MCP functionalities, ensuring proper behavior and risk acknowledgment.

---------

Co-authored-by: whatevertogo <149563971+whatevertogo@users.noreply.github.com>
Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: letr <letr007@foxmail.com>
Co-authored-by: united_pooh <united_pooh@outlook.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: united_pooh <united_pooh@icloud.com>
Co-authored-by: Lishiling <m18384519631@163.com>
Co-authored-by: Li-shi-ling <114913764+Li-shi-ling@users.noreply.github.com>
Co-authored-by: letr <123731298+letr007@users.noreply.github.com>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: catDforD <3276453835@qq.com>
Co-authored-by: united_pooh <united_pooh@MBP-F6H6T2CYVV-2219.local>
2026-03-22 22:44:05 +08:00
LIghtJUNction
5721f7bf24 fix: remove broken tests referencing non-existent functions
- Remove test_computer_config.py (discover_bay_credentials not found)
- Remove test_main.py (check_dashboard_files not found)
- Remove test_skill_metadata_enrichment.py (_parse_frontmatter_description not found)
- Fix test_uninstall.py assertions to match actual output
- Fix test_bk.py digest test async mock
- Fix test_booter_decoupling.py shipyard test (incomplete config returns 0 tools)
- Fix computer_client.py _list_local_skill_dirs type error (Path vs anyio.Path)
- Remove TestApplySandboxTools class (function _apply_sandbox_tools not found)
2026-03-22 22:30:53 +08:00
LIghtJUNction
2f45280222 fix(dashboard): symlink dist for dev-mode resource resolution
importlib.resources.files('astrbot')/dashboard/dist needs to exist
in the package dir for bundled dashboard detection to work in dev.
2026-03-22 22:29:26 +08:00
whatevertogo
e9b1dd35f9 fix: remove privacy data from test case (#6803)
Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
2026-03-22 21:49:43 +08:00
LIghtJUNction
798182fd8a Merge branch 'dev' of https://github.com/AstrBotDevs/AstrBot into dev 2026-03-22 20:17:28 +08:00
LIghtJUNction
5ba7ecec9e Merge branch 'master' of https://github.com/AstrBotDevs/AstrBot into dev 2026-03-22 20:16:52 +08:00
二枣子
937872cda7 feat(aiocqhttp): support file upload via Napcat stream transfer (#6433)
* feat(aiocqhttp): support file upload via Napcat stream transfer aiocqhttp

feat(aiocqhttp): support file upload via Napcat stream transfer
aiocqhttp上传资源文件时只传输本地路径,此方案对于没有共享磁盘方案不友好,Napcat >= v4.8.115 后,已支持新的 Stream API 方案。此方案在路径传输失败时自动尝试流式传输。

* perf(aiocqhttp): optimize file upload retry and streaming memory usage

1.内存使用优化,文件边读边传。
2.重试逻辑包装为独立方法便于阅读维护。
3.异常处理优化。
4.硬编码提取为模块级常量,提升可读性和配置性。

---------

Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
2026-03-22 20:11:58 +08:00
LIghtJUNction
3545c8d393 chore: 新增依赖,移除类型忽略注释 2026-03-22 19:58:46 +08:00
LIghtJUNction
2f82f04ee2 chore: restore tui screen from history 2026-03-22 19:53:56 +08:00
LIghtJUNction
88821bd1bb Update test_plugin_manager.py 2026-03-22 19:50:36 +08:00
LIghtJUNction
b1d048ca5c chore: resolve merge conflicts (prefer HEAD) 2026-03-22 19:50:26 +08:00
LIghtJUNction
eab231fd94 chore: gitignore .env warker.js 2026-03-22 19:12:12 +08:00
LIghtJUNction
dd5105a504 fix(core/platform): platform event and adapters updates 2026-03-22 19:08:59 +08:00
LIghtJUNction
8cff9be334 fix(core): event bus and pipeline stage updates 2026-03-22 19:08:56 +08:00
LIghtJUNction
3a9bbcfdee fix(core/cron): update cron manager logic 2026-03-22 19:08:54 +08:00
LIghtJUNction
95ba23c3ab fix(core): minor changes to agent tool executor and lifecycle 2026-03-22 19:08:51 +08:00
LIghtJUNction
b70eb4e64f fix(core): narrow typed overrides for quoted message parser 2026-03-22 19:08:48 +08:00
Soulter
eab3298d42 docs: update wechat app version requirements for WeChat adapter and add instructions for profile photo/remark modifications 2026-03-22 18:33:32 +08:00
Soulter
81c7b0f715 chore: bump version to 4.22.0 2026-03-22 17:34:09 +08:00
Frank
1879e5961d fix: keep all CallToolResult content items (#6149)
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-03-22 17:21:22 +08:00
Soulter
b2d71e2b77 feat: supports image compressing (#6794)
* feat: supports image compressing (#6463)

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

* feat: 增加图像压缩最大尺寸至1280

* Update astrbot/core/astr_main_agent.py

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

* feat: 增强临时文件管理,添加图像压缩路径跟踪与清理功能

* feat: 更新图片压缩功能提示,移除对 chat_completion 提供商的限制说明

---------

Co-authored-by: Chen <42998804+a61995987@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-22 17:12:28 +08:00
Chen
02a910f038 feat: supports image compressing (#6463)
* feat:新增本地图片预压缩机制 避免原图体积过大造成的413错误

* 修正“图片解析失败”消息追加的位置错误
修正"temp_dir"的路径错误

* 修正temp_dir的相对路径错误

* 移动模块导入位置

* fix:重构图片压缩方法 使用异步方式避免阻塞

* ```
feat(core): 优化图片压缩功能并替换UUID为时间戳

- 将图片压缩的同步阻塞操作移至线程池执行,提升性能
- 替换uuid依赖为time模块,使用时间戳生成文件名
- 添加异步图片压缩内部函数_do_compress_sync
- 修复图片压缩时的异常处理日志级别
- 在消息附件和回复链中集成图片压缩功能
```

* fix:修改temp_dir指向 现在使用框架内置的get_astrbot_temp_path来获取临时目
fix:分离image_path的计算行为 提高可读性
fix:使用uuid来生成压缩后的图片 而非时间戳

* fix:修改错误的注释

* fix:分离图片压缩函数到媒体文件处理工具中

* fix:修改原有的列表推导式以提高可读性
feat:增加预留功能的说明注释

* fix:在图片压缩工具中使用pathlib.path获取路径并拼接压缩后的文件名称

* feat: 新增本地图片预压缩机制,增强图片解析容错能力

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-22 16:36:33 +08:00
Soulter
63dd28d778 fix: handle potential None values for token usage metrics in OpenAI provider (#6788)
Such as: unsupported operand type(s) for -: 'int' and 'NoneType'

fixes: #6772
2026-03-22 15:20:22 +08:00
M1LKT
a2dae0fc5e Feat(webui): support pinning and dragging for installed plugins (#6649) (#6776)
* refactor(persona): replace local folder components with shared folder components

* feat(webui): implement draggable reordering with animation for pinned plugins

* refactor(webui): extract PinnedPluginItem into a standalone component
2026-03-22 14:55:02 +08:00
Ruochen Pan
554c9cecfa feat: fix preserve escaped newlines in frontmatter & update tests & ci workflows (#6783) 2026-03-22 14:23:21 +08:00
Waterwzy
ef43217117 feat: skip search when the entire knowledge base is empty (#6750)
* feat:增加知识库全为空时的跳过检索

* apply bot suggestions

* style:reformat code
2026-03-22 13:36:18 +08:00
Lockinwize Lolite
3e68b7a3f3 fix(platform.tg_adapter): import Forbidden instead of deprecated Unauthorized (#6765) (#6769) 2026-03-22 13:35:09 +08:00
Soulter
e204790797 feat: supports weixin personal account (#6777)
* feat: supports weixin personal account

* feat(weixin): update documentation for personal WeChat integration and add QR code image

* feat(weixin): refactor send method to streamline message handling

* fix(weixin): correct AES key encoding in media payload construction

* feat(weixin): update weixin_oc_base_url description for clarity in config metadata

* feat(weixin): enhance WeChat integration with QR code support and configuration updates

* feat(weixin): implement WeixinOCClient for improved media handling and API requests

* feat(platform): update platform status refresh interval to 5 seconds
2026-03-22 13:25:12 +08:00
lightjunction
753e9a2bba chore: 2026-03-22 02:00:53 +08:00
Soulter
0743cb51bc chore: bump version to 4.21.0 2026-03-22 02:00:28 +08:00
Soulter
5419efbc9c feat(extension): add category filtering for market plugins and enhance UI components (#6762) 2026-03-22 01:54:21 +08:00
Soulter
52beeef83c feat(skill_manager): normalize and rename legacy skill markdown files to SKILL.md (#6757)
* feat(skill_manager): normalize and rename legacy skill markdown files to `SKILL.md`

* fix(vec_db): format debug log message for empty batch insert
2026-03-22 00:43:30 +08:00
LIghtJUNction
f9243a73d5 feat: reduce default max_agent_step to 3 and refactor shell execution
- Lower default max_agent_step from 30 to 3 across all agent runners
  (coze, dashscope, deerflow, dify) for faster responses
- Refactor ExecuteShellTool to use plumbum with session-based isolation,
  maintaining shell state per session (cwd, env vars, etc.)
- Remove unused API-specific environment variables from cmd_run
- Fix data access bug in shipyard_neo._maybe_model_dump
- Add plumbum>=1.10.0 dependency
2026-03-21 23:47:43 +08:00
Stable Genius
589776ab3f fix: skip empty knowledge-base embedding batches (#6106)
Co-authored-by: stablegenius49 <185121704+stablegenius49@users.noreply.github.com>
2026-03-21 20:56:13 +08:00
Stable Genius
5b71d01efb fix: convert Feishu opus files for Whisper API STT (#6078)
* fix: convert lark opus files for whisper api

* chore: ruff format

---------

Co-authored-by: Stable Genius <259448942+stablegenius49@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-21 20:44:36 +08:00
LIghtJUNction
43e107068a chore: cloudflare 2026-03-21 17:35:30 +08:00
LIghtJUNction
09157f8b88 Fix: combine conditions for bot mention check in Discord adapter 2026-03-21 17:12:29 +08:00
若月千鸮
173583781e fix(lark): Defer card creation and renew on tool call break (#6743)
* fix(lark): defer streaming card creation and renew card on tool call break

- Defer CardKit streaming card creation until the first text token
  arrives, preventing an empty card from rendering before content.
- Handle `type="break"` signal in send_streaming: close the current
  card and lazily create a new one for post-tool-call text, so the
  new card appears below the tool status message in correct order.
- Only emit "break" signal when show_tool_use is enabled; when tool
  output is hidden, the AI response continues on the same card.

* style: format ruff

* fix: cr bug

* fix: cr
2026-03-21 17:08:25 +08:00
LIghtJUNction
256c8cceeb Fix: handle None values for ctx.author and ctx.interaction in Discord adapter 2026-03-21 16:15:33 +08:00
LIghtJUNction
7391f8e5ee Fix: only enable CORS credentials when allow_origin is not wildcard 2026-03-21 16:00:17 +08:00
LIghtJUNction
b563518711 Fix: replace fullwidth comma with halfwidth comma in discord_platform_adapter.py 2026-03-21 15:21:35 +08:00
LIghtJUNction
255a4c0d5b Fix: support configuring allowed CORS origins via CORS_ALLOW_ORIGIN env
var for cross-origin credential requests
2026-03-21 15:20:43 +08:00
LIghtJUNction
859ca98f1e Fix: support configuring allowed CORS origins via CORS_ALLOW_ORIGIN env var for cross-origin credential requests 2026-03-21 15:14:08 +08:00
LIghtJUNction
a58319f594 Fix: Discord adapter not adding At component when bot is mentioned, causing group messages to not wake the bot 2026-03-21 14:26:22 +08:00
LIghtJUNction
26c5e67efe Refactor: change relative imports to absolute imports in tool_loop_agent_runner.py 2026-03-21 14:13:43 +08:00
LIghtJUNction
4412f789e1 Fix: downgrade SSL APPLICATION_DATA_AFTER_CLOSE_NOTIFY errors to debug level 2026-03-21 14:13:07 +08:00
LIghtJUNction
cefeaf8d9f Fix: add task tracking to BaseAgentRunner and ToolLoopAgentRunner, replace asdict with custom serialization in Response 2026-03-21 13:55:05 +08:00
LIghtJUNction
97efa3ab38 Fix: _BUNDLED_DIST undefined, use self.bundled_dist instead 2026-03-21 13:54:39 +08:00
LIghtJUNction
61e525afd4 Merge branch 'master' into dev 2026-03-21 12:25:04 +08:00
Stable Genius
25c136ef95 fix: fall back on Windows skill file encodings (#6058)
Co-authored-by: stablegenius49 <185121704+stablegenius49@users.noreply.github.com>
2026-03-21 11:00:40 +08:00
Stable Genius
5e69b62e4c fix(webchat): render standalone HTML replies as code (#6074)
Co-authored-by: Stable Genius <259448942+stablegenius49@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-03-21 10:52:46 +08:00
Stable Genius
968868f16b fix: ensure Gemini array schemas always include items (#6051)
Co-authored-by: Stable Genius <259448942+stablegenius49@users.noreply.github.com>
2026-03-21 10:44:48 +08:00
qingyun
e643bc94e5 fix(skills): use actual sandbox path from cache instead of hardcoded workspace root (#6331)
* 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>
2026-03-21 10:39:52 +08:00
Soulter
df4eb33582 docs: update README.md to add separator in links section 2026-03-21 10:34:27 +08:00
LIghtJUNction
286f6668f4 Fix formatting of bundled_dist property method 2026-03-21 05:10:52 +08:00
LIghtJUNction
4a5ac407d1 Refactor bundled_dist path handling in AstrbotPaths
Removed the _BUNDLED_DIST variable and added a bundled_dist property to calculate the path dynamically.
2026-03-21 05:01:41 +08:00
LIghtJUNction
93cab0e198 Reorganize .env loading sequence in astrbot_path.py
Refactor environment variable loading order in astrbot_path.py.
2026-03-21 04:51:53 +08:00
LIghtJUNction
b2a04ffed1 Fix syntax error in tool_loop_agent_runner.py 2026-03-21 04:21:21 +08:00
LIghtJUNction
3405c72b5e Modify context configuration parameters
Updated max_context_tokens default value and adjusted enforce_max_turns logic.
2026-03-21 04:17:59 +08:00
LIghtJUNction
4ee93c7f83 Limit max_step to a maximum of 3
基本都是设置为30,30太夸张了,这是日志里面截出来的:
system,user,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,user,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,tool,assistant,user,assistant,tool,tool,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user
2026-03-21 04:12:49 +08:00
LIghtJUNction
a710c06be2 Validate config_path before checking existence
Add check for empty config_path in check_exist method
2026-03-21 03:49:12 +08:00
LIghtJUNction
864a6851df Fix context manager usage for timeout enforcement 2026-03-21 03:36:32 +08:00
LIghtJUNction
37594dd74b Return Path object for project root property 2026-03-21 03:04:00 +08:00
LIghtJUNction
68c01cfba4 Fix handling of cached_tokens in _extract_usage
Ensure cached_tokens is an integer and handle None safely.
2026-03-21 02:37:04 +08:00
LIU Yaohua
8d9838a293 fix(agent): pass tool_call_timeout to subagent handsoff, cron and background task execution, and increase default timeout from 60 to 120 (#6713)
* fix(agent): pass tool_call_timeout to SubAgent handoff execution

- Add tool_call_timeout parameter to _execute_handoff method
- Pass run_context.tool_call_timeout to ctx.tool_loop_agent
- Add unit test to verify tool_call_timeout is correctly passed
- Fixes #6711: SubAgent MCP tool call timeout now respects configured timeout

The SubAgent handoff execution was using the default 60-second timeout
instead of the configured tool_call_timeout from provider settings.
This change ensures that SubAgent MCP tool calls respect the user's
configured timeout settings.

* test: add unit test for tool_call_timeout in SubAgent handoff

* fix: restore deleted test and fix test assertion

- Restore test_collect_handoff_image_urls_filters_extensionless_missing_event_file
- Fix test_collect_handoff_image_urls_keeps_extensionless_existing_event_file assertion
- Keep new test_execute_handoff_passes_tool_call_timeout_to_tool_loop_agent

* refactor: simplify tool_call_timeout passing in _execute_handoff

- Pass run_context.tool_call_timeout directly to ctx.tool_loop_agent
- Remove unnecessary local variable assignment
- Addresses review feedback from Sourcery AI

* fix(config): increase default tool call timeout from 60 to 120 seconds

---------

Co-authored-by: LehaoLin <linlehao@cuhk.edu.cn>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-21 01:30:53 +08:00
BillionToken
b273ba2a19 fix(config): respect disabled system functions in web search tools (#6584)
Co-authored-by: BillionClaw <billionclaw@cl OSS.dev>
2026-03-21 01:18:47 +08:00
Soulter
5214a8c0ba perf(webchat): enhance message handling with proactive saving and streaming completion (#6698) 2026-03-21 01:14:02 +08:00
Yufeng He
7beab796bb fix: skills-like re-query missing extra_user_content_parts causes image_caption not to be injected (#6710)
当使用 skills-like tool mode 时,_resolve_tool_exec 的 re-query 调用没有
传递 extra_user_content_parts,导致图片描述等附加内容丢失。

fixes #6702

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-03-21 01:11:34 +08:00
qingyun
b2797b6f16 fix(agent): reject follow-up messages after stop request (#6704)
* fix: reject follow-up messages after stop requested (#6626)

Once a user sends /stop, follow-up messages should no longer be
accepted for that runner. Previously, there was a race window where
messages sent after stop could still be queued as follow-ups.

This fix gates the follow_up() method to check both done() and
_stop_requested before accepting a new follow-up message.

Acceptance criteria met:
- After /stop, later follow-up messages return None (rejected)
- Post-stop follow-ups are not added to _pending_follow_ups
- No post-stop text is injected into tool results
- Graceful-stop behavior otherwise unchanged
- Follow-ups submitted before stop retain current behavior

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

* test: add regression tests for issue #6626 follow-up rejection

Add focused tests that verify the complete tool-result injection path
for follow-up messages after stop is requested:

- test_follow_up_rejected_and_runner_stops_without_execution: Verifies
  that when stop is requested before any execution, follow-ups are
  rejected and the runner stops gracefully without executing tools.

- test_follow_up_merged_into_tool_result_before_stop: Verifies that
  follow-ups queued before stop are properly merged into tool results
  via _merge_follow_up_notice().

- test_follow_up_after_stop_not_merged_into_tool_result: Regression
  test that simulates the race condition from issue #6626. Verifies
  that only pre-stop follow-ups are merged into tool results, and
  post-stop follow-ups are rejected at the admission point.

These tests validate the fix in ToolLoopAgentRunner.follow_up() that
checks both self.done() and self._stop_requested before accepting
new follow-up messages.

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

* fix(agent): update stop request check in ToolLoopAgentRunner

---------

Co-authored-by: ccsang <ccsang@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-21 01:06:37 +08:00
LIghtJUNction
6e3273dbec 修复:argon2库已过时,无法在3.12运行 2026-03-21 01:03:39 +08:00
SJ
b816f26fe6 fix(core): interrupt subagent tool waits on stop (#5850)
* fix(core): interrupt subagent tool waits on stop

* test: relax subagent handoff timeout

* test: cover stop-aware tool interruption

* refactor: unify runner stop state

* refactor: simplify tool executor interruption

* fix: preserve tool interruption propagation

* refactor: tighten interruption helpers

---------

Co-authored-by: idiotsj <idiotsj@users.noreply.github.com>
2026-03-21 00:59:52 +08:00
LIghtJUNction
af77f82c51 更名:conf password可以修改账户名称,因此改名为admin
astrbot conf admin -p xxx
2026-03-21 00:47:14 +08:00
LIghtJUNction
1b92c517e7 Merge branch 'master' into dev 2026-03-21 00:31:18 +08:00
LIghtJUNction
c238880cd2 修复:server.py 2026-03-21 00:28:56 +08:00
晴空
d2e0bc778a fix: preserve PATHEXT for stdio mcp servers on windows (#5822)
* fix: preserve PATHEXT for stdio mcp servers on windows

* chore: delete test_mcp_client.py

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-21 00:27:54 +08:00
LIghtJUNction
92b3e2d260 fix: avoid false dashboard port conflicts 2026-03-21 00:24:35 +08:00
Gargantua
dde02815c2 feat: add a toggle to disable thinking mode in Ollama (#5941)
* feat: add ollama thinking toggle

* fix: simplify hint for ollama_disable_thinking configuration

---------

Co-authored-by: Gargantua <22532097@zju.edu.cn>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-21 00:19:08 +08:00
LIghtJUNction
00c9388da3 重构:彻底放弃md5保存密码
main.py调整说明
修复一系列导入问题
修复一部分ruff check问题
2026-03-21 00:09:58 +08:00
whatevertogo
2c279abad1 fix: prevent accidental removal of MCP external tools due to name collisions with disabled built-in tools (#5925)
* fix: 解决 MCP 工具与内置工具重名时的连坐问题

- 修改 get_func 方法:优先返回已激活的工具
- 修改 get_full_tool_set 方法:使用 add_tool 防止同名冲突
- 修改 add_tool 方法:优先保留已激活的工具

Fixes #5821

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

* refactor: address PR review feedback for tool conflict resolution

- Fix inconsistency: get_func now uses reversed() to match ToolSet.add_tool's
  "last-active-wins" logic, preventing potential "tool hijacking" issues
- Improve readability: replace double negative condition with clearer logic
- Add compatibility: use getattr with default for tools without 'active' attribute
- Remove unnecessary deepcopy: MCPTool runtime objects should not be deep copied
- Update docstring: accurately describe the actual tool resolution behavior

Addresses review comments from sourcery-ai, gemini-code-assist, and Copilot.

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

* test: add tests for tool conflict resolution (issue #5821)

Add comprehensive tests for ToolSet.add_tool, get_func, and get_full_tool_set
to verify the conflict resolution behavior when MCP tools share names with
built-in tools.

Test cases:
- ToolSet.add_tool: active/inactive priority, last-one-wins for same state
- get_func: returns last active tool, fallback to last matching tool
- get_full_tool_set: deduplication logic, no deepcopy, MCP overrides disabled builtin

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

* fix: 修复工具冲突处理逻辑,确保未激活工具不被错误移除

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 23:44:07 +08:00
_Kerman
abb5de2ed5 chore: rename "OpenAI" provider to "OpenAI Compatible" (#6707) 2026-03-20 23:19:26 +08:00
LIghtJUNction
7445126057 Merge branch 'master' into dev 2026-03-20 22:40:32 +08:00
LIghtJUNction
9f2240a2a6 fix async ssl path handling 2026-03-20 21:50:46 +08:00
LIghtJUNction
a130b344b0 fix: narrow knowledge base provider types 2026-03-20 21:45:04 +08:00
LIghtJUNction
28e8e50005 fix: improve dashboard and knowledge base file handling 2026-03-20 21:40:21 +08:00
LIghtJUNction
a0b61c4da9 fix: correct rate limit stage algorithm docs 2026-03-20 21:35:55 +08:00
LIghtJUNction
b4f48ea1f0 fix: resolve dashboard build type errors 2026-03-20 21:21:31 +08:00
RichardLiu
a10ba4d641 feat: add xiaomi MiMo TTS & STT providers (#6643)
* feat: add mimo tts provider support

* fix: handle empty mimo tts choices

* feat: add mimo stt provider support
2026-03-20 20:52:21 +08:00
Helian Nuits
64853487b5 fix: auto-restart telegram polling loop on failure (#6648)
* fix: auto-restart telegram polling loop on failure (#373)

* fix: auto-restart telegram polling loop on failure

* fix: harden telegram polling restart lifecycle

* fix(telegram): 根据建议优化轮询鲁棒性并处理 Token 失效错误

* fix: 补全配置元数据及 i18n
2026-03-20 20:35:48 +08:00
LIghtJUNction
5ff71fef3e chore:环境变量注释修正 2026-03-20 20:02:47 +08:00
LIghtJUNction
073891c093 修复:移除错误的环境变量名字 2026-03-20 20:00:32 +08:00
LIghtJUNction
4fd77ea008 修复:启动链,参数/环境变量加载逻辑优化 2026-03-20 19:47:04 +08:00
LIghtJUNction
78edc0fff8 修复:启动链,参数/环境变量加载逻辑优化 2026-03-20 19:44:12 +08:00
LIghtJUNction
4f04d39348 同步:同步主线 2026-03-20 16:59:43 +08:00
LIghtJUNction
13132517b2 重构: 修正一些错误,引入_internel包 2026-03-20 16:51:27 +08:00
LIghtJUNction
804a02a2d1 fix(types): await anyio.open_file before async use to satisfy type checkers 2026-03-20 16:36:22 +08:00
LIghtJUNction
f076799b81 fix: async dashboard version read via anyio async context manager 2026-03-20 16:33:51 +08:00
LIghtJUNction
0068825cd5 cli(init): add --root option and generate .env from config.template into ASTRBOT_ROOT (auto-loaded by run) 2026-03-20 16:24:02 +08:00
LIghtJUNction
0b2a143681 cli(run): simplify env loading — move .env early-load to astrbot_path; service-config treated as .env; preserve CLI > service-config > .env precedence 2026-03-20 16:05:30 +08:00
LIghtJUNction
0e95a47276 fix: import error 2026-03-20 15:18:03 +08:00
Yufeng He
39131d2e12 fix: Follow-up logic persists after /stop trigger (#6656)
/stop 设置 agent_stop_requested 标记,但 runner 直到当前工具调用
超时才从 _ACTIVE_AGENT_RUNNERS 注销。在此窗口期内,用户发的新消息
被 try_capture_follow_up() 当作 follow-up 吞掉。

在 follow-up 捕获前检查 stop 标记:一旦用户请求停止,就不再把后续
消息注入到正在终止的 agent 上下文中。

Fixes #6626
2026-03-20 13:53:56 +08:00
letr
735bd43648 fix(dashboard): simplify persona selector layout for mobile screens (#5907) 2026-03-20 13:45:21 +08:00
Soulter
6a42ad7934 fix(openai): improve logging for proxy and API base configuration (#6669)
fix: #6558
2026-03-20 13:42:58 +08:00
daniel5u
b07dbb3d26 feat: add Kimi Coding Plan provider with Anthropic API compatibility (#6559)
* Add Kimi Code provider

* Add icon mapping for Kimi Code provider

* Clarify Kimi CodingPlan provider labeling

* Refine Kimi Code header handling

* modified docker compose

* fix: correct Kimi Coding Plan label and update API base URL

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-20 13:32:06 +08:00
leonforcode
0b69034491 fix: prevent truncation logic from removing the only user message in long tool-calling conversations (#6198)
* fix: 压缩算法删除 user 消息 Bug 修复

* perf: improve truncate algo

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-20 12:05:54 +08:00
Yufeng He
e286da75c4 fix: 截断器丢失唯一 user 消息导致智谱等 provider 返回 400 (#6581)
* fix: 截断器丢失唯一 user 消息导致 API 400

修复 #6196

当对话只有一条 user 消息(长 tool chain 场景:system → user → assistant
→ tool → assistant → tool → ...),三个截断方法都会把这条 user 消息丢掉,
导致智谱、Gemini 等要求 user 消息的 provider 返回 400。

改动:
- 提取 `_split_system_rest()` 去掉三个方法里重复的 system/non-system 拆分
- 新增 `_ensure_user_message()`:截断后如果没有 user 了,从原始消息里补回
  第一条 user,避免违反 API 格式要求
- 删掉 `truncate_by_dropping_oldest_turns` 里把没有 user 就清空全部消息的逻辑
- 5 个新测试覆盖单 user + 长 tool chain 场景,3 个旧测试更新断言

* style: format code

---------

Co-authored-by: Yufeng He <40085740+universeplayer@users.noreply.github.com>
Co-authored-by: RC-CHN <1051989940@qq.com>
2026-03-20 10:06:20 +08:00
LIghtJUNction
bf11f4c376 chore: fw2hw 2026-03-20 00:44:39 +08:00
LIghtJUNction
ef5dac77a2 chore: fw2hw 2026-03-20 00:44:08 +08:00
LIghtJUNction
92bae1fdae docs: replace prints with logger in upload_doc_images_to_r2.py 2026-03-19 23:30:25 +08:00
LIghtJUNction
a3371ad6c8 core: refactor modules & fix typing/runtime issues 2026-03-19 23:06:27 +08:00
LIghtJUNction
8184e20850 dashboard: validate SSL file paths with pathlib before use (fix typing/runtime issues) 2026-03-19 22:41:04 +08:00
LIghtJUNction
a4e6e16fd8 fix: surface https backend requirement in dashboard (#6623)
* fix: surface https backend requirement in dashboard

* Update dashboard/src/stores/api.ts

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>
2026-03-19 20:35:32 +08:00
LIghtJUNction
cc88ac6bef fix(cli): export webui group symbol 2026-03-19 20:09:47 +08:00
LIghtJUNction
b6f4614c58 fix(cli): robust password hashing when argon2 missing (fallback to PBKDF2) 2026-03-19 20:02:24 +08:00
LIghtJUNction
f03040a12e chore(pyproject): limit requires-python <3.14 to avoid resolver mismatch in env 2026-03-19 19:58:27 +08:00
LIghtJUNction
1bb73ab3cf feat(cli): add 'webui' group + register command in CLI 2026-03-19 19:53:48 +08:00
LIghtJUNction
17b0dfe974 fix(cli): restore cmd_conf password hashing and validators; use absolute import for check_astrbot_root 2026-03-19 19:46:21 +08:00
LIghtJUNction
d16f62423c Merge branch 'master' into dev 2026-03-19 19:25:47 +08:00
machina
7008a46158 fix: update hint for ID whitelist configuration to clarify behavior when empty (#6611)
* fix: update hint for ID whitelist configuration to clarify behavior when empty

* fix: update whitelist hint

---------

Co-authored-by: machina <1531829828@qq.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-19 19:06:53 +08:00
Soulter
5a90b56e45 fix(openai): Token usage not working when using MoonshotAI official API (#6618)
fixes: #6614
2026-03-19 19:04:24 +08:00
LIghtJUNction
c0282e4d28 Potential fix for code scanning alert no. 45: Use of a broken or weak cryptographic hashing algorithm on sensitive data
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-03-19 17:40:25 +08:00
LIghtJUNction
fce8069b18 Potential fix for code scanning alert no. 44: Use of a broken or weak cryptographic hashing algorithm on sensitive data
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-03-19 17:40:09 +08:00
LIghtJUNction
201a19a63e Potential fix for code scanning alert no. 46: Use of a broken or weak cryptographic hashing algorithm on sensitive data
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-03-19 17:39:55 +08:00
Yufeng He
2cb6c84eeb feat: context token counting support for multimodal content (images, audio, and chain-of-thought) (#6596)
EstimateTokenCounter 之前只计算 TextPart,完全忽略 ImageURLPart、
AudioURLPart 和 ThinkPart。多模态对话中图片占 500-2000 token,
不被计入会导致 context 压缩触发过晚,API 先报 context_length_exceeded。

改动:
- ImageURLPart 按 765 token 估算(OpenAI vision 低/高分辨率中位数)
- AudioURLPart 按 500 token 估算
- ThinkPart 的文本内容正常计算
- 10 个新测试覆盖各类型单独和混合场景

Co-authored-by: Yufeng He <40085740+universeplayer@users.noreply.github.com>
2026-03-19 17:25:49 +08:00
Soulter
1a1d83d3be fix(wecom-aibot): significantly improve streaming readability and speed via add throttling (#6610)
* fix(wecom-ai): add 0.5s interval for streaming responses

* fix(wecom-ai): correct event type checking and add spacing in WecomAIBotMessageEvent
2026-03-19 17:14:42 +08:00
Scofield
a748264fa4 fix: prevent wecom ai bot long connection replies from disappearing (#6606)
* fix: prevent empty fallback replies from clearing wecom ai bot output

* fix: 优化消息发送逻辑,避免发送空消息

---------

Co-authored-by: shijianhuai <shijianhuai@simuwang.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-19 16:56:15 +08:00
LIghtJUNction
664bc68093 fix: support github pages base path config (#6608) 2026-03-19 16:03:52 +08:00
Ruochen Pan
2cda708eba docs(sandbox): clarify section references in guides (#6591) 2026-03-19 10:07:30 +08:00
Ruochen Pan
7f897887fd feat (doc) : Add doc for shipyard-neo sandbox driver (#6590)
* fix(ui): localize session management group texts

Replace hardcoded Chinese strings in SessionManagementPage with i18n
lookups for group management labels, dialogs, and action feedback.

Add and align translation keys in en-US, ru-RU, and zh-CN for group
management and batch operation messages to ensure consistent multilingual
UI behavior.

* fix(ui): localize interval method hint text

* docs(sandbox): document shipyard neo setup

Expand the Chinese sandbox guide to cover Shipyard Neo as the
recommended driver and distinguish it from legacy Shipyard.

Add deployment and configuration guidance for standalone and
compose-based setups, include a full annotated config example,
and clarify profile selection, TTL behavior, workspace paths,
and persistence semantics.

* docs(sandbox): recommend standalone shipyard neo

Clarify that Shipyard Neo is best deployed on a separate,
better-provisioned host for long-term use.

Update the setup steps and AstrBot connection guidance, and
remove the earlier combined Docker Compose deployment flow.

* docs(sandbox): expand shipyard neo guide

Document Shipyard Neo as the recommended sandbox driver and
clarify how it differs from the legacy Shipyard setup.

Add guidance for deployment, performance requirements, Bay
configuration, profile selection, TTL behavior, workspace
persistence, and browser capability support.

Also reorganize the sandbox configuration section and keep the
legacy Shipyard instructions for compatibility.

* docs(sandbox): fix shipyard neo doc links

Update the sandbox guides in English and Chinese to link
directly to the upstream `config.yaml` example.

Replace duplicated TTL and persistence notes with references
to the dedicated sections to keep the guide concise and easier
to maintain.
2026-03-19 10:00:19 +08:00
LIghtJUNction
b49c3210d9 Update linting rules in pyproject.toml
Added new rules for isort, pyupgrade, flake8-debugger, flake8-print, flake8-pyi, flake8-pytest-style, flake8-tidy-imports, and Ruff-specific rules.
2026-03-19 03:35:58 +08:00
LIghtJUNction
46b7a4e441 move runtime_bootstrap.py 2026-03-19 03:25:24 +08:00
LIghtJUNction
ee1f9dece8 fix:gh-pages 2026-03-19 01:32:43 +08:00
LIghtJUNction
99453652f8 fix(plugin): make temporary requirements context manager async to allow and avoid blocking event loop 2026-03-19 00:04:59 +08:00
LIghtJUNction
6e90937ab4 fix: path 2026-03-18 23:51:33 +08:00
エイカク
40076b6aff fix: set packaged Windows runtime build env for pip native builds (#6575)
* Fix Windows packaged runtime pip build env

* test(pip): cover packaged runtime env injection edges

* refactor(pip): tighten packaged runtime env handling

* test(pip): cover missing runtime build dirs

* fix(pip): build runtime env inside locked section

* test(pip): expand windows path normalization coverage

* refactor(pip): build runtime env from snapshots

* fix(pip): preserve windows env key semantics

* refactor(pip): simplify windows runtime env handling

Keep the in-process pip environment mutation and case-insensitive INCLUDE/LIB handling localized so packaged Windows builds are easier to follow. Add a UNC no-op regression case to guard path normalization.

* refactor(pip): streamline runtime env mutation helpers

Keep packaged Windows pip environment handling easier to follow by reusing a temporary environment context manager, isolating case-insensitive INCLUDE/LIB lookup, and documenting native path normalization behavior.
2026-03-19 00:07:03 +09:00
LIghtJUNction
bb4e9f61f4 Merge branch 'master' into dev 2026-03-18 23:03:00 +08:00
LIghtJUNction
98a8502ebe fix: resolve asynchronous context manager and coroutine attribute issues
- Fixed '_GeneratorContextManager' error in pip_installer.py by using synchronous 'with' for constraints_file().
- Fixed 'CoroutineType' has no attribute 'is_file' in dashboard/routes/config.py by adding missing await.
- Fixed undefined names (Group, ComponentTypes, File, Reply, At) in aiocqhttp_platform_adapter.py.
- Added 'pytest-cov' for code coverage testing.
2026-03-18 22:35:49 +08:00
LIghtJUNction
a410fa3351 fix: path 2026-03-18 21:20:11 +08:00
糯米茨
24554cf443 enhance:更改未完成更新的文档用词问题(多处“消息平台”已更名为“机器人”) (#6568)
* Update kubernetes.md

* Update discord.md

* Update kubernetes.md

* Update AstrBot setup instructions in Kubernetes doc
2026-03-18 21:12:39 +08:00
LIghtJUNction
9cbf253697 chore: remove redundant pdf parser type ignores 2026-03-18 20:12:58 +08:00
LIghtJUNction
a92dfc3913 refactor: simplify cli initialization and uninstall messaging 2026-03-18 20:12:53 +08:00
LIghtJUNction
884efd47cd fix: refresh astrbot root path resolution 2026-03-18 20:12:30 +08:00
LIghtJUNction
1b9820af44 feat: update dashboard 2026-03-18 20:12:22 +08:00
LIghtJUNction
e8c234f0cf feat: improve cli admin setup and api startup logs 2026-03-18 18:21:49 +08:00
LIghtJUNction
14ec513b0d fix: clean lint suppressions and async route errors 2026-03-18 18:06:42 +08:00
LIghtJUNction
26d6d1b36f fix: resolve ruff check issues 2026-03-18 17:38:27 +08:00
LIghtJUNction
fb93949edd fix: resolve ruff async path violations 2026-03-18 17:36:46 +08:00
LIghtJUNction
c9fac2bf82 fix: sync lock file 2026-03-18 17:29:07 +08:00
LIghtJUNction
f6945e0992 chore: remove deploy-dashboard.yml 2026-03-18 17:25:33 +08:00
LIghtJUNction
7fd02cc76a Merge branch 'master' into dev 2026-03-18 17:22:50 +08:00
LIghtJUNction
4bf2f0cb28 fix(dashboard): handle missing static assets gracefully and fix async/ruff issues
- Dashboard: Catch missing index.html error, log warning, and disable WebUI instead of crashing.
- Dashboard: Use anyio.Path for async file existence checks in SSL config.
- CLI/Backup: Replace blocking file operations with anyio async operations.
- Core: Replace blocking file operations with anyio in Coze/Dify clients and TTS simulation.
- Provider: Rename 'timeout' param to 'init_timeout'/'request_timeout' to fix ASYNC109 warnings.
- Ruff: Fix various ASYNC230/ASYNC240 errors across multiple files.
2026-03-18 16:46:22 +08:00
camera-2018
4e5587998b perf(dashboard): subset MDI icon font and self-host Google Fonts (#6532)
* perf(dashboard): subset MDI icon font and self-host Google Fonts

* perf(dashboard): subset MDI icon font and self-host Google Fonts

* perf(dashboard): subset MDI icon font and self-host Google Fonts

* perf(dashboard): subset MDI icon font cr fix

* chore: update lockfile
2026-03-18 16:32:19 +08:00
LIghtJUNction
f1ad60982c feat(cli): init cmd supports restoring from backup 2026-03-18 16:02:32 +08:00
LIghtJUNction
b301ff21f2 feat(cli): enhance run/init/help cmds & service config support 2026-03-18 14:16:25 +08:00
LIghtJUNction
ad3e5c473a Merge conflict resolution 2026-03-18 14:16:14 +08:00
LIghtJUNction
12cdf454b4 feat(cli): enhance run/init/uninstall for systemd & debug; refactor(env): standardize vars 2026-03-18 13:52:00 +08:00
LIghtJUNction
b839de2050 fix(discord): handle timeout error on shutdown; chore(cli): remove systemd service creation 2026-03-18 12:56:05 +08:00
Yufeng He
412e2e07cc Clarify FileUpload/DownloadTool descriptions to fix LLM tool selection (#6527)
Multiple models (Gemini 3, GPT-5.2, Claude Sonnet, Kimi K2.5) consistently
pick FileDownloadTool when they should pick FileUploadTool. The old
descriptions used "upload/download" which is ambiguous from the LLM's
perspective — it doesn't know which side is "local" vs "remote".

Rewrite descriptions to use explicit directional language:
- Upload: "Transfer FROM host INTO sandbox" + "when user sends a file"
- Download: "Transfer FROM sandbox OUT to host" + "ONLY when user asks
  to retrieve/export"

Also improve parameter descriptions with the same directional clarity.

Fixes #6497

Co-authored-by: Yufeng He <40085740+universeplayer@users.noreply.github.com>
2026-03-18 09:34:48 +08:00
LIghtJUNction
2946460484 update astrbot.service 2026-03-18 01:22:43 +08:00
LIghtJUNction
73517ec2a5 更新 cmd_init.py 2026-03-18 00:35:29 +08:00
LIghtJUNction
87b50a5fd5 fix/ astrbot.service, update path 2026-03-18 00:34:26 +08:00
LIghtJUNction
9877abc472 更新 cmd_init.py 2026-03-18 00:22:21 +08:00
LIghtJUNction
7eafa3a2e2 update astrbot.service 2026-03-18 00:21:27 +08:00
鸦羽
c22e1f6a4d fix: restrict workflows to upstream repo (#6531) 2026-03-17 23:35:16 +08:00
Soulter
51c8d22d05 feat: install plugin using metadata name and validate importable identifiers (#6530)
* feat: install plugin using metadata name and validate importable identifiers

* fix: cleanup temporary upload extraction directory on plugin install failure

* Update astrbot/core/star/star_manager.py

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

* fix: avoid unnecessary install when repository directory already exists

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-17 23:23:59 +08:00
LIghtJUNction
c1ad6f7032 fix(core): use explicit import for anyio.to_thread to resolve static analysis issue
This resolves a 'BrokenWorkerInterpreter' attribute access error reported by basedpyright.
2026-03-17 22:52:33 +08:00
LIghtJUNction
b53f042a6d fix(core): ensure parent directories exist before saving skill config and cache; fix async file read in star_manager 2026-03-17 22:33:56 +08:00
LIghtJUNction
6dc13b880b refactor: rename skills_like to lazy_load and add skill schema support 2026-03-17 21:32:06 +08:00
LIghtJUNction
f3d6f762c3 refactor: rename skills_like to lazy_load and add skill schema support 2026-03-17 20:46:07 +08:00
shuiping233
718215425d refactor: downgrade StrEnum to (str, Enum) in kook_type for backward compatibility (#6512)
我那时候搓 #5719 的时候 #5729 已经合并了, 既然ruff的py限制版本里是`3.12`,那我那时候干脆用的StrEnum,现在发现那个pr revert了,那我也降级回旧Enum写法好了
2026-03-17 19:58:40 +08:00
Soulter
6be8a4302d docs: add aiocqhttp and satori protocol documentation; remove outdated lagrange and napcat guides 2026-03-17 19:56:08 +08:00
Soulter
62be8d2600 perf: improve onebot and satori documents 2026-03-17 19:33:51 +08:00
LIghtJUNction
4c0fb31e7d Refactor theme constants and resolve merge conflicts 2026-03-17 19:27:50 +08:00
Kangyang Ji
7aae048405 feat(dashboard): add auto switch theme (default off) (#6405)
* feat(dashboard): add auto switch theme (default off)
feat(dashboard): move all get theme and set theme by check current theme into stores/customizer

* feat(dashboard): fix duplicate for auto switch theme
根据Gemini的意见更改了一些地方。
将原本的状态更新挪到了App.vue里,可以去除很多地方更新theme所需要的theme依赖。
将翻译修改了
将监听器改为了watch
2026-03-17 19:06:01 +08:00
qingyun
df1e59e01c fix(core): use original version constraints instead of locking to installed version (#6445)
* feat: Add OpenRouter chat completion provider adapter with custom headers. (#6436)

* chore: update astrbot.service configuration

* fix(core): use original version constraints instead of locking to installed version

Fixes #6420

The core constraints mechanism was using the currently installed version as
an exact constraint (e.g., `aiosqlite==0.21.0`), preventing plugins from
installing higher versions even when they satisfy the original constraint.

Changes:
- Preserve original version specifier from pyproject.toml (e.g., `>=0.21.0`)
- Allow plugins to require higher versions as long as they satisfy core constraint
- Prevent downgrade by using `>=installed` for packages without version constraint

Example:
- Before: Core constraint `aiosqlite==0.21.0`, plugin requires `>=0.22.1` → BLOCKED
- After: Core constraint `aiosqlite>=0.21.0`, plugin requires `>=0.22.1` → ALLOWED

This enables better dependency management while still protecting core dependencies
from incompatible downgrades.

---------

Co-authored-by: Futureppo <luominzhi2005@qq.com>
Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
Co-authored-by: ccsang <ccsang@users.noreply.github.com>
2026-03-17 18:59:24 +08:00
LIghtJUNction
25f9effcc9 Merge branch 'master' into dev 2026-03-17 18:53:46 +08:00
LIghtJUNction
5caf3a4793 chore: update AGENTS.md 2026-03-17 18:52:44 +08:00
LIghtJUNction
458e8e0db8 fix(cli): recover flags consumed by -E option and prompt for recipient 2026-03-17 18:48:19 +08:00
LIghtJUNction
976398d1f2 feat(cli): enhance backup capabilities and refactor path management
- Introduce 'astrbot bk' command with GPG signing, encryption, and digest support
- Add import/export functionality using core backup modules
- Refactor path management to use 'AstrbotPaths' singleton across CLI commands
- Replace blocking subprocess calls with asyncio.create_subprocess_exec in backup command
- Add comprehensive tests for uninstall and backup commands
- Improve module resource handling for bundled dashboard assets
2026-03-17 18:32:32 +08:00
shuiping233
f5ba1a026a perf: Implement Pydantic data models for the KOOK adapter to enhance data retrieval and message schema validation (#5719)
* refactor: 给kook适配器添加kook事件数据类

* format: 使用StrEnum替换kook适配器中的(str,enum)
2026-03-17 18:05:58 +08:00
jnMetaCode
dcffb5269a fix: only pass dimensions when explicitly configured in embedding config (#6432)
* fix: only pass dimensions param when explicitly configured

Models like bge-m3 don't support the dimensions parameter in the
embedding API, causing HTTP 400 errors. Previously dimensions was
always sent with a default value of 1024, even when the user never
configured it. Now dimensions is only included in the request when
embedding_dimensions is explicitly set in provider config.

Closes #6421

Signed-off-by: JiangNan <1394485448@qq.com>

* fix: handle invalid dimensions config and align get_dim return

- Add try-except around int() conversion in _embedding_kwargs to
  gracefully handle invalid embedding_dimensions config values
- Update get_dim() to return 0 when embedding_dimensions is not
  explicitly configured, so callers know dimensions weren't specified
  and can handle it accordingly
- Both methods now share consistent logic for reading the config

Signed-off-by: JiangNan <1394485448@qq.com>

* fix: improve logging for invalid embedding_dimensions configuration

---------

Signed-off-by: JiangNan <1394485448@qq.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-17 17:53:03 +08:00
LIghtJUNction
4b7d42c2a3 chore: ruff format 2026-03-17 16:53:45 +08:00
LIghtJUNction
f6321be8c8 sync 2026-03-17 16:51:45 +08:00
whatevertogo
ebd232ec8e fix: register_agent decorator NameError (#5765)
* fix: 修改 register_agent 以避免运行时导入 AstrAgentContext

* test: improve register_agent test robustness

- Add fixture for llm_tools cleanup to avoid test interference
- Use multiple import patterns to make guard more robust to refactors
- Add assertion to verify decorated coroutine is wired as handoff handler

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

* 删除测试文件: 移除 register_agent 装饰器的运行时行为测试

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-17 16:07:30 +08:00
whatevertogo
1fd3d4ce0e fix: subagent lookup failure when using default persona (#5672)
* fix: resolve subagent persona lookup for 'default' and unify resolution logic

- Add PersonaManager.get_persona_v3_by_id() to centralize v3 persona resolution
- Handle 'default' persona_id mapping to DEFAULT_PERSONALITY in subagent orchestrator
- Fix HandoffTool.default_description using agent_name parameter correctly
- Add tests for default persona in subagent config and tool deduplication

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

* refactor: simplify get_default_persona_v3 using get_persona_v3_by_id

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

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-03-17 15:42:15 +08:00
linzhengtian
26d69c96d1 fix: reading skills on Windows (#6490)
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.
2026-03-17 15:12:02 +08:00
YYMa
3dcdb8b29c chore: remove deprecated version field from compose.yml (#5495)
The version field is no longer required in Docker Compose v2 and has been deprecated.
2026-03-17 14:20:35 +08:00
dependabot[bot]
437adead28 chore(deps): bump the github-actions group with 2 updates (#6461)
Bumps the github-actions group with 2 updates: [ncipollo/release-action](https://github.com/ncipollo/release-action) and [actions/github-script](https://github.com/actions/github-script).


Updates `ncipollo/release-action` from 1.20.0 to 1.21.0
- [Release notes](https://github.com/ncipollo/release-action/releases)
- [Commits](https://github.com/ncipollo/release-action/compare/v1.20.0...v1.21.0)

Updates `actions/github-script` from 7 to 8
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

---
updated-dependencies:
- dependency-name: ncipollo/release-action
  dependency-version: 1.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-17 13:53:37 +08:00
Rhonin Wang
d5b98b353c fix: parse multiline frontmatter description in SKILL.md (#6460)
* fix(skills): support multiline frontmatter descriptions

* fix(skills): 修复多行 frontmatter 描述解析

* style(skills): clean up frontmatter parser follow-ups

---------

Co-authored-by: RhoninSeiei <RhoninSeiei@users.noreply.github.com>
2026-03-17 13:53:16 +08:00
Yufeng He
acbc5150cf fix: SQLite 'database is locked' by adding busy timeout (#6474)
The async engine is created without a busy timeout, so concurrent
writes (agent responses, metrics, session updates) fail instantly
with 'database is locked' instead of waiting for the lock.

Add connect_args={'timeout': 30} for SQLite engines so the driver
waits up to 30 seconds for the write lock. Combined with the existing
WAL journal mode, this handles the typical concurrent write bursts
from agent + metrics + session operations.

Fixes #6443
2026-03-17 12:56:34 +08:00
Ruochen Pan
85cfd62014 feat: localize session management group & interval method texts (#6471)
* fix(ui): localize session management group texts

Replace hardcoded Chinese strings in SessionManagementPage with i18n
lookups for group management labels, dialogs, and action feedback.

Add and align translation keys in en-US, ru-RU, and zh-CN for group
management and batch operation messages to ensure consistent multilingual
UI behavior.

* fix(ui): localize interval method hint text
2026-03-17 10:21:55 +08:00
LIghtJUNction
1c7c2ee0cd chore: Delete .github/workflows/pr-checklist-check.yml 2026-03-17 10:18:08 +08:00
Soulter
ed47420678 ci: add pr check 2026-03-17 01:07:22 +08:00
Soulter
6d687691a2 chore: bump version to 4.20.1 2026-03-17 00:35:57 +08:00
LIghtJUNction
6db0959bb1 feat(cli): implement uninstall command and add log-level option
- Implement 'astrbot uninstall' to remove systemd service and data files
- Add '--log-level' option to 'astrbot run' (default: INFO)
- Pass log level config to core logger via env var
2026-03-16 23:55:36 +08:00
Soulter
0c71d351ee chore: revise PULL_REQUEST_TEMPLATE 2026-03-16 22:20:48 +08:00
LIghtJUNction
f00ba5adc6 chore(github): 更新 PR 模板以区分 dev 和 master 提交规则 2026-03-16 21:43:14 +08:00
LIghtJUNction
a05bfed15d Merge pull request #6434 from a61995987/fix-修正shell工具未正确应用工具调用超时的问题
Fix 修正shell工具未正确应用工具调用超时的问题
2026-03-16 20:51:03 +08:00
LIghtJUNction
a027fb310c Update astrbot/core/computer/tools/shell.py
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-16 20:34:17 +08:00
LIghtJUNction
d3d4e1db7b Merge branch 'master' of https://github.com/AstrBotDevs/AstrBot 2026-03-16 19:17:42 +08:00
LIghtJUNction
78b3e12c66 chore: update astrbot.service configuration 2026-03-16 19:15:44 +08:00
Futureppo
c42ac87ee1 feat: Add OpenRouter chat completion provider adapter with custom headers. (#6436) 2026-03-16 19:11:43 +08:00
Chen
4b0d9ae979 Merge branch 'fix-修正shell工具未正确应用工具调用超时的问题' of https://github.com/a61995987/AstrBot into fix-修正shell工具未正确应用工具调用超时的问题 2026-03-16 18:11:12 +08:00
Chen
a1a3db2218 fix-修正shell工具未正确应用工具调用超时的问题 2026-03-16 18:10:23 +08:00
Chen
3e278dbd9e Merge branch 'AstrBotDevs:master' into fix-修正shell工具未正确应用工具调用超时的问题 2026-03-16 18:02:15 +08:00
LIghtJUNction
7733ccc54a Merge pull request #6429 from xkeyC/feat/persona_clone
feat: add clone persona functionality
2026-03-16 17:23:01 +08:00
LIghtJUNction
9c7c0ec95a Merge pull request #6404 from rin259/feat/onebot-file-send
feat: add OneBot V11 file API support for sending files
2026-03-16 17:08:39 +08:00
LIghtJUNction
2685528cbd Merge pull request #6397 from AstrBotDevs/master
sync master-﹥dev
2026-03-16 17:03:40 +08:00
LIghtJUNction
3f24f82486 Merge branch 'master' into dev 2026-03-16 17:02:15 +08:00
xkeyC
38f21675d5 feat: 支持克隆人格 2026-03-16 16:52:01 +08:00
QuietStars
3fbd16b211 docs: update rainyun.md with backup access instructions (#6427)
Added a note about using a backup address if the management panel cannot be accessed.
2026-03-16 15:38:01 +08:00
qingyun
e77500ff69 fix(provider): sync providers_config after creating new provider (#6388)
Fixes #6283

When adding a new embedding provider, the knowledge base creation page
did not show the new provider until restart.

Root cause: create_provider() did not update self.providers_config,
which is used by get_provider_config_list() to return provider lists.

This fix syncs the in-memory config after loading the new provider,
consistent with how reload() handles config updates.

Co-authored-by: ccsang <ccsang@users.noreply.github.com>
2026-03-16 15:29:51 +08:00
lppsuixn
2c49ac0dcf Refactor _extract_session_id for chat type handling (#5775)
Update session ID extraction to handle group and single chat types.
2026-03-16 15:27:16 +08:00
LIghtJUNction
c0e07971b3 Merge pull request #6391 from ccsang/fix/tool-result-multiple-content
fix(agent): process all content items in CallToolResult, not just the first
2026-03-16 15:21:17 +08:00
Rin
7cce05c459 fix: remove accidentally added commit message from code 2026-03-16 14:37:52 +08:00
rin
0a16df2837 fix: add missing logger import 2026-03-16 14:35:34 +08:00
LIghtJUNction
e2365a53b9 Update README_zh.md 2026-03-16 13:34:36 +08:00
LIghtJUNction
7dc142ddf2 docs: synchronize multi-language READMEs with README_zh.md 2026-03-16 13:33:29 +08:00
Soulter
65decfbe87 chore: remove unused scripts for closing duplicate plugin publish issues and generating changelog 2026-03-16 12:39:39 +08:00
stevessr
92c31192de perf: enhance umo processing compatibility (#5996) 2026-03-16 12:34:21 +08:00
Soulter
414f98fb5e perf: onebot, satori docs improvement 2026-03-16 11:41:25 +08:00
ccsang
8e6c835b85 refactor(agent): extract image-handling logic into helper function
Address Sourcery AI review feedback: the image-handling logic was
duplicated for ImageContent and EmbeddedResource cases.

Changes:
- Extract _handle_image_content() helper function
- Consolidate image caching, result appending, and yielding logic
- Reduce code duplication and improve maintainability
2026-03-16 00:17:33 +00:00
ccsang
fb2a2a63f2 fix(agent): process all content items in CallToolResult, not just the first
Fixes #6140

When a tool returns CallToolResult with multiple content items (e.g.,
both TextContent and ImageContent), the agent was only processing
content[0], ignoring the rest.

Changes:
- Replace direct content[0] access with enumerate(res.content) loop
- Process all content items: TextContent, ImageContent, EmbeddedResource
- Use content_index for image caching to distinguish multiple images

This fixes the issue where tools like Bilibili plugin return both
text descriptions and screenshots, but LLM only received one of them.
2026-03-16 00:17:33 +00:00
LIghtJUNction
b795f804a7 更新 pr-checklist-check.yml 2026-03-16 02:51:39 +08:00
LIghtJUNction
bc3b5e58a4 更新 pr-checklist-check.yml 2026-03-16 02:44:05 +08:00
LIghtJUNction
7e3c32b828 更新 pr-checklist-check.yml 2026-03-16 02:29:33 +08:00
LIghtJUNction
ceb32dce9f 更新 pr-checklist-check.yml 2026-03-16 02:24:01 +08:00
LIghtJUNction
84e880af5f 更新 pr-checklist-check.yml 2026-03-16 02:21:05 +08:00
LIghtJUNction
9909d774ed Merge pull request #6400 from AstrBotDevs/copilot/implement-modifications-summary
feat: auto-close PRs when author checks "did not read" checklist item
2026-03-16 02:13:20 +08:00
LIghtJUNction
6b3868b4be Update pr-checklist-check.yml 2026-03-16 02:11:15 +08:00
LIghtJUNction
11c840953a 更新 pr-checklist-check.yml 2026-03-16 01:49:49 +08:00
LIghtJUNction
2bbca887ce Refine PR checklist validation and closure message
Updated the checklist validation script and modified the comment for PR closure.
2026-03-16 01:46:07 +08:00
copilot-swe-agent[bot]
dd89a4b334 feat: add PR checklist enforcement workflow
Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>
2026-03-15 17:30:29 +00:00
copilot-swe-agent[bot]
a3fa8a5a7c Initial plan 2026-03-15 17:28:39 +00:00
LIghtJUNction
aa60467782 Merge pull request #6399 from AstrBotDevs/LIghtJUNction-patch-1
Refactor checklist items in PR template
2026-03-16 01:24:30 +08:00
LIghtJUNction
d936bb0a10 Refactor checklist items in PR template
Duplicated checklist items in the pull request template for clarity and emphasis.
2026-03-16 01:23:51 +08:00
LIghtJUNction
3f863cce7f Merge pull request #6389 from AstrBotDevs/copilot/create-daily-build-workflow
feat: daily workflow to build dashboard with Bun and deploy to GitHub Pages
2026-03-15 23:45:13 +08:00
copilot-swe-agent[bot]
c42bd3150d feat: add daily workflow to build dashboard with bun and deploy to GitHub Pages
Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>
2026-03-15 15:39:48 +00:00
copilot-swe-agent[bot]
4c22abd99c Initial plan 2026-03-15 15:37:59 +00:00
LIghtJUNction
f08147dc38 更新 smoke_test.yml 2026-03-15 23:36:25 +08:00
LIghtJUNction
11d40ac0c3 更新 smoke_test.yml 2026-03-15 23:35:21 +08:00
Stable Genius
64e0183b55 fix: drop Groq reasoning_content from assistant history (#6065)
Co-authored-by: Stable Genius <259448942+stablegenius49@users.noreply.github.com>
2026-03-15 22:51:52 +08:00
Soulter
420d82df11 chore: ruff format 2026-03-15 22:43:29 +08:00
Yufeng He
d87cf897da Fix TypeError when API returns null choices (#6313)
* Fix CreateSkillPayloadTool array schema missing items field

The payload parameter's anyOf array variant lacked an items field,
causing Gemini API to reject the tool declaration with 400 Bad Request:
'parameters.properties[payload].any_of[1].items: missing field.'

Add items: {type: object} to the array variant to satisfy the Gemini
API requirement for array type schemas.

Fixes #6279

* Fix TypeError when OpenAI-compatible API returns null choices

Some providers (e.g. OpenRouter) may return a completion where
choices is None rather than an empty list — for instance on rate
limiting, content filtering, or transient errors. The existing code
used len(completion.choices) which throws TypeError on None.

Replace all len(...choices) == 0 checks with 'not ... .choices' which
handles both None and empty list. Affects _query_stream, _parse_openai_completion,
and _extract_reasoning_content.

Fixes #6252
2026-03-15 22:28:26 +08:00
時壹
2f51916a73 fix: deduplicate repeated QQ webhook retry callbacks (#6320) 2026-03-15 22:18:37 +08:00
Rin
b0e10cf479 fix: add null check for delta in streaming mode to prevent AttributeError when tool calls are returned (#6365) 2026-03-15 22:17:12 +08:00
Simon
20efaa5320 fix: revise link to model service configuration (#6296) 2026-03-15 22:03:52 +08:00
洛薇Lovie
3ccd70cd4e Fix: AI fails to send media files when tool-calling mode is set to "skills-like". (#6317)
* fix: improve send_message_to_user tool description for skills_like mode

* fix: enhance description for send_message_to_user tool to clarify usage

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-15 21:46:01 +08:00
xwsjjctz
da520e573a feat(provider): add MiniMax (#6318)
* feat(provider): add MiniMax

* feat(provider): reintroduce MiniMax provider configuration and remove deprecated source

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-15 21:37:44 +08:00
Trainingcqy
6d055e81e9 fix: GIF sent as static image in Telegram adapter (#6329)
* fix(telegram): route GIF files to send_animation instead of send_photo

* fix: narrow exception in _is_gif to OSError

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

* refactor: simplify image send dispatch in send_with_client

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

* refactor: simplify image dispatch in _process_chain_items

* ruff format

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-15 21:33:30 +08:00
Xial
d41ccb70c5 fix: replace npm registry URLs with jsdelivr CDN for provider icons (#6340) 2026-03-15 21:15:04 +08:00
qingyun
18a99a25c2 fix(platform): parse QQ official face messages to readable text (#6355)
Fixes #6294

QQ official bot receives emoji/sticker messages as raw XML-like tags:
`<faceType=4,faceId="",ext="eyJ0ZXh0IjoiW+a7oeWktOmXruWPt10ifQ==">`

This made the LLM unable to understand the emoji content.

Changes:
- Added `_parse_face_message()` method to parse face message format
- Decode base64 `ext` field to get emoji description text
- Replace face tags with `[表情:描述]` format for readability

Example:
- Input: `<faceType=4,faceId="",ext="eyJ0ZXh0IjoiW+a7oeWktOmXruWPt10ifQ==">`
- Output: `[表情:[满头问号]]`

Co-authored-by: ccsang <ccsang@users.noreply.github.com>
2026-03-15 21:05:47 +08:00
LIghtJUNction
04aee2890a feat: implement dashboard download caching and fallback mechanism
- Add local file caching for dashboard downloads with version validation
- Implement fallback to 'latest' version if specific version download fails
- Add robust error handling in CLI check_dashboard to prevent crashes
- Remove dashboard caching from smoke tests (backend-only mode)
2026-03-15 19:14:13 +08:00
LIghtJUNction
c18165909e 修复: 尝试下载当前版本的dashboard,如果下载失败(开发版本),回退为下载最新版本 2026-03-15 18:18:23 +08:00
LIghtJUNction
0b534f65c2 fix(dashboard): use absolute path for bundled dist and handle 404s gracefully 2026-03-15 18:05:15 +08:00
LIghtJUNction
c9910d4a66 fix(dashboard): add early check for missing index.html to prevent 404s 2026-03-15 18:01:55 +08:00
LIghtJUNction
342b378de1 Updated READMEs 2026-03-15 17:45:12 +08:00
LIghtJUNction
7579db11be chore: bump version to 4.21.0 and refactor version retrieval 2026-03-15 17:08:31 +08:00
LIghtJUNction
b5a40a66fa sync/pnpm-lock.yaml 2026-03-15 16:51:42 +08:00
LIghtJUNction
282ff8d414 fix(dashboard): improve visibility of inline code in announcements
- Update CSS for inline code elements in the welcome announcement section
- Ensure proper contrast and emphasis in both light and dark modes
- Fix issue where code blocks appeared as white boxes in dark mode
2026-03-15 16:47:53 +08:00
LIghtJUNction
f3cdb7c006 fix(dashboard): restore original header logo layout
- Replaced Logo component with original inline text implementation in VerticalHeader
- Added missing isChristmas computed property
- Removed v-spacer centering for logo to match master branch layout
- This fixes the display issue where the logo/title appeared incorrect or misaligned
2026-03-15 16:35:58 +08:00
LIghtJUNction
c3afc3d72b fix(dashboard): resolve header layout issues and restore sidebar toggle
- Replace constrained v-container with full-width div in app bar
- Add 'app' prop to v-app-bar to fix layout flow
- Restore missing sidebar toggle buttons for desktop/mobile
- Clean up unused dev dependencies in package.json
2026-03-15 16:28:26 +08:00
LIghtJUNction
0c74bd1aeb fix: restore missing _poll_webchat_stream_result function 2026-03-15 15:58:47 +08:00
LIghtJUNction
070f281dae Resolve merge conflict in StandaloneChat.vue 2026-03-15 15:45:04 +08:00
LIghtJUNction
28a0f372fc Update vite version to match lockfile 2026-03-15 15:43:17 +08:00
邹永赫
d7457f38d4 fix: handle webchat image outputs without streaming 2026-03-15 16:15:43 +09:00
LIghtJUNction
96cafe001d Merge pull request #6293 from AstrBotDevs/LIghtJUNction-patch-1
Update package.md
2026-03-15 03:15:10 +08:00
LIghtJUNction
29d100dd83 Update package.md 2026-03-15 02:55:34 +08:00
Soulter
14f3701c4a fix: update Discord invite link in community documentation
closes: #6188
2026-03-14 23:48:13 +08:00
Stable Genius
1044fc48ca fix: avoid webchat stream result crash on queue errors (#6123)
Co-authored-by: stablegenius49 <185121704+stablegenius49@users.noreply.github.com>
2026-03-14 23:41:28 +08:00
Soulter
693c2ca818 refactor: improve chat component behavior, use shiki to represent code block (#6286) 2026-03-14 23:37:17 +08:00
LIghtJUNction
da1565ee81 Merge pull request #6282 from advent259141/agent-fix-clean
Agent fix clean
2026-03-14 23:32:16 +08:00
Gao Jinzhe
7d3401fec0 Merge branch 'dev' into agent-fix-clean 2026-03-14 23:17:10 +08:00
LIghtJUNction
fca691b3ca Merge pull request #6276 from AstrBotDevs/feat/optional-backend
Feat/optional backend
2026-03-14 21:40:06 +08:00
LIghtJUNction
ca8f356812 Resolve conflicts in dashboard files 2026-03-14 21:36:35 +08:00
Soulter
b1c486ba98 feat: add send shortcut configuration and localization support for chat input (#6272) 2026-03-14 21:25:12 +08:00
Soulter
9363fb824a chore: ruff format 2026-03-14 21:12:00 +08:00
Flartiny
044b361ac5 feat: add conversation batch deletion for webchat (#6160)
* feat: add conversation batch deletion for webchat

* fix: security issues in batch_delete_sessions and better handle batch select

* feat: enhance batch selection UI with animated checkbox visibility in ConversationSidebar

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-14 21:09:36 +08:00
Frank
06fd2d2428 fix: preserve subagent handoff tools during plugin filtering (#6155) 2026-03-14 20:55:15 +08:00
eason
dd6bc1dcdb fix: add missing spaces in cron prompt and replace deprecated utcnow() (#6192)
1. Fix missing spaces in cron job wake prompt string concatenation.
   Python implicit string concatenation produced:
   "...scheduled taskProceed..." and "...conversation.After..."
   which sent garbled instructions to the LLM agent, causing unreliable
   cron job execution.

2. Replace deprecated datetime.utcnow() with
   datetime.now(datetime.timezone.utc) in JWT generation.
   utcnow() is deprecated since Python 3.12 and returns naive datetime
   which can cause incorrect token expiry on non-UTC systems.

Closes #6103
Closes #6165

Co-authored-by: easonysliu <easonysliu@tencent.com>
2026-03-14 20:52:00 +08:00
Rhonin Wang
52d5258b10 feat: display latency when testing model connection (#6258)
Co-authored-by: RhoninSeiei <RhoninSeiei@users.noreply.github.com>
2026-03-14 20:50:40 +08:00
Anima
91933bbd19 perf: webui theme color improvement (#6263)
* fix: update scrollbar styles to follow theme variables

* fix: update theme colors to use CSS variables for consistency

* fix: change login button color to primary for better visibility

* fix: update theme colors for Dark and Light themes; change login button color to secondary

* fix: update border and theme colors for consistency in DarkTheme

* fix: update sidebar list class to conditionally hide scrollbar in mini sidebar mode

* fix: simplify button visibility logic and remove unnecessary leftPadding style

* fix: refactor language switcher to use grouped menu for better UX

* fix: update theme colors to use primary color for consistency across components

* fix: add preview text for template output in multiple languages
2026-03-14 20:45:55 +08:00
Sakari
f8d075b5d3 fix(telegram): avoid treating normal replies as topic threads (#6174) 2026-03-14 18:27:13 +08:00
LIghtJUNction
a4a0a5bb1a Resolve conflicts 2026-03-14 18:24:48 +08:00
eason
86ef758a9a fix: prevent ValueError when removing already-removed API key in retry loop (#6193)
In _handle_api_error(), when a 429 rate-limit is encountered, the code
calls available_api_keys.remove(chosen_key). If the same key was already
removed in a previous retry iteration (e.g. the key rotated back to the
same value), this raises ValueError which crashes the entire LLM request
with an opaque error instead of a proper retry/fallback.

Add a membership check before calling remove() to prevent the crash.

Co-authored-by: easonysliu <easonysliu@tencent.com>
2026-03-14 18:22:14 +08:00
Ann-Holmes
1a03180643 Add binding for local temp directory in YAML (#6191)
* Add binding for local temp directory in YAML

Bind the local temp directory to the sandbox for file access.

* Update compose-with-shipyard.yml

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

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-03-14 18:21:47 +08:00
DroidKali
326183a3fd fix: update startup command to 'astrbot run' in all README files (#6189)
Updated the quick start command from 'astrbot' to 'astrbot run' across all
language versions of README documentation for consistency and correctness.

Co-authored-by: DroidKali <DroidKali@users.noreply.github.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-03-14 18:20:48 +08:00
qingyun
08fc657755 fix: preserve whitespace in Plain.toDict() for @ mentions (#6244)
* fix: preserve whitespace in Plain.toDict() for @ mentions

- Remove .strip() from Plain.toDict() to match async to_dict() behavior
- Fixes #6237: QQ @mentions no longer lose trailing spaces
- This ensures '@user message' displays correctly instead of '@usermessage'

* refactor: remove redundant to_dict() from Plain class

- Let Plain inherit to_dict() from BaseMessageComponent
- BaseMessageComponent.to_dict() calls toDict() by default
- Reduces code duplication and prevents future divergence
- Addressed code review feedback from @gemini-code-assist and @sourcery-ai

* feat: add async to_dict method to Plain message component

* fix: add return type hint to Plain.toDict method

---------

Co-authored-by: ccsang <ccsang@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-14 18:18:14 +08:00
Gao Jinzhe
0ff9539599 Merge pull request #6208 from nuomicici/master
更新(添加)部分文档中已过时的名词
2026-03-14 18:17:14 +08:00
lalala
38f5e077ee fix: remove duplicate dependencies (#6247)
remove duplicate `aiocqhttp` `aiodocker` `aiohttp` in requirements.txt
2026-03-14 18:15:06 +08:00
MousseC
89fbd75e7a perf(OneBot): add a whitespace after At component (#6238)
修复 At 组件后的空格在发送时被 strip 移除的问题。在消息解析时检测 At 组件并在其后额外插入空格。
2026-03-14 18:12:55 +08:00
Salman Chishti
493662524a ci: upgrade GitHub Actions to latest versions (#6251)
Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
2026-03-14 18:08:25 +08:00
糯米茨
1afbb357db Update docs/zh/platform/matrix.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-13 21:14:00 +08:00
糯米茨
8d2140f607 Update docs/zh/platform/wecom_ai_bot.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-13 21:13:45 +08:00
糯米茨
97732987d9 更新部分新版名称 2026-03-13 20:53:41 +08:00
糯米茨
a60a40bca3 更新部分新版本名称
Update the instructions for installing and configuring the Matrix adapter in AstrBot.
2026-03-13 20:51:39 +08:00
エイカク
a8ff2b3d9c fix(dashboard): stabilize sidebar hash navigation on startup (#6159)
* fix(dashboard): stabilize sidebar hash navigation on startup

* fix(dashboard): reuse shared extension tab route helpers

* fix(dashboard): avoid leaking extension route query state

* fix(dashboard): preserve route params in tab locations

* fix(dashboard): harden hash tab routing fallbacks

* fix(dashboard): warn on tab route navigation failures

* fix(dashboard): harden extension tab startup routing
2026-03-13 11:53:50 +09:00
advent259141
3a8bfa0873 style: ruff format on merge-touched files 2026-03-13 09:20:08 +08:00
advent259141
c07fba7add merge: resolve conflicts with origin/master
- .gitignore: keep both .serena and .worktrees/ entries
- astr_main_agent_resources.py: keep deletion (refactored to tools/)
- send_message.py: port video message type support from master
2026-03-13 09:17:31 +08:00
zenfun
855483c8c2 style: fix ruff I001/F401 violations in changed files 2026-03-13 01:18:39 +08:00
zenfun
048c511b18 fix: align browser property with base class and remove dead env writes
- shipyard_neo: browser property now returns None when not initialized
  instead of raising RuntimeError, matching ComputerBooter base contract
- computer_tool_provider: remove dead os.environ writes for shipyard
  (SHIPYARD_ENDPOINT / SHIPYARD_ACCESS_TOKEN are never read anywhere)
  and remove unused os import
2026-03-13 01:14:23 +08:00
zenfun
dfc0c34d95 fix: address review issues in tool injection refactor
- Rewrite TestApplySandboxToolsRefactored to test ComputerToolProvider
  directly (_apply_sandbox_tools was removed; old tests permanently skipped)
- Add TestExecutorCapabilityGuard with 5 strict tests for browser
  capability rejection at executor level
- Fix typo: "on hehalf you" -> "on behalf of you" in subagent result
- Remove extra blank lines (ruff E303) after _apply_sandbox_tools comment
- Remove dead _build_sync_and_scan_command (no callers after refactor)
2026-03-13 01:11:50 +08:00
Soulter
a21bb5b234 chore: bump version to 4.20.0 2026-03-13 00:33:36 +08:00
Soulter
994d39241e chore: ruff format 2026-03-13 00:26:40 +08:00
2ndelement
e6c1164755 perf(QQ Official API): improve streaming message delivery reliability and proactive media sending (#6131)
* fix(qqofficial): fix streaming message delivery for C2C

* fix(qqofficial): rewrite send_streaming for C2C vs non-C2C split

* fix(qqofficial): add _extract_response_message_id for safe id extraction

* fix(qqofficial): flush stream segment on tool-call break signal

* fix(qqofficial): downgrade rich-media to non-stream send in C2C

* fix(qqofficial): auto-append \n to final stream chunk (state=10)

* fix(qqofficial): propagate stream param to all _send_with_markdown_fallback call sites

* fix(qqofficial): retry on STREAM_MARKDOWN_NEWLINE_ERROR with newline fix

* fix(qqofficial): handle None/non-dict response in post_c2c_message gracefully

* fix(qqofficial): remove msg_id from video/file media payloads in send_by_session

QQ API rejects msg_id on proactive media (video/file, msg_type=7) messages
sent via the tool-call path, returning "请求参数msg_id无效或越权". The
msg_id passive-reply credential is consumed by the first send and cannot be
reused for subsequent media uploads in the same session.

Remove msg_id from the payload after setting msg_type=7 for video and file
sends, for both FRIEND_MESSAGE (C2C) and GROUP_MESSAGE paths.

* fix(qqofficial): replace deprecated get_event_loop() with get_running_loop()

asyncio.get_event_loop() is deprecated since Python 3.10 and raises a
DeprecationWarning (or errors) when called from inside a running coroutine
without a current event loop set on the thread.  Replace both call-sites
in the streaming throttle logic with asyncio.get_running_loop(), which is
the correct API to use inside an already-running async context.

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

---------

Co-authored-by: 2ndelement <2ndelement@users.noreply.github.com>
Co-authored-by: Claude Sonnet <noreply@anthropic.com>
2026-03-13 00:24:15 +08:00
Aleksandr
89cc8a1a65 feat: add Russian translation (#6081)
* feat: add Russian translation

* revert: remove auth route changes from PR
2026-03-13 00:08:37 +08:00
Stable Genius
c0e4f1e114 fix(dashboard): restore README dialog anchor navigation (#6083)
Co-authored-by: stablegenius49 <185121704+stablegenius49@users.noreply.github.com>
2026-03-13 00:02:45 +08:00
Stable Genius
7b43448ce4 fix: prefer named weekday cron examples (#6091)
Co-authored-by: stablegenius49 <185121704+stablegenius49@users.noreply.github.com>
2026-03-12 23:57:45 +08:00
orbisai0security
bdac0b65f4 fix: resolve critical vulnerability V-004 (#6093)
Automatically generated security fix

Co-authored-by: orbisai0security <orbisai0security@users.noreply.github.com>
2026-03-12 23:53:47 +08:00
Gao Jinzhe
cf9ee6f20c Merge pull request #6135 from advent259141/feat/add-community-links
docs: 添加 Astrbook 和玖帕喵社区链接
2026-03-12 23:11:19 +08:00
advent259141
01eae72a64 docs: 添加 Astrbook 和玖帕喵社区链接 2026-03-12 23:05:00 +08:00
letr
bca1476eab fix(extension): refresh plugin market install state after install (#6124)
* fix(extension): refresh market install state after plugin install

* chore: remove redundant call

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>
2026-03-12 20:19:00 +08:00
エイカク
fbcbde0a4b chore: update dependency and workflow versions (#6119) 2026-03-12 20:18:23 +09:00
エイカク
3914d766db fix: install only missing plugin dependencies (#6088)
* chore: ignore local worktrees

* fix: install only missing plugin dependencies

* fix: harden missing dependency install fallback

* fix: clarify dependency install fallback logging

* refactor: simplify dependency install test helpers

* refactor: reuse requirements precheck planning
2026-03-12 11:50:29 +09:00
Chen
b1a119edb4 ruff 2026-03-12 03:44:36 +08:00
Chen
3dc4bb8e34 将shell调用时的timeout转为int 获取系统配置时正确传递umo 2026-03-12 03:42:33 +08:00
Chen
f5e7ca12f7 feat: 增加 shell 工具自定义超时配置 2026-03-12 03:26:18 +08:00
zenfun
7c3cc7b90c refactor: add capabilities to sandbox tool binding logs 2026-03-12 02:58:48 +08:00
zenfun
a5a1ba72fd refactor: add get_sandbox_capabilities API and structured logging to computer_client 2026-03-12 02:58:15 +08:00
zenfun
e1d76117b4 refactor: standardize booter structured logging format 2026-03-12 02:57:04 +08:00
zenfun
ad3911a21f refactor: add debug logging to sandbox tool resolution 2026-03-12 02:56:59 +08:00
zenfun
3440dcd14b test: add booter decoupling and profile-aware tool tests 2026-03-12 02:55:09 +08:00
zenfun
e85eef05b8 fix: stabilize tool injection for LLM prefix cache hits
Two changes to make the tool schema sent to the LLM deterministic:
1. ToolSet.normalize() — sort tools by name before serialization.
   Called at the end of build_main_agent() after all injection passes.
   Eliminates ordering drift from plugin load order, MCP reconnection,
   and persona tool list differences.
2. Always inject full sandbox tool set — ComputerToolProvider now
   returns get_default_sandbox_tools() unconditionally, regardless of
   sandbox boot state. Browser tools are always in the schema even if
   the sandbox profile lacks browser capability. The executor rejects
   calls to unavailable browser tools with a descriptive error instead
   of silently omitting them from the schema.
   This eliminates the pre-boot/post-boot tool set jump that caused
   prefix cache misses on the second request of a conversation.
2026-03-12 02:43:19 +08:00
zenfun
f16edd4fff refactor: delegate tool injection to booter self-description API
- Add get_default_tools/get_tools/get_system_prompt_parts to ComputerBooter base
- Each booter subclass (ShipyardNeo, Shipyard, Boxlite) declares its own tools
- ComputerToolProvider now delegates to booter API via computer_client helpers
- Add unified query API: get_sandbox_tools, get_default_sandbox_tools, etc.
- Extract Neo prompts to dedicated computer/prompts.py module
- Add booter type constants (booters/constants.py)
- Fix subagent tool path to pass sandbox_cfg and session_id
- Fix Sourcery issues: shell injection in send_message, typo in prompts,
  internal tools bypass inactivated_llm_tools check
2026-03-12 02:43:19 +08:00
DOHEX
3e2cb6a2ab fix(telegram): remove deprecated normalize_whitespace param from (#6044)
telegramify_markdown.markdownify calls
2026-03-12 00:34:07 +08:00
莫思潋
25830524f3 fix(docs): typo in docker.md & napcat.md (#6048)
* Fix wording in admin ID configuration instructions

* Update docker.md
2026-03-12 00:30:31 +08:00
Soulter
304094630c perf: optimize booter selection for edge cases and message sending tool (#6064)
* feat: add video message support and enhance message type descriptions in SendMessageToUserTool

* feat: add error handling for disabled sandbox runtime in get_booter function
2026-03-12 00:29:52 +08:00
Soulter
5c3643c54c feat: added support for file, voice, and video messages for QQ Official Bot (including WebSocket mode). (#6063) 2026-03-12 00:26:08 +08:00
エイカク
589cce18af fix: improve Windows local skill file reading (#6028)
* chore: ignore local worktrees

* fix: improve Windows local skill file reading

* fix: address Windows path and decoding review feedback

* fix: simplify shell decoding follow-up

* fix: harden sandbox skill prompt metadata

* fix: preserve safe sandbox skill summaries

* fix: relax sandbox summary sanitization

* fix: tighten path sanitization for skill prompts

* fix: harden sandbox skill display metadata

* fix: preserve Unicode skill paths in prompts

* fix: quote Windows skill prompt paths

* fix: simplify local shell output decoding

* fix: localize Windows prompt path handling

* fix: normalize Windows-style skill paths in prompts

* fix: align prompt and shell decoding behavior
2026-03-11 23:58:28 +09:00
Soulter
e254caf82d fix(docs): add official developer group ID to multiple language READMEs and enhance regex description in config metadata 2026-03-11 21:26:11 +08:00
advent259141
438fc105cd feat: 增加在工具注入前对工具是否启用的检查 2026-03-11 20:37:41 +08:00
Soulter
7efcd242d6 fix(docs): update edit link patterns and remove obsolete repository reference 2026-03-11 17:42:42 +08:00
JIANG Zijun
5d811d3949 fix: Persist Discord pre-ack emoji config across restart by adding missing default key (#6031)
* Initial plan

* fix: add discord default platform_specific pre-ack config

Co-authored-by: Jzjerry <20167827+Jzjerry@users.noreply.github.com>

* Delete tests/unit/test_config.py

we don't need to add tests

* fix: use 🤔 as default discord pre-ack emoji

Co-authored-by: Jzjerry <20167827+Jzjerry@users.noreply.github.com>

* add back old test config

* doc: discord pre-ack-emoji doc

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Jzjerry <20167827+Jzjerry@users.noreply.github.com>
2026-03-11 16:41:08 +08:00
Flartiny
8e6aaee10c fix(webui): unify search input clear behavior (#6017)
* fix(webui): unify search input clear behavior

* fix: centralize search input normalization
2026-03-11 15:14:16 +08:00
エイカク
6da59cfb07 fix: 插件依赖自动安装逻辑与 Dashboard 安装体验优化 (#5954)
* fix: install plugin requirements before first load

* fix: handle pip option arguments correctly

* fix: harden pip install input parsing

* refactor: simplify pip install input parsing

* fix: align plugin dependency install handling

* fix: respect configured pip index overrides

* test: parameterize plugin dependency install flows

* refactor: simplify multiline pip input parsing

* fix: install plugin dependencies before loading

* fix: protect core dependencies from downgrades and simplify package input splitting

* fix: enhance dependency conflict reporting and improve user-facing warnings

* refactor: preserve pip log indentation and fix CodeQL URL sanitization alert

* fix: explicit re-export for DependencyConflictError to satisfy ruff F401

* test: enhance index override verification in pip installer tests

* fix: correctly map pip ERROR and WARNING outputs to proper log levels

* refactor: show specific version conflicts in DependencyConflictError and revert log level mapping

* refactor: simplify install() by decoupling pip logging, failure classification and constraint file management

* refactor: further simplify pip installer and requirement parsing logic

* refactor: simplify dependency installation logic and improve circular requirement reporting

* style: organize imports in astrbot/core/__init__.py

* refactor: optimize requirement parsing efficiency and flatten pip installer API

* style: fix import sorting in astrbot/core/__init__.py

* refactor: consolidate requirement parsing, optimize core protection, and improve exception propagation

* fix: preserve valid pip requirement parsing

* fix: skip empty pip installs and preserve blank output

* chore: normalize gitignore entry style

* fix: tighten pip trust and requirement parsing

* refactor: centralize pip install parsing and failure handling

* fix: redact pip argv credentials in logs

* fix: surface plugin dependency install errors

* fix: cache core constraints and clarify requirement installs

* fix: harden pip requirement parsing for plugin installs

* fix: simplify pip installer parsing internals

* fix: tighten pip installer parsing and redaction

* refactor: simplify plugin dependency install flow

* fix: preserve core constraint conflict errors

* fix: harden pip installer fallback resolution

* refactor: split pip requirement and constraint helpers

* refactor: simplify pip installer helper flow

* refactor: streamline requirement precheck helpers

* refactor: clarify core constraint resolution

* fix: surface pip install failures explicitly

* refactor: separate pip conflict context parsing

* fix: harden core constraint resolution

* test: cover pip installer failure call sites

* refactor: remove dead requirements fallback helper

* refactor: narrow core constraint error handling

* refactor: unify requirement iteration

* refactor: share requirement name parsing

* test: align pip helper coverage

* fix: bind pip output limit at runtime

* refactor: reuse core requirement parser for tokens
2026-03-11 14:21:55 +09:00
advent259141
eae87e1ec9 Merge branch 'agent-fix-clean' of https://github.com/advent259141/AstrBot into agent-fix-clean 2026-03-11 10:42:30 +08:00
advent259141
894d72e657 feat: Introduce an internal agent sub-stage to the pipeline, enabling LLM agentic capabilities with configurable tools and context management. 2026-03-11 10:42:19 +08:00
Gao Jinzhe
42b8293f99 Merge branch 'AstrBotDevs:master' into agent-fix-clean 2026-03-11 09:48:36 +08:00
Soulter
10ceacfbb1 chore: bump version to 4.19.5 2026-03-11 00:17:14 +08:00
ChuwuYo
66f5ccd902 fix: add file size validation to TTS provider test and MiniMax empty audio detection (#5999)
- Add audio data validation in MiniMax TTS get_audio() method to detect empty responses
- Validate generated audio file size in TTSProvider.test() to ensure valid output
- Provide detailed error messages guiding users to check group_id configuration
- Auto-cleanup test audio files after validation
- Fixes issue where 0KB audio files would pass TTS detection when group_id is not configured
2026-03-11 00:07:19 +08:00
Soulter
3379587223 feat(mcp): enhance logging and initialize MCP clients in background (#5993)
* feat(mcp): enhance logging and initialize MCP clients in background

fixes: #5777

* rf

* fix(mcp): simplify MCP client initialization in background

* fix(mcp): update error message for MCP background initialization failure
2026-03-11 00:00:48 +08:00
邹永赫
e25a1a42cf Revert "fix: clarify missing MCP stdio command errors (#5992)"
This reverts commit 0c771e4a77.
2026-03-11 00:08:06 +09:00
advent259141
21f1fa82f4 feat: Implement API routes and dashboard UI for managing tools and MCP servers. 2026-03-10 22:22:18 +08:00
エイカク
0c771e4a77 fix: clarify missing MCP stdio command errors (#5992)
* fix: clarify missing MCP stdio command errors

* refactor: tighten MCP error presentation helpers

* fix: improve MCP test connection feedback

* fix: structure MCP test connection errors

* refactor: share MCP test error codes
2026-03-10 23:05:50 +09:00
advent259141
ff4412a627 refactor: Centralize and decouple computer-use tool injection logic into a new ComputerToolProvider and associated tool modules. 2026-03-10 22:00:23 +08:00
advent259141
bf430e659a feat: Introduce cron job management and refactor tool provisioning with dedicated providers for computer-use runtimes. 2026-03-10 21:05:09 +08:00
camera-2018
ec21cb13d3 feat(lark): supports CardKit streaming output for feishu (#5777)
* feat(lark): 支持飞书 CardKit 流式输出

* refactor(lark): extract streaming fallback logic and deduplicate final text update

* fix(lark): 修复流式输出竞态条件及增强健壮性

- 修复 sender loop 中 delta 快照竟态: await 期间 delta 被 generator
  更新导致 last_sent 记录了未发送的值, 造成输出卡在最后一段
- send_streaming 入口增加 platform_meta 守卫, 未启用时直接回退
- _fallback_send_streaming 移除对已耗尽 generator 的 super() 调用,
  改为内联父类副作用 (Metric.upload + _has_send_oper)
- Metric.upload 统一改为 await, 确保指标上报在方法返回前完成
- 装饰器 support_streaming_message 改为 False, 与 meta() 动态配置对齐
- i18n hint 补充提示: 需在「AI 配置 → 其他配置」中开启流式输出

* chore(lark): 收口配置

* docs(lark): update streaming output instructions and client version requirements

---------

Co-authored-by: bread-ovo <2570425204@qq.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-10 19:40:46 +08:00
Soulter
1d26b96d90 fix(workflow): update build-docs.yml to trigger on version tags instead of master branch 2026-03-10 17:16:56 +08:00
一袋米要扛幾樓
be017c87f4 fix: 前端修正切換到 chat 切換後回 welcome 的配置保存最終切換頁面 (#5792)
* 前端修正切換到chat切換後回 welcome 的配置保存最終切換頁面

* 修復 SSR 不含localStorage 環境驗證
2026-03-10 17:14:28 +08:00
lustresixx
23fffa95c8 fix(provider): support 84-char Azure TTS subscription keys (#5813)
* fix(provider): support 84-char Azure TTS subscription keys

* test(provider): add negative Azure TTS key validation cases

* chore: delete test

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-10 17:09:13 +08:00
dependabot[bot]
5b303e2e6d chore(deps): bump the github-actions group with 7 updates (#5966)
Bumps the github-actions group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [actions/setup-node](https://github.com/actions/setup-node) | `2` | `6` |
| [actions/checkout](https://github.com/actions/checkout) | `4` | `6` |
| [actions/setup-python](https://github.com/actions/setup-python) | `5` | `6` |
| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `3` | `4` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3` | `4` |
| [docker/login-action](https://github.com/docker/login-action) | `3` | `4` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `6` | `7` |


Updates `actions/setup-node` from 2 to 6
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2...v6)

Updates `actions/checkout` from 4 to 6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

Updates `actions/setup-python` from 5 to 6
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5...v6)

Updates `docker/setup-qemu-action` from 3 to 4
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)

Updates `docker/setup-buildx-action` from 3 to 4
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)

Updates `docker/login-action` from 3 to 4
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

Updates `docker/build-push-action` from 6 to 7
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: docker/setup-qemu-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: docker/setup-buildx-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: docker/build-push-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 16:56:52 +08:00
Soulter
fc33b3eb68 docs: transfer AstrBotDevs/AstrBot-docs to AstrBotDevs/AstrBot (#5960)
* docs: transfer AstrBotDevs/AstrBot-docs to AstrBotDevs/AstrBot
* refactor: reorder imports and improve type hints in sync_docs_to_wiki.py and upload_doc_images_to_r2.py
* feat: add GitHub Actions workflow to sync wiki with documentation

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: anka-afk <110004162+anka-afk@users.noreply.github.com>
Co-authored-by: zouyonghe <62183434+zouyonghe@users.noreply.github.com>
Co-authored-by: shuiping233 <49360196+shuiping233@users.noreply.github.com>
Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>
Co-authored-by: Sjshi763 <179909421+Sjshi763@users.noreply.github.com>
Co-authored-by: xiewoc <70128845+xiewoc@users.noreply.github.com>
Co-authored-by: QingFeng-awa <151742581+QingFeng-awa@users.noreply.github.com>
Co-authored-by: PaloMiku <96452465+PaloMiku@users.noreply.github.com>
Co-authored-by: shangxueink <138397030+shangxueink@users.noreply.github.com>
Co-authored-by: IGCrystal-A <244300990+IGCrystal-A@users.noreply.github.com>
Co-authored-by: RC-CHN <67079377+RC-CHN@users.noreply.github.com>
Co-authored-by: MC090610 <113341105+MC090610@users.noreply.github.com>
Co-authored-by: Waterwzy <196913419+Waterwzy@users.noreply.github.com>
Co-authored-by: Lanhuace-Wan <186303160+Lanhuace-Wan@users.noreply.github.com>
Co-authored-by: LiAlH4qwq <61769640+LiAlH4qwq@users.noreply.github.com>
Co-authored-by: HSOS6 <209910899+HSOS6@users.noreply.github.com>
Co-authored-by: th-dd <162813557+th-dd@users.noreply.github.com>
Co-authored-by: miaoxutao123 <81676466+miaoxutao123@users.noreply.github.com>
Co-authored-by: nuomicici <143102889+nuomicici@users.noreply.github.com>
Co-authored-by: nasyt233 <210103278+nasyt233@users.noreply.github.com>
Co-authored-by: jlugjb <7426462+jlugjb@users.noreply.github.com>
Co-authored-by: Raven95676 <176760093+Raven95676@users.noreply.github.com>
Co-authored-by: Futureppo <180109455+Futureppo@users.noreply.github.com>
Co-authored-by: MliKiowa <61873808+MliKiowa@users.noreply.github.com>
Co-authored-by: Fridemn <150212937+Fridemn@users.noreply.github.com>
Co-authored-by: BakaCookie520 <138355736+BakaCookie520@users.noreply.github.com>
Co-authored-by: YumeYuka <125112916+YumeYuka@users.noreply.github.com>
Co-authored-by: xming521 <32786500+xming521@users.noreply.github.com>
Co-authored-by: ywh555hhh <121592812+ywh555hhh@users.noreply.github.com>
Co-authored-by: stevessr <89645372+stevessr@users.noreply.github.com>
Co-authored-by: roeseth <41995115+roeseth@users.noreply.github.com>
Co-authored-by: ikun-1145141 <265925499+ikun-1145141@users.noreply.github.com>
Co-authored-by: evpeople <54983536+evpeople@users.noreply.github.com>
Co-authored-by: Yue-bin <60509781+Yue-bin@users.noreply.github.com>
Co-authored-by: W1ndys <109416673+W1ndys@users.noreply.github.com>
Co-authored-by: TheFurina <218887821+TheFurina@users.noreply.github.com>
Co-authored-by: Seayon <12275933+Seayon@users.noreply.github.com>
Co-authored-by: OnlyblackTea <38585636+OnlyblackTea@users.noreply.github.com>
Co-authored-by: ocetars <74854972+ocetars@users.noreply.github.com>
Co-authored-by: railgun19457 <117180744+railgun19457@users.noreply.github.com>
Co-authored-by: JunieXD <107397009+JunieXD@users.noreply.github.com>
Co-authored-by: advent259141 <197440256+advent259141@users.noreply.github.com>
Co-authored-by: Doge2077 <91442300+Doge2077@users.noreply.github.com>
Co-authored-by: Bocity <23430545+Bocity@users.noreply.github.com>
Co-authored-by: Aurora-xk <192227833+Aurora-xk@users.noreply.github.com>
2026-03-09 23:38:21 +08:00
ChuwuYo
795aec9578 feat(extension): add filtering and sorting for installed plugins in WebUI (#5923)
* feat(extension): add PluginSortControl reusable component for sorting

* i18n: add i18n keys for plugin sorting and filtering features

* feat(extension): add sorting and status filtering for installed plugins

Backend changes (plugin.py):
- Add _resolve_plugin_dir method to resolve plugin directory path
- Add _get_plugin_installed_at method to get installation time from file mtime
- Add installed_at field to plugin API response

Frontend changes (InstalledPluginsTab.vue):
- Import PluginSortControl component
- Add status filter toggle (all/enabled/disabled) using v-btn-toggle
- Integrate PluginSortControl for sorting options
- Add toolbar layout with actions and controls sections

Frontend changes (MarketPluginsTab.vue):
- Import PluginSortControl component
- Replace v-select + v-btn combination with unified PluginSortControl

Frontend changes (useExtensionPage.js):
- Add installedStatusFilter, installedSortBy, installedSortOrder refs
- Add installedSortItems and installedSortUsesOrder computed properties
- Add sortInstalledPlugins function with multi-criteria support
- Support sorting by install time, name, author, and update status
- Add status filtering in filteredPlugins computed property
- Disable default table sorting by setting sortable: false

* test: add tests for installed_at field in plugin API

- Assert all plugins have installed_at field in get_plugins response
- Assert installed_at is not null after plugin installation

* fix(extension): add explicit fallbacks for installed plugin sort comparisons

* i18n(extension): rename install time label to last modified

* fix(extension): cache installed_at parsing and validate timestamp format in tests

* test(dashboard): strengthen installed_at coverage for plugin API
2026-03-09 17:12:22 +09:00
Soulter
7d31140c14 chore: bump version to 4.19.4 2026-03-09 11:13:39 +08:00
Soulter
654112ca86 feat(wecomai): implement long connection mode and update configuration options (#5930) 2026-03-09 11:10:32 +08:00
Soulter
5dd30f9a45 chore: bump version to 4.19.3 2026-03-09 00:20:33 +08:00
Jason
a53a1ca49b fix(provider): handle MiniMax ThinkingBlock when max_tokens reached (#5913)
* fix(provider): handle MiniMax ThinkingBlock when max_tokens reached

Fixes #5912

Problem: MiniMax API returns ThinkingBlock when stop_reason='max_tokens',
but AstrBot throws 'completion 无法解析' exception because both
completion_text and tools_call_args are empty.

Root cause: The validation logic didn't consider ThinkingBlock
(reasoning_content) as valid content.

Fix: When completion_text and tools_call_args are empty but
reasoning_content is present, treat it as valid instead of throwing
exception. This happens when the model thinks but runs out of tokens
before generating the actual response.

Impact: MiniMax models now work correctly when responses are truncated
due to max_tokens limit.

* refactor: address review feedback

1. Use getattr for safe stop_reason access (prevent AttributeError)
2. Use ValueError instead of generic Exception for better error handling

Thanks @gemini-code-assist and @sourcery-ai for the review!

* refactor: flatten nested if/else with guard clause

Address Gemini Code Assist feedback:
- Use guard clause for early return
- Flattened nested conditional for better readability

Logic unchanged, just cleaner code structure.

* fix(provider): improve logging for ThinkingBlock completions in ProviderAnthropic

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-09 00:17:11 +08:00
whatevertogo
3fd6c4c8a6 fix: 修复 asyncio 事件循环相关问题 (#5774)
* fix: 修复 asyncio 事件循环相关的问题

1. components.py: 修复异常处理结构错误
   - 将 except Exception 移到正确的内部 try 块
   - 确保 _download_file() 异常能被正确捕获和记录

2. session_lock.py: 修复跨事件循环 Lock 绑定问题
   - 添加 _access_lock_loop_id 追踪事件循环
   - 当事件循环变化时重新创建 Lock

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

* fix: 根据代码审查反馈修复问题

1. components.py: 移除 asyncio.set_event_loop() 调用
   - 创建临时 event loop 时不再设置为全局
   - 避免干扰其他 asyncio 使用

2. session_lock.py: 简化延迟初始化逻辑
   - 移除 loop-ID 追踪和 _get_lock 方法
   - 使用 setdefault 简化 session lock 创建
   - 保留延迟初始化行为

3. wecomai_queue_mgr.py: 使用 time.monotonic() 替代 loop.time()
   - 同步方法不再依赖活动的 event loop
   - 避免在非异步上下文中抛出 RuntimeError

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

* fix: 优化 asyncio 事件循环管理,使用安全的方式创建和关闭事件循环

* fix: 根据代码审查反馈改进异常处理和事件循环使用

- main.py: 显式处理 check_dashboard_files() 返回 None 的情况
- components.py: 使用 logger.exception 保留异常堆栈信息
- star_manager.py: 添加 Future 异常回调处理 __del__ 执行异常
- bay_manager.py: 缓存事件循环引用避免重复调用

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

* refactor: 简化 SessionLockManager 使用 defaultdict 和 setdefault

- 使用 defaultdict(asyncio.Lock) 简化锁的懒创建
- 使用 setdefault 简化 _get_loop_state 逻辑
- 减少 get + if 分支,提升可读性

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

* fix: 降低 webui_dir 检查失败时的日志级别为 warning

改为警告而非退出,允许程序在无 WebUI 的情况下继续运行

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

* refactor: 重构事件循环锁管理,简化锁状态管理逻辑

* 新增对 SessionLockManager 的多事件循环隔离测试

* fix: 修复测试中的变量声明和断言,确保事件循环管理器的正确性

* fix: 修复插件删除时异常处理逻辑,确保正确记录错误信息

* fix: 新增针对多个事件循环的 OneBot 实例的测试,确保锁对象在不同事件循环间不共享

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 01:00:13 +09:00
sanyekana
5808784f07 fix: prevent crash on malformed MCP server config (#5666) (#5673)
* fix: prevent crash on malformed MCP server config (#5666)

* fix: prevent crash on malformed MCP server config (#5666)

* fix: validate MCP connection before persisting server config

* fix: guard mcpServers type before iterating server list

* refactor: use typed empty-config error and extract MCP rollback helper

* fix: translate error messages and comments to English for consistency

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-08 23:46:32 +08:00
Soulter
537849c1e7 fix(dingtalk): text is ignored; cannot send file actively (#5921) 2026-03-08 23:31:11 +08:00
Soulter
7f3c0fdeb2 fix: cannot receive image, file in dingtalk (#5920)
fixes: #5916 #5786
2026-03-08 23:18:56 +08:00
Windy_cold
8e431e2076 correct openrouter api_base (#5911) 2026-03-08 21:53:56 +09:00
ChuwuYo
89c11fd683 fix(extension): support searching installed plugins by display name (#5806) (#5811)
* fix(extension): support searching installed plugins by display name

* fix: unify plugin search matching across installed and market tabs

* refactor(extension): optimize plugin search matcher and remove redundant checks

* refactor(extension-page): centralize search query normalization and text matching logic

- Extract `buildSearchQuery` to create normalized query objects from raw input
- Extract `matchesText` as a reusable text matching helper for normalized/loose/pinyin/initials matching
- Remove unused `marketCustomFilter` to eliminate dead code
- Simplify `matchesPluginSearch` to accept query object instead of pre-normalized string
- Replace Set with Array for candidates to simplify control flow
- Avoid redundant normalization by having callers pass raw strings to `buildSearchQuery`

* refactor: remove unused marketCustomFilter from extension page components

- Remove marketCustomFilter from destructuring in ExtensionPage.vue, InstalledPluginsTab.vue, and MarketPluginsTab.vue

* refactor(extension): extract plugin search utilities into shared module

- Create pluginSearch.js to centralize plugin search helpers
- Move `normalizeStr`, `normalizeLoose`, `toPinyinText`, and `toInitials` into the shared module
- Add `buildSearchQuery`, `matchesText`, and `matchesPluginSearch` for reusable search matching
- Refactor useExtensionPage.js to consume the shared utilities
- Simplify plugin search logic by consolidating normalization and matching in one place

* refactor(extension): add caching to pinyin utilities and extract search fields helper

- Add Map-based caching for `toPinyinText` and `toInitials` to avoid redundant pinyin computation
- Extract `getPluginSearchFields` function to retrieve plugin fields for searching
- Improve plugin search performance with caching and better code organization

* perf(extension): add bounded caching for plugin search

- cap normalization and pinyin caches with `MAX_SEARCH_CACHE_SIZE`
- add `setCacheValue()` for oldest-entry eviction
- cache normalized and loose text values to avoid repeated string processing
- skip pinyin matching for non-CJK text using Unicode `\p{Unified_Ideograph}` property
- improve search performance while keeping memory usage bounded

* refactor(extension): extract memoizeLRU helper for cache management

- Create `memoizeLRU` higher-order function to generate LRU-cached functions
- Replace manual cache implementation with `memoizeLRU` for cleaner code
- Optimize `matchesText` to lazily compute looseValue only when needed
- Simplify caching logic while maintaining bounded cache size

* refactor(extension): simplify memoization and remove LRU logic

- Rename `memoizeLRU` to `memoizeStringFn` and remove bounded cache size
- Simplify cache hit logic for cleaner code
- Remove `MAX_SEARCH_CACHE_SIZE` constant as it's no longer needed
2026-03-08 17:41:45 +09:00
時壹
7cfe2aca99 fix: apply reply_with_quote and reply_with_mention to image-only response (#5219)
* fix: apply reply_with_quote and reply_with_mention to image-only responses

* fix: restrict reply_with_quote and reply_with_mention to plain-text/image chains
2026-03-08 17:41:12 +09:00
時壹
3a938d2a13 fix: use re.search instead of re.match in RegexFilter (#5368) 2026-03-08 17:40:40 +09:00
whatevertogo
812834bc9f feat(skills): add batch upload functionality for multiple skill ZIP files (#5804)
* 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>
2026-03-07 23:18:01 +08:00
エイカク
51ff4f6e46 fix: detect desktop runtime without frozen python (#5859)
* fix: detect desktop runtime without frozen python

* chore: drop planning docs from runtime fix pr
2026-03-07 21:42:56 +09:00
Soulter
7ac169c5e8 docs: add macOS usage note and update instructions for astrbot in multiple README files 2026-03-06 14:34:29 +08:00
Soulter
61648ebe3e docs: add new QQ group entries to README files 2026-03-06 11:11:12 +08:00
Soulter
0610f0db0a fix: pipeline scheduler not found after creating platform bot via using 'create new config' (#5776) 2026-03-05 23:53:53 +08:00
whatevertogo
8c935981bb fix: align aiocqhttp poke payload with onebot v11 (#5773)
Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
2026-03-05 23:02:26 +08:00
Ruochen Pan
3f3b4e4924 test(skill_manager): update sandbox cache path expectations (#5706)
* test(skill_manager): update sandbox cache path expectations

adjust sandbox cache tests to match absolute path resolution in
list_skills for sandbox runtime.

verify sandbox-cached skills cannot be deactivated via set_skill_active
by asserting a PermissionError, and keep active-only listing behavior
intact.

add coverage for show_sandbox_path=false to ensure local skills still
override cached metadata while sandbox-only skills retain cached paths.

* test(skill_manager): tighten local skill path assertions
2026-03-05 22:47:20 +08:00
Soulter
af581e7f21 chore: bump version to 4.19.2 2026-03-05 16:10:09 +08:00
Soulter
9e371ee10b chore: update shipyard-neo-sdk dependency to version 0.2.0 2026-03-05 16:07:10 +08:00
camera-2018
7cf77adbc8 feat(telegram): supports sendMessageDraft API (#5726)
* feat(telegram): 使用 sendMessageDraft API 实现私聊流式输出

- 新增 _send_message_draft 方法封装 Telegram Bot API sendMessageDraft
- 私聊流式输出使用 sendMessageDraft 推送草稿动画,群聊保留 edit_message_text 回退
- 使用独立异步发送循环 (_draft_sender_loop) 按固定间隔推送最新缓冲区内容,
  完全解耦 token 到达速度与 API 网络延迟
- 流式结束后发送真实消息保留最终内容(draft 是临时的)
- 使用模块级递增 draft_id 替代随机生成,确保 Telegram 端动画连续性

* fix(telegram): convert draft text to Markdown before sending message draft

* chore(telegram): telegram 适配器重构

- 提取公共方法
- 有新 token 到达时触发流式
- 生成结束后清除draft内容
- 默认draft发送md格式

* style(telegram): ruff format

* style(telegram): ruff check

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-05 11:20:28 +08:00
Soulter
31673ee521 fix: require node.js env when uv sync 2026-03-05 11:20:16 +08:00
エイカク
ff22030dde docs: align deployment sections across multilingual readmes (#5734)
* docs: align deployment sections across multilingual readmes

* docs: normalize deployment punctuation and AUR guidance

* docs: fix french and russian deployment wording
2026-03-05 11:19:27 +08:00
Soulter
101580fd77 chore: add sponsors section to README
Added a sponsors section with an image link.
2026-03-03 19:08:12 +08:00
Soulter
418f05f6e4 fix: tests 2026-03-03 16:06:49 +08:00
Soulter
df421e5554 fix: test 2026-03-03 16:04:08 +08:00
shuiping233
ed84074a60 unittest: 添加之前遗漏的kook_card_data.json (#5703) 2026-03-03 16:01:26 +08:00
Soulter
bbf61239ad fix(kook): remove debug logging for received messages and heartbeat responses 2026-03-03 15:54:45 +08:00
miaoxutao123
92ee534a2c feat: add OS information to tool descriptions and implement unit tests (#5677)
* feat: add OS information to tool descriptions and implement unit tests

* refactor: use module-level constant for OS name as suggested in PR review
2026-03-03 15:16:38 +08:00
L1ngg
fa4df0b5f3 fix(core): correctly parse DEMO_MODE as boolean from env var. (#5676)
* fix(core): correctly parse DEMO_MODE as boolean from env var.

* Update astrbot/core/__init__.py

fix(core): 添加.strip()以确保代码健壮性

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

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-03-03 15:15:20 +08:00
dependabot[bot]
e5ac31efe7 chore(deps): bump the github-actions group with 2 updates (#5694)
Bumps the github-actions group with 2 updates: [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact).


Updates `actions/upload-artifact` from 6 to 7
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

Updates `actions/download-artifact` from 7 to 8
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-03 15:14:28 +08:00
時壹
2a7745c767 fix: only allow HTTPS URLs to pass through directly in LINE adapter (#5697) 2026-03-03 15:14:08 +08:00
Gargantua
82e7502f74 fix(dashboard): stabilize sidebar customization state (#5405) (#5670)
- use stable sidebar list keys to avoid vnode reuse drift

- sanitize persisted opened groups against current sidebar menu

- guard non-array customization keys from localStorage

Co-authored-by: Gargantua <22532097@zju.edu.cn>
2026-03-03 15:12:15 +08:00
shuiping233
866e546b59 feat: integrates KOOK platform adapter (#5658)
* feat: 将kook适配器插件并入astrbot官方适配器目录中

* refactor: 重命名函数名为 _warp_message

* refactor: 使用Protocol替换Union类型

* bugfix: 修复base64前缀处理问题

* refactor: 抛出的错误不再包含"[kook]"

* refactor: 添加读取本地文件时的路径安全检查

* refactor: 卡片消息解析失败时会打印错误信息

* refactor: 添加处理接收卡片消息内的图片url时的安全校验

* refactor: 安全处理ws需要重连的情况

* Revert "refactor: 使用Protocol替换Union类型"

This reverts commit 58e0dceeb20c3d7dddb16f623fd3bbdcfa632173.

* feat: 添加获取机器人名称的实现

* refactor: 让send_by_session发送主动消息时正确传入当前消息链的文本消息内容

* refactor: 统一处理适配器配置相关内容,处理仪表盘出传入配置,并添加仪表盘的kook适配器配置页面的i18n文本

* unittest: 添加kook适配器的单元测试,虽然没覆盖多少单测

* unittest: TEST_DATA_DIR用更安全的路径

* refactor: KookConfig使用了更好的默认值处理方式

* refactor: 移除kook_adapter 的config字段重复定义

* refactor: 隐藏获取kook gateway时url里的token,防止把token打印出来

* refactor: KookConfig.pretty_jsons使用*来屏蔽token内容

* bugfix: 修复主动发送消息时,调用了父方法`send_by_session`可能导致指标被重复上传的bug

* refactor: 优化upload_asset的路径处理报错

* bugfix: 修复kook ws心跳间隔可能会出现负数时间的bug

* refactor: KookClient移到KookPlatformAdapter.__init__里初始化

* bugfix: 修复处理base64 url 多替换了/而报错的bug

* refactor: kook适配器上传文件失败时,会抛出错误

* chore: 移除一条注释

* refactor: 移除没用的return

* refactor: 即使消息链中有消息发送失败了,也尽可能将其他消息发送出去,并把报错信息也发送出去

* refactor: 增强上传任务失败时的错误处理,使其发生错误时尽力而为发送其余消息

* refactor: 发送到消息频道的报错消息加了个⚠️,小巧思这块?

* refactor: 咱们在写适配器啊,要什么小巧思呢,小巧思给上游插件开发弄不好么)

* refactor: enhance Kook adapter with kmarkdown parsing and improve file URL handling

* refactor: extract card message parsing logic into a separate method

* feat: add kook_bot_nickname configuration to ignore messages from specific nicknames

* refactor: remove commented-out code and clean up file upload error handling

* fix: remove redundant prefix handling for file URLs in asset upload

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-03-03 15:08:16 +08:00
Soulter
6b642d7674 refactor: bundled webui static files into wheel and replace astrbot cli log with English (#5665)
* refactor: bundled webui static files into wheel and replace astrbot cli log with English

- Translated and standardized log messages in cmd_conf.py for better clarity.
- Updated initialization logic in cmd_init.py to provide clearer user prompts and error handling.
- Improved plugin management commands in cmd_plug.py with consistent language and error messages.
- Enhanced run command in cmd_run.py with clearer status messages and error handling.
- Updated utility functions in basic.py and plugin.py to improve readability and maintainability.
- Added version comparison logic in version_comparator.py with clearer comments.
- Enhanced logging configuration in log.py to suppress noisy loggers.
- Updated the updater logic in updator.py to provide clearer error messages for users.
- Improved IO utility functions in io.py to handle dashboard versioning more effectively.
- Enhanced dashboard server logic in server.py to prioritize bundled assets and improve user feedback.
- Updated pyproject.toml to include bundled dashboard assets and custom build hooks.
- Added a custom build script (hatch_build.py) to automate dashboard builds during package creation.

* refactor: improve exception messages and formatting in CLI command validation

* perf: change npm install to npm ci for consistent dependency installation

* fix
2026-03-03 12:58:59 +08:00
SJ
0711ec346f Fix/fix: resolve MCP tools race condition causing 'completion 无法解析' error (#5534)
* fix: resolve MCP tools race condition causing 'completion 无法解析' error

- Wait for MCP client initialization to complete before accepting requests
- Add Future-based synchronization in init_mcp_clients()
- Prevent tool_calls from being rejected due to empty func_list
- Improve error logging for MCP initialization failures

Fixes race condition where AI attempts to call MCP tools before they are
registered, resulting in 'API 返回的 completion 无法解析' exceptions.

The issue occurred because:
1. MCP clients were initialized asynchronously without waiting
2. System accepted user requests immediately after startup
3. AI received empty tool list and attempted to call non-existent tools
4. Tool matching failed, causing parsing errors

This fix ensures all MCP tools are loaded before the system processes
any requests that might use them.

* perf: add timeout and better error handling for MCP initialization

- Add 20-second total timeout to prevent slow MCP servers from blocking startup
- Show detailed configuration info when MCP initialization fails
- List all failed services in a summary warning
- Gracefully handle timeout by using already-completed services

This ensures that even if some MCP servers are slow or unreachable,
the system will start within a reasonable time and provide clear
feedback about which services failed and why.

* refactor: simplify MCP init orchestration and improve log security

- Replace Future-based sync with asyncio.wait + name→task mapping
- Explicitly cancel timed-out tasks after 20s timeout
- Downgrade sensitive config details (command/args/URL) to debug level
- Move urllib.parse import to top-level

* fix: prevent initialized MCP clients from being cleaned up on timeout

- Do not cancel pending tasks on timeout; let them continue running
  in the background waiting for the termination signal (event.set()),
  so successfully initialized services remain available
- Track initialization state with a flag to distinguish init failures
  from post-init cancellations in _init_mcp_client_task_wrapper

* fix: restore task cancellation on timeout per review feedback

Pending tasks in asyncio.wait are tasks that have NOT completed
initialization within 20s, so cancelling them is safe and correct.

* fix: separate init signal from client lifetime in MCP task wrapper

The previous design awaited task completion, but tasks only finish
on shutdown (after event.wait()), causing asyncio.wait to always
hit the 20s timeout and cancel all clients.

Fix: introduce a dedicated ready_event that is set immediately after
_init_mcp_client completes. init_mcp_clients now waits only for
ready_event (with 20s timeout), while the long-lived client task
continues running in the background until shutdown_event is set.

This ensures startup returns promptly once clients are ready.

* security: redact sensitive MCP config from debug logs

Only log executable name and argument count instead of full
command/args to avoid leaking tokens or credentials even at
debug level.

* refactor: use McpClientInfo dataclass and MCP_INIT_TIMEOUT constant

- Extract MCP_INIT_TIMEOUT = 20.0 as a named module-level constant
- Replace tuple-based client_info with _McpClientInfo dataclass to
  eliminate index-based access and improve readability
- Remove _wait_ready helper; use asyncio.create_task(event.wait()) directly
- Await cancelled tasks after timeout to prevent lingering background
  tasks and unobserved exceptions

* fix: handle CancelledError and clean up wait_tasks on timeout

- Catch asyncio.CancelledError separately in _init_mcp_client_task_wrapper
  so ready_event.set() is always called (Python 3.8+ CancelledError
  inherits BaseException, not Exception)
- Cancel and await lingering wait_tasks after timeout to prevent
  them from hanging indefinitely when ready_event is never set

* fix: align enable_mcp_server with new wrapper API and fix security/config issues

- Fix enable_mcp_server to pass shutdown_event + ready_event instead of
  ready_future, matching _init_mcp_client_task_wrapper's current signature
- Cancel and await init_task on timeout; clean up mcp_client_event on failure
- Read MCP_INIT_TIMEOUT from env var ASTRBOT_MCP_INIT_TIMEOUT (default 20s)
  so operators can tune it without code changes
- Strip userinfo from URL in debug log (use hostname+port only, not netloc)
  to avoid leaking credentials embedded in URLs

* refactor: register mcp_client_event only after successful init in enable_mcp_server

Move self.mcp_client_event[name] assignment to after initialization
succeeds, so callers never observe a stale event for a failed client.

* fix: harden MCP init state handling and timeout parsing

* fix: improve MCP timeout and post-init error observability

* refactor: simplify MCP init lifecycle orchestration

* refactor: simplify MCP init flow and cap timeout values

* fix: refine mcp timeout handling and lifecycle task tracking

* fix: harden mcp shutdown and timeout source logging

* refactor: simplify mcp runtime registry and timeout flow

* fix: keep mcp init summary return contract

* refactor: streamline mcp lifecycle and init errors

* refactor: unify mcp lifecycle wait handling

* refactor: simplify mcp runtime ownership and timeout resolution

* fix: harden mcp shutdown waiting and startup signaling

* refactor: streamline mcp lifecycle and shutdown errors

* refactor: harden mcp runtime access and shutdown

* fix: ensure mcp client cleanup and clarify views

* refactor: cache mcp client view and guard startup

* refactor: simplify mcp init cleanup and runtime lock

* refactor: reduce mcp runtime duplication

* refactor: reuse mcp cleanup and client view

---------

Co-authored-by: idiotsj <idiotsj@users.noreply.github.com>
Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-03-03 01:09:45 +09:00
LIghtJUNction
bbafb59cb2 Update dashboard/package.json
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 16:57:31 +08:00
LIghtJUNction
eaa1fddfa9 Update astrbot/cli/commands/cmd_init.py
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-02 16:57:07 +08:00
LIghtJUNction
1ffa339a2a Update astrbot/core/config/default.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 15:33:14 +08:00
Copilot
0dbe32e2dc feat: add Discord pre-ack emoji support (#5609)
* Initial plan

* feat: add Discord pre-ack emoji support

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

* feat: add Discord pre-acknowledgment emoji configuration in English and Chinese locales

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-02 14:38:12 +08:00
Soulter
4e855a17bc fix: update Discord command registration descriptions and hints in config metadata 2026-03-02 14:31:36 +08:00
Soulter
f2fc724e0f fix: update tutorial links to use the correct path format 2026-03-02 14:22:56 +08:00
Copilot
460acf40c0 fix: apply max_agent_step config to subagents (#5608)
* Initial plan

* fix: apply max_agent_step config to subagents

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

* fix: streamline max_agent_step and streaming_response retrieval in FunctionToolExecutor

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-02 14:16:14 +08:00
Soulter
cf29d9390f chore: reorganize provider settings for quoted message parsing 2026-03-02 12:35:35 +08:00
Soulter
ac44d1fdef feat: enhance chat interface and mobile responsiveness (#5635) 2026-03-02 12:26:55 +08:00
Soulter
66d0f0afd4 chore: remove deprecated websearch command from event filter 2026-03-02 11:51:58 +08:00
Ruochen Pan
2a7b4f6e64 Merge pull request #5028 from w31r4/feat/neo-skill-self-iteration
feat: 接入 Shipyard Neo 自迭代 Skill 闭环与管理能力
2026-03-02 09:40:32 +08:00
RC-CHN
6e1be64aef Merge branch 'feat/neo-skill-self-iteration' of https://github.com/w31r4/AstrBot into feat/neo-skill-self-iteration 2026-03-02 09:37:42 +08:00
RC-CHN
f818ad0758 Merge remote-tracking branch 'origin/master' into feat/neo-skill-self-iteration 2026-03-02 09:37:06 +08:00
sanyekana
4abea2bd30 fix: harden backup import for duplicate platform stats (#5594)
* fix: harden backup import for duplicate platform stats

- 修复 replace 模式下主库清空失败仍继续导入的问题。
- 导入前对 platform_stats 重复键做聚合(count 累加),并统一时间戳判重格式。
- 非法 count 按 0 处理并告警(限流),补充对应测试。

* refactor: improve robustness and readability of platform stats import

- 告警上限魔法数字提取为模块常量 PLATFORM_STATS_INVALID_COUNT_WARN_LIMIT
- 抽取 parse_count 内联函数,消除重复的 try/except 分支
- 存储行的 timestamp 同步写入规范化值,避免落库格式混用
- 补充测试:已有行 count 非法、告警限流、replace 模式中断断言

* fix: normalize invalid platform_stats count for non-duplicate rows

* fix: avoid merging invalid platform_stats timestamps

* refactor: simplify platform stats merge and normalize naive UTC

* refactor: inline platform stats merge helpers

* refactor: flatten platform stats merge flow

* refactor: harden platform stats merge key handling

* refactor: streamline platform stats preprocessing

* refactor: simplify platform stats merge helpers

* refactor: inline platform stats merge normalization

* refactor: extract platform stats merge helpers

* refactor: simplify platform stats preprocessing flow

* refactor: flatten platform stats preprocess helpers

* refactor: streamline platform stats merge helpers

* refactor: isolate platform stats warning limiter

---------

Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-03-01 20:46:35 +09:00
pandyzhou
267abfd552 fix: resolve /model command misleading behavior when switching to model from different provider (#5578)
* fix: /model command now auto-switches provider when model exists elsewhere

Made-with: Cursor

* fix: address Sourcery review - log get_models() failures in cross-provider lookup

Made-with: Cursor

* fix: integer branch exception handling and API key masking in model command

Made-with: Cursor

* fix: harden cross-provider model resolution

* fix: improve model lookup resilience and cache hygiene

* refactor: simplify model switch lookup flow

* refactor: streamline provider model cache updates

* fix: align provider annotations and key error flow

* fix: narrow provider command exception handling

* refactor: harden provider command error redaction and flow

* fix: improve provider model lookup and secret redaction

* refactor: cache normalized model names in provider lookup

* refactor: simplify provider model lookup helpers

* refactor: extract provider model lookup helpers

* fix: harden provider lookup cancellation and redaction

* refactor: streamline provider cache and lookup settings

* refactor: simplify provider command setting and update helpers

* refactor: streamline provider model lookup config usage

* refactor: flatten provider lookup settings and filter model lookup providers

* refactor: simplify provider cache and callback flow

* refactor: simplify provider command model cache flow

* refactor: scope provider model cache by session

* fix: preserve redaction context and restore provider hooks

* refactor: unify provider model lookup config flow

* refactor: inline provider model cache access flow

* fix: align provider lookup cache and callback semantics

* refactor: centralize provider model fetch error handling

* refactor: simplify provider model cache and lookup flow

---------

Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-03-01 19:11:31 +09:00
Soulter
b4450eb617 fix: update computer_use_runtime to 'none' for improved configuration flexibility 2026-03-01 17:35:50 +08:00
Chen
daa2efde14 fix:修正子agent无法正确接收本地图片(参考图)路径的问题 (#5579)
* fix: 修复5081号PR在子代理执行后台任务时,未正确使用系统配置的流式/非流请求的问题(#5081)

* feat:为子代理增加远程图片URL参数支持

* fix: update description for image_urls parameter in HandoffTool to clarify usage in multimodal tasks

* ruff format

* fix:修正子agent无法正确接收本地图片(参考图)路径的问题

* fix:增强image_urls接收的鲁棒性

* fix:ruff检查

* fix: harden handoff image_urls preprocessing

* fix: refactor handoff image_urls preprocessing flow

* refactor: simplify handoff image_urls data flow

* fix: filter non-string handoff image_urls entries

* refactor: streamline handoff image url collection

* refactor: share handoff image ref validation utilities

* refactor: simplify handoff image url processing

* refactor: honor prepared handoff image urls contract

---------

Co-authored-by: Soulter <905617992@qq.com>
Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-03-01 17:01:23 +09:00
Soulter
d561046ba3 feat: enhance shell command execution description for cross-platform compatibility
fixes: #5499
2026-03-01 15:35:40 +08:00
WintryWind
fd223bb259 fix: resolve unhandled UTC timezone offset for timestamps in conversation records (#5580)
* fix: resolve unhandled UTC timezone offset for timestamps in conversation records

* fix: standardize timezone imports

* fix: unify UTC datetime normalization in dashboard routes

---------

Co-authored-by: 邹永赫 <1259085392@qq.com>
2026-03-01 16:10:35 +09:00
エイカク
451ad685ae feat: 集成 DeerFlow Agent Runner 并优化流式处理 (#5581)
* feat: integrate DeerFlow agent runner and improve stream handling

* refactor: split DeerFlow stream flow and close stale client on reset

* fix: enforce max_step and correct timeout type check

* fix: harden DeerFlow config parsing and session lifecycle

* fix: preserve third-party runner error semantics and harden image parsing

* perf: bound DeerFlow values history and seen-id cache

* refactor: improve deerflow stream semantics and client lifecycle

* fix: harden third-party runner error semantics and fallback aggregation

* refactor: reduce deerflow image log noise and lazy-init api session

* perf: avoid unnecessary iterable copies in deerflow stream utils

* refactor: centralize runner error key and clarify deerflow client lifecycle

* refactor: simplify third-party runner output flow

* fix: defer streaming runner cleanup and unify error mapping

* fix: handle id-less values messages and redact stream payload logs

* fix: improve deerflow error signaling and third-party runner flow

* fix: support deerflow proxy and refine runner lifecycle

* fix: tighten deerflow image validation and runner lifecycle

* feat: support deerflow image output components

* fix: harden runner stream cleanup and refactor deerflow config

* fix: preserve deerflow done hook and simplify runner lifecycle

* refactor: simplify third-party runner aggregation and lifecycle closing

* fix: preserve first deerflow values payload and simplify runner flow

* refactor: unify runner final resolution and harden deerflow close state

* refactor: share int coercion and make deerflow close best effort

* refactor: extract deerflow mappers and streamline third-party lifecycle

* refactor: simplify third-party flow and harden sse flush parsing

* fix: make deerflow runner close path best effort

* refactor: simplify third-party orchestration and centralize deerflow keys

* refactor: simplify third-party chunk flow and deerflow finalization

* fix: harden deerflow stream parsing and simplify runner lifecycle

* refactor: remove redundant deerflow values text assignment

* fix: improve deerflow timeout diagnostics and image input feedback

* refactor: flatten third-party runner lifecycle and aggregation

* chore: use deerflow official remote svg icon

* chore: remove unused deerflow local logo asset
2026-03-01 12:31:38 +09:00
whatevertogo
93decaa997 test: add comprehensive tests for core lifecycle and agent execution (#5357)
* test: add comprehensive tests for core lifecycle and agent execution

- Add core lifecycle unit tests
- Add main agent execution tests
- Add computer use tests
- Enhance event bus tests

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

* fix: 更新用户查询标题生成逻辑,确保处理为纯文本并忽略内部指令
refactor(tests): 移除测试文件中的循环导入注释
refactor(tests): 优化计算机客户端测试,简化不可用引导程序的处理逻辑

* fix(event_bus): 优化事件处理逻辑,简化配置检查并增强错误日志记录,优化了测试内容

* fix(astr_main_agent): 简化 LLM 安全模式系统提示的设置逻辑

* test: enhance persona resolution in mock context for persona management tests

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-03-01 00:23:47 +08:00
Soulter
0d1a3ab18b refactor: remove unused router import and group click handler in NavItem component 2026-03-01 00:12:09 +08:00
whatevertogo
2a6863cf70 test: add tests for star base class and config management (#5356)
* test: add tests for star base class and config management

- Add Star base class safety helper tests
- Expand config management unit tests
- Update cron manager tests

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

* test: fix plugin_manager test isolation issues

- Use local mock plugin instead of real network requests
- Clear sys.modules cache for entire data module tree
- Clear star_map and star_registry in teardown
- Use pytest_asyncio.fixture for async fixture support

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

* test: fix test isolation and compatibility issues

- test_main.py: fix version comparison and path assertions for Windows
- test_smoke.py: add missing apscheduler.triggers mock modules
- test_tool_loop_agent_runner.py: update assertion for new interrupt behavior
- test_api_key_open_api.py: use unique session IDs to avoid test conflicts

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

* test: add unit tests for _version_info comparisons

* test: enhance plugin manager tests with mock implementations and improved assertions

* test: add mock plugin builder and updater for plugin management tests

* fix: resolve pipeline and star import cycles (#5353)

* fix: resolve pipeline and star import cycles

- Add bootstrap.py and stage_order.py to break circular dependencies
- Export Context, PluginManager, StarTools from star module
- Update pipeline __init__ to defer imports
- Split pipeline initialization into separate bootstrap module

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

* fix: add logging for get_config() failure in Star class

* fix: reorder logger initialization in base.py

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: update cron job scheduling tests and refactor star base tests for clarity

* test: expand star base tests for comprehensive coverage

- Add tests for Star class initialization and context handling
- Add tests for text_to_image with/without config
- Add tests for html_render method
- Add tests for initialize/terminate lifecycle methods
- Add type hint validation tests for Context
- Add circular import prevention tests

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

* fix: address PR review feedback - use TYPE_CHECKING instead of Any

- pipeline/context.py: Use TYPE_CHECKING to import PluginManager instead of Any
- pipeline/__init__.py: Add TYPE_CHECKING imports for __all__ exports to satisfy static analyzers
- star/register/star_handler.py: Use TYPE_CHECKING to import AstrAgentContext instead of Any
- tests: Remove invalid type hint tests that tested incorrect assumptions

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

* fix: improve TYPE_CHECKING pattern for circular import resolution

- star/register/star_handler.py: Use AstrAgentContext instead of Any in generic types
- star/context.py: Remove unnecessary else branch with CronJobManager = Any
  (with __future__ annotations, TYPE_CHECKING imports are sufficient)

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

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-03-01 00:06:04 +08:00
Soulter
76e0d6d71a feat: refactor API key creation and add new tests for open API routes 2026-02-28 23:43:05 +08:00
Soulter
974bb6b359 feat: improve error messaging for AI execution failures in agent runners 2026-02-28 21:23:44 +08:00
Soulter
2e410fc728 docs: update readme 2026-02-28 21:23:44 +08:00
Flartiny
0e2ca0379f fix: add plugin sorting by name and improve search filtering logic (#5559) 2026-02-28 18:35:11 +08:00
Soulter
9214d48a2d feat: add email support link to multiple language READMEs and enhance deployment instructions 2026-02-28 16:19:12 +08:00
Soulter
064495698f feat(i18n): add neoDeactivate messages for extension management 2026-02-28 15:45:41 +08:00
Soulter
7c913093b0 feat(i18n): add neoFilterHint for filtering candidates and release records 2026-02-28 15:27:50 +08:00
Soulter
edf0982ce4 feat(skills): enhance candidate promotion buttons with loading and disabled states 2026-02-28 15:25:14 +08:00
エイカク
7bf44bd8d2 feat: support persona custom error reply message with fallback (#5547)
* feat: support persona custom error reply message with fallback

* refactor: centralize persona custom error message helpers
2026-02-28 13:34:12 +09:00
エイカク
881b409ebc feat: improve plugin failure handling and extension list UX (#5535)
* feat: improve plugin failure handling and extension list UX

* fix: address plugin review comments

* fix: clear stale reload feedback on failed plugin reload

* fix: refine extension i18n and uninstall flow

* fix: refresh extension list after install failure

* feat: add random plugin visibility controls in market

* refactor: extract extension helpers and simplify uninstall flow

* refactor: improve failed plugin diagnostics and uninstall flow

* refactor: streamline extension uninstall flow

* fix: harden failed plugin install tracking and cleanup

* refactor: simplify extension flows and remove unused timed message

* fix: improve failed uninstall idempotency and extension error handling

* refactor: unify extension install-uninstall orchestration
2026-02-28 00:06:47 +08:00
LIghtJUNction
eacfd14218 细节修正/路径参数(astrbot_root)语义一致化 2026-02-27 23:51:44 +08:00
LIghtJUNction
b8ffecf500 完善前端/允许退出登录 2026-02-27 23:41:43 +08:00
Soulter
74a46464c8 docs: update deployment instructions across multiple language READMEs 2026-02-27 23:25:35 +08:00
LIghtJUNction
e5d85e402b 完善前端 2026-02-27 23:06:13 +08:00
Soulter
4aa63dbeaf chore: update readme 2026-02-27 22:54:39 +08:00
Soulter
ddc268a732 docs: enhance README_zh.md with detailed AstrBot features
Expanded description of AstrBot's capabilities and deployment options across various messaging platforms.
2026-02-27 22:47:44 +08:00
Soulter
f6ac6b9007 docs: update readme
- Updated links in Japanese, Russian, and Traditional Chinese README files to include a new Simplified Chinese README.
- Enhanced the description and features of AstrBot across all language versions.
- Improved formatting of supported messaging platforms and model services in Japanese, Russian, and Traditional Chinese README files.
- Added a new README file in Simplified Chinese with comprehensive details about AstrBot, including features, deployment methods, and community contributions.
2026-02-27 22:40:38 +08:00
LIghtJUNction
ea21d44d60 修正一个小错误 2026-02-27 22:33:54 +08:00
LIghtJUNction
0f734e19fd fix: import errors and port detection issue 2026-02-27 22:26:55 +08:00
LIghtJUNction
6044502968 修正导入问题 2026-02-27 22:23:26 +08:00
LIghtJUNction
fed11fffa4 恢复分支 2026-02-27 22:20:38 +08:00
LIghtJUNction
f79f460b89 Merge pull request #5538 from AstrBotDevs/master
同步
2026-02-27 22:08:50 +08:00
LIghtJUNction
a6009e2bd8 同步到主分支 (#5537)
* feat: add bocha web search tool (#4902)

* add bocha web search tool

* Revert "add bocha web search tool"

This reverts commit 1b36d75a17.

* 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 (#4928)

* fix: messages[x] assistant content must contain at least one part

fixes: #4876

* ruff format

* chore: bump version to 4.14.5 (#4930)

* feat: implement feishu / lark media file handling utilities for file, 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

* fix: correct spelling of 'temporary' in SharedPreferences class

* perf: optimize webchat and wecom ai queue lifecycle (#4941)

* perf: optimize webchat and wecom ai queue lifecycle

* perf: enhance webchat back queue management with conversation ID support

* fix: localize provider source config UI (#4933)

* 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>

* chore: bump version to 4.14.6

* feat: add provider-souce-level proxy (#4949)

* 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>

* feat(ComponentPanel):  implement permission management for dashboard (#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 预览工具返回的图片并自主决定是否发送 (#4895)

* 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 (#4893)

* 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)**:明确指出缺少结束标志或总数信息
  https://github.com/tdlib/telegram-bot-api/issues/643

- **Telegram Bot API 服务器 issue**:讨论媒体组处理的不便性,推荐使用超时机制
  https://github.com/tdlib/telegram-bot-api/issues/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 社区**:确认媒体组消息单独到达,需手动处理
  https://github.com/python-telegram-bot/python-telegram-bot/discussions/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 welcome feature with localized content and onboarding steps

* fix: correct height attribute to max-height for dialog component

* feat: supports electron app (#4952)

* 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>

* fix: dedupe preset messages (#4961)

* feat: enhance package.json with resource filters and compression settings

* chore: update Python version requirements to 3.12 (#4963)

* chore: bump version to 4.14.7

* feat: refactor release workflow and add special update handling for electron app (#4969)

* chore: bump version to 4.14.8 and bump faiss-cpu version up to date

* chore: auto ann fix by ruff (#4903)

* 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>

* fix: prepare OpenSSL via vcpkg for Windows ARM64

* ci: change ghcr namespace

* chore: update pydantic dependency version (#4980)

* feat: add delete button to persona management dialog (#4978)

* 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>

* feat: enhance Dingtalk adapter with active push message and image, video, audio message type (#4986)

* fix: handle pip install execution in frozen runtime (#4985)

* fix: handle pip install execution in frozen runtime

* fix: harden pip subprocess fallback handling

* fix: collect certifi data in desktop backend build (#4995)

* feat: 企业微信应用 支持主动消息推送,并优化企微应用、微信公众号、微信客服音频相关的处理 (#4998)

* feat: 企业微信智能机器人支持主动消息推送以及发送视频、文件等消息类型支持 (#4999)

* feat: enhance WecomAIBotAdapter and WecomAIBotMessageEvent for improved streaming message handling (#5000)

fixes: #3965

* feat: enhance persona tool management and update UI localization for subagent orchestration (#4990)

* feat: enhance persona tool management and update UI localization for subagent orchestration

* fix: remove debug logging for final ProviderRequest in build_main_agent function

* perf: 稳定源码与 Electron 打包环境下的 pip 安装行为,并修复非 Electron 环境下点击 WebUI 更新按钮时出现跳转对话框的问题 (#4996)

* fix: handle pip install execution in frozen runtime

* fix: harden pip subprocess fallback handling

* fix: scope global data root to packaged electron runtime

* refactor: inline frozen runtime check for electron guard

* fix: prefer current interpreter for source pip installs

* fix: avoid resolving venv python symlink for pip

* refactor: share runtime environment detection utilities

* fix: improve error message when pip module is unavailable

* fix: raise ImportError when pip module is unavailable

* fix: preserve ImportError semantics for missing pip

* fix: 修复非electron app环境更新时仍然显示electron更新对话框的问题

---------

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

* fix: 'HandoffTool' object has no attribute 'agent' (#5005)

* fix: 移动agent的位置到super().__init__之后

* add: 添加一行注释

* chore(deps): bump the github-actions group with 2 updates (#5006)

Bumps the github-actions group with 2 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [actions/download-artifact](https://github.com/actions/download-artifact).


Updates `astral-sh/setup-uv` from 6 to 7
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v6...v7)

Updates `actions/download-artifact` from 6 to 7
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: stabilize packaged runtime pip/ssl behavior and mac font fallback (#5007)

* fix: patch pip distlib finder for frozen electron runtime

* fix: use certifi CA bundle for runtime SSL requests

* fix: configure certifi CA before core imports

* fix: improve mac font fallback for dashboard text

* fix: harden frozen pip patch and unify TLS connector

* refactor: centralize dashboard CJK font fallback stacks

* perf: reuse TLS context and avoid repeated frozen pip patch

* refactor: bootstrap TLS setup before core imports

* fix: use async confirm dialog for provider deletions

* fix: replace native confirm dialogs in dashboard

- Add shared confirm helper in dashboard/src/utils/confirmDialog.ts for async dialog usage with safe fallback.

- Migrate provider, chat, config, session, platform, persona, MCP, backup, and knowledge-base delete/close confirmations to use the shared helper.

- Remove scattered inline confirm handling to keep behavior consistent and avoid native blocking dialog focus/caret issues in Electron.

* fix: capture runtime bootstrap logs after logger init

- Add bootstrap record buffer in runtime_bootstrap for early TLS patch logs before logger is ready.

- Flush buffered bootstrap logs to astrbot logger at process startup in main.py.

- Include concrete exception details for TLS bootstrap failures to improve diagnosis.

* fix: harden runtime bootstrap and unify confirm handling

- Simplify bootstrap log buffering and add a public initialize hook for non-main startup paths.

- Guard aiohttp TLS patching with feature/type checks and keep graceful fallback when internals are unavailable.

- Standardize dashboard confirmation flow via shared confirm helpers across composition and options API components.

* refactor: simplify runtime tls bootstrap and tighten confirm typing

* refactor: align ssl helper namespace and confirm usage

* fix: 修复 Windows 打包版后端重启失败问题 (#5009)

* fix: patch pip distlib finder for frozen electron runtime

* fix: use certifi CA bundle for runtime SSL requests

* fix: configure certifi CA before core imports

* fix: improve mac font fallback for dashboard text

* fix: harden frozen pip patch and unify TLS connector

* refactor: centralize dashboard CJK font fallback stacks

* perf: reuse TLS context and avoid repeated frozen pip patch

* refactor: bootstrap TLS setup before core imports

* fix: use async confirm dialog for provider deletions

* fix: replace native confirm dialogs in dashboard

- Add shared confirm helper in dashboard/src/utils/confirmDialog.ts for async dialog usage with safe fallback.

- Migrate provider, chat, config, session, platform, persona, MCP, backup, and knowledge-base delete/close confirmations to use the shared helper.

- Remove scattered inline confirm handling to keep behavior consistent and avoid native blocking dialog focus/caret issues in Electron.

* fix: capture runtime bootstrap logs after logger init

- Add bootstrap record buffer in runtime_bootstrap for early TLS patch logs before logger is ready.

- Flush buffered bootstrap logs to astrbot logger at process startup in main.py.

- Include concrete exception details for TLS bootstrap failures to improve diagnosis.

* fix: harden runtime bootstrap and unify confirm handling

- Simplify bootstrap log buffering and add a public initialize hook for non-main startup paths.

- Guard aiohttp TLS patching with feature/type checks and keep graceful fallback when internals are unavailable.

- Standardize dashboard confirmation flow via shared confirm helpers across composition and options API components.

* refactor: simplify runtime tls bootstrap and tighten confirm typing

* refactor: align ssl helper namespace and confirm usage

* fix: avoid frozen restart crash from multiprocessing import

* fix: include missing frozen dependencies for windows backend

* fix: use execv for stable backend reboot args

* Revert "fix: use execv for stable backend reboot args"

This reverts commit 9cc27becff.

* Revert "fix: include missing frozen dependencies for windows backend"

This reverts commit 52554bea1f.

* Revert "fix: avoid frozen restart crash from multiprocessing import"

This reverts commit 10548645b0.

* fix: reset pyinstaller onefile env before reboot

* fix: unify electron restart path and tray-exit backend cleanup

* fix: stabilize desktop restart detection and frozen reboot args

* fix: make dashboard restart wait detection robust

* fix: revert dashboard restart waiting interaction tweaks

* fix: pass auth token for desktop graceful restart

* fix: avoid false failure during graceful restart wait

* fix: start restart waiting before electron restart call

* fix: harden restart waiting and reboot arg parsing

* fix: parse start_time as numeric timestamp

* fix: 修复app内重启异常,修复app内点击重启不能立刻提示重启,以及在后端就绪时及时刷新界面的问题 (#5013)

* fix: patch pip distlib finder for frozen electron runtime

* fix: use certifi CA bundle for runtime SSL requests

* fix: configure certifi CA before core imports

* fix: improve mac font fallback for dashboard text

* fix: harden frozen pip patch and unify TLS connector

* refactor: centralize dashboard CJK font fallback stacks

* perf: reuse TLS context and avoid repeated frozen pip patch

* refactor: bootstrap TLS setup before core imports

* fix: use async confirm dialog for provider deletions

* fix: replace native confirm dialogs in dashboard

- Add shared confirm helper in dashboard/src/utils/confirmDialog.ts for async dialog usage with safe fallback.

- Migrate provider, chat, config, session, platform, persona, MCP, backup, and knowledge-base delete/close confirmations to use the shared helper.

- Remove scattered inline confirm handling to keep behavior consistent and avoid native blocking dialog focus/caret issues in Electron.

* fix: capture runtime bootstrap logs after logger init

- Add bootstrap record buffer in runtime_bootstrap for early TLS patch logs before logger is ready.

- Flush buffered bootstrap logs to astrbot logger at process startup in main.py.

- Include concrete exception details for TLS bootstrap failures to improve diagnosis.

* fix: harden runtime bootstrap and unify confirm handling

- Simplify bootstrap log buffering and add a public initialize hook for non-main startup paths.

- Guard aiohttp TLS patching with feature/type checks and keep graceful fallback when internals are unavailable.

- Standardize dashboard confirmation flow via shared confirm helpers across composition and options API components.

* refactor: simplify runtime tls bootstrap and tighten confirm typing

* refactor: align ssl helper namespace and confirm usage

* fix: avoid frozen restart crash from multiprocessing import

* fix: include missing frozen dependencies for windows backend

* fix: use execv for stable backend reboot args

* Revert "fix: use execv for stable backend reboot args"

This reverts commit 9cc27becff.

* Revert "fix: include missing frozen dependencies for windows backend"

This reverts commit 52554bea1f.

* Revert "fix: avoid frozen restart crash from multiprocessing import"

This reverts commit 10548645b0.

* fix: reset pyinstaller onefile env before reboot

* fix: unify electron restart path and tray-exit backend cleanup

* fix: stabilize desktop restart detection and frozen reboot args

* fix: make dashboard restart wait detection robust

* fix: revert dashboard restart waiting interaction tweaks

* fix: pass auth token for desktop graceful restart

* fix: avoid false failure during graceful restart wait

* fix: start restart waiting before electron restart call

* fix: harden restart waiting and reboot arg parsing

* fix: parse start_time as numeric timestamp

* fix: preserve windows frozen reboot argv quoting

* fix: align restart waiting with electron restart timing

* fix: tighten graceful restart and unmanaged kill safety

* chore: bump version to 4.15.0 (#5003)

* fix: add reminder for v4.14.8 users regarding manual redeployment due to a bug

* fix: harden plugin dependency loading in frozen app runtime (#5015)

* fix: compare plugin versions semantically in market updates

* fix: prioritize plugin site-packages for in-process pip

* fix: reload starlette from plugin target site-packages

* fix: harden plugin dependency import precedence in frozen runtime

* fix: improve plugin dependency conflict handling

* refactor: simplify plugin conflict checks and version utils

* fix: expand transitive plugin dependencies for conflict checks

* fix: recover conflicting plugin dependencies during module prefer

* fix: reuse renderer restart flow for tray backend restart

* fix: add recoverable plugin dependency conflict handling

* revert: remove plugin version comparison changes

* fix: add missing tray restart backend labels

* feat: adding support for media and quoted message attachments for feishu (#5018)

* docs: add AUR installation method (#4879)

* docs: sync system package manager installation instructions to all languages

* Update README.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update README.md

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

* fix/typo

* refactor: update system package manager installation instructions for Arch Linux across multiple language README files

* feat: add installation command for AstrBot in multiple language README files

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>

* fix(desktop): 为 Electron 与后端日志增加按大小轮转 (#5029)

* fix(desktop): rotate electron and backend logs

* refactor(desktop): centralize log rotation defaults and debug fs errors

* fix(desktop): harden rotation fs ops and buffer backend log writes

* refactor(desktop): extract buffered logger and reduce sync stat calls

* refactor(desktop): simplify rotation flow and harden logger config

* fix(desktop): make app logging async and flush-safe

* fix: harden app log path switching and debug-gated rotation errors

* fix: cap buffered log chunk size during path switch

* feat: add first notice feature with multilingual support and UI integration

* fix: 提升打包版桌面端启动稳定性并优化插件依赖处理 (#5031)

* fix(desktop): rotate electron and backend logs

* refactor(desktop): centralize log rotation defaults and debug fs errors

* fix(desktop): harden rotation fs ops and buffer backend log writes

* refactor(desktop): extract buffered logger and reduce sync stat calls

* refactor(desktop): simplify rotation flow and harden logger config

* fix(desktop): make app logging async and flush-safe

* fix: harden app log path switching and debug-gated rotation errors

* fix: cap buffered log chunk size during path switch

* fix: avoid redundant plugin reinstall and upgrade electron

* fix: stop webchat tasks cleanly and bind packaged backend to localhost

* fix: unify platform shutdown and await webchat listener cleanup

* fix: improve startup logs for dashboard and onebot listeners

* fix: revert extra startup service logs

* fix: harden plugin import recovery and webchat listener cleanup

* fix: pin dashboard ci node version to 24.13.0

* fix: avoid duplicate webchat listener cleanup on terminate

* refactor: clarify platform task lifecycle management

* fix: continue platform shutdown when terminate fails

* feat: temporary file handling and introduce TempDirCleaner (#5026)

* 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

* fix: close unawaited reset coroutine on early return (#5033)

When an OnLLMRequestEvent hook stops event propagation, the
reset_coro created by build_main_agent was never awaited, causing
a RuntimeWarning. Close the coroutine explicitly before returning.

Fixes #5032

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

* fix: update error logging message for connection failures

* docs: clean and sync README (#5014)

* fix: close missing div in README

* fix: sync README_zh-TW with README

* fix: sync README

* fix: correct typo

correct url in README_en README_fr README_ru

* docs: sync README_en with README

* Update README_en.md

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

---------

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

* fix: provider extra param dialog key display error

* chore: ruff format

* feat: add send_chat_action for Telegram platform adapter (#5037)

* feat: add send_chat_action for Telegram platform adapter

Add typing/upload indicator when sending messages via Telegram.
- Added _send_chat_action helper method for sending chat actions
- Send appropriate action (typing, upload_photo, upload_document, upload_voice)
  before sending different message types
- Support streaming mode with typing indicator
- Support supergroup with message_thread_id

* refactor(telegram): extract chat action helpers and add throttling

- Add ACTION_BY_TYPE mapping for message type to action priority
- Add _get_chat_action_for_chain() to determine action from message chain
- Add _send_media_with_action() for upload → send → restore typing pattern
- Add _ensure_typing() helper for typing status
- Add chat action throttling (0.5s) in streaming mode to avoid rate limits
- Update type annotation to ChatAction | str for better static checking

* feat(telegram): implement send_typing method for Telegram platform

---------

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

* fix: 修复更新日志、官方文档弹窗双滚动条问题 (#5060)

* docs: sync and fix readme typo (#5055)

* docs: fix index typo

* docs: fix typo in README_en.md

- 移除英文README中意外出现的俄语,并替换为英语

* docs: fix html typo

- remove unused '</p>'

* docs: sync table with README

* docs: sync README header format

- keep the README header format consistent

* doc: sync key features

* style: format files

- Fix formatting issues from previous PR

* fix: correct md anchor link

* docs: correct typo in README_fr.md

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

* docs: correct typo in README_zh-TW.md

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

---------

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

* fix: 修复备份时缺失的人格文件夹映射 (#5042)

* feat: QQ 官方机器人平台支持主动推送消息、私聊场景下支持接收文件 (#5066)

* feat: QQ 官方机器人平台支持主动推送消息、私聊场景下支持接收文件

* feat: enhance QQOfficialWebhook to remember session scenes for group, channel, and friend messages

* perf: 优化分段回复间隔时间的初始化逻辑 (#5068)

fixes: #5059

* fix: chunk err when using openrouter deepseek (#5069)

* feat: add i18n supports for custom platform adapters (#5045)

* Feat: 为插件提供的适配器的元数据&i18n提供数据通路

* chore: update docstrings with pull request references

Added references to pull request 5045 in docstrings.

---------

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

* fix: 完善转发引用解析与图片回退并支持配置化控制 (#5054)

* feat: support fallback image parsing for quoted messages

* fix: fallback parse quoted images when reply chain has placeholders

* style: format network utils with ruff

* test: expand quoted parser coverage and improve fallback diagnostics

* fix: fallback to text-only retry when image requests fail

* fix: tighten image fallback and resolve nested quoted forwards

* refactor: simplify quoted message extraction and dedupe images

* fix: harden quoted parsing and openai error candidates

* fix: harden quoted image ref normalization

* refactor: organize quoted parser settings and logging

* fix: cap quoted fallback images and avoid retry loops

* refactor: split quoted message parser into focused modules

* refactor: share onebot segment parsing logic

* refactor: unify quoted message parsing flow

* feat: move quoted parser tuning to provider settings

* fix: add missing i18n metadata for quoted parser settings

* chore: refine forwarded message setting labels

* fix: add config tabs and routing for normal and system configurations

* chore: bump version to 4.16.0 (#5074)

* feat: add LINE platform support with adapter and configuration (#5085)

* fix-correct-FIRST_NOTICE.md-locale-path-resolution (#5083) (#5082)

* fix:修改配置文件目录

* fix:添加备选的FIRST_NOTICE.zh-CN.md用于兼容

* fix: remove unnecessary frozen flag from requirements export in Dockerfile

fixes: #5089

* fix #5089: add uv lock step in Dockerfile before export (#5091)

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

* feat: support hot reload after plugin load failure (#5043)

* add :Support hot reload after plugin load failure

* Apply suggestions from code review

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

* fix:reformat code

* fix:reformat code

---------

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

* feat: add fallback chat model chain in tool loop runner (#5109)

* feat: implement fallback provider support for chat models and update configuration

* feat: enhance provider selection display with count and chips for selected providers

* feat: update fallback chat providers to use provider settings and add warning for non-list fallback models

* feat: add Afdian support card to resources section in WelcomePage

* feat: replace colorlog with loguru for enhanced logging support (#5115)

* feat: add SSL configuration options for WebUI and update related logging (#5117)

* chore: bump version to 4.17.0

* fix: handle list format content from OpenAI-compatible APIs (#5128)

* fix: handle list format content from OpenAI-compatible APIs

Some LLM providers (e.g., GLM-4.5V via SiliconFlow) return content as
list[dict] format like [{'type': 'text', 'text': '...'}] instead of
plain string. This causes the raw list representation to be displayed
to users.

Changes:
- Add _normalize_content() helper to extract text from various content formats
- Use json.loads instead of ast.literal_eval for safer parsing
- Add size limit check (8KB) before attempting JSON parsing
- Only convert lists that match OpenAI content-part schema (has 'type': 'text')
  to avoid collapsing legitimate list-literal replies like ['foo', 'bar']
- Add strip parameter to preserve whitespace in streaming chunks
- Clean up orphan </think> tags that may leak from some models

Fixes #5124

* fix: improve content normalization safety

- Try json.loads first, fallback to ast.literal_eval for single-quoted
  Python literals to avoid corrupting apostrophes (e.g., "don't")
- Coerce text values to str to handle null or non-string text fields

* fix: update retention logic in LogManager to handle backup count correctly

* chore: bump version to 4.17.1

* docs: Added instructions for deploying AstrBot using AstrBot Launcher. (#5136)

Added instructions for deploying AstrBot using AstrBot Launcher.

* fix: add MCP tools to function tool set in _plugin_tool_fix (#5144)

* fix: add support for collecting data from builtin stars in electron pyinstaller build (#5145)

* chore: bump version to 4.17.1

* chore: ruff format

* fix: prevent updates for AstrBot launched via launcher

* fix(desktop): include runtime deps for builtin plugins in backend build (#5146)

* fix: 'Plain' object has no attribute 'text' when using python 3.14 (#5154)

* fix: enhance plugin metadata handling by injecting attributes before instantiation (#5155)

* fix: enhance handle_result to support event context and webchat image sending

* chore: bump version to 4.17.3

* chore: ruff format

* feat: add NVIDIA provider template (#5157)

fixes: #5156

* feat: enhance provider sources panel with styled menu and mobile support

* fix: improve permission denied message for local execution in Python and shell tools

* feat: enhance PersonaForm component with responsive design and improved styling (#5162)

fix: #5159

* ui(CronJobPage): fix action column buttons overlapping in CronJobPage (#5163)

- 修改前:操作列容器仅使用 `d-flex`,在页面宽度变窄时,子元素(开关和删除按钮)会因为宽度挤压而发生视觉重叠,甚至堆叠在一起。
- 修改后:
    1. 为容器添加了 `flex-nowrap`,强制禁止子元素换行。
    2. 设置了 `min-width: 140px`,确保该列拥有固定的保护空间,防止被其他长文本列挤压。
    3. 增加了 `gap: 12px` 间距,提升了操作辨识度并优化了点击体验。

* feat: add unsaved changes notice to configuration page and update messages

* feat: implement search functionality in configuration components and update UI (#5168)

* feat: add FAQ link to vertical sidebar and update navigation for localization

* feat: add announcement section to WelcomePage and localize announcement title

* chore: bump version to 4.17.4

* feat: supports send markdown message in qqofficial (#5173)

* feat: supports send markdown message in qqofficial

closes: #1093 #918 #4180 #4264

* ruff format

* fix: prevent duplicate error message when all LLM providers fail (#5183)

* fix: 修复选择配置文件进入配置文件管理弹窗直接关闭弹窗显示的配置文件不正确 (#5174)

* feat: add MarketPluginCard component and integrate random plugin feature in ExtensionPage (#5190)

* feat: add MarketPluginCard component and integrate random plugin feature in ExtensionPage

* feat: update random plugin selection logic to use pluginMarketData and refresh on relevant events

* feat: supports aihubmix

* docs: update readme

* chore: ruff format

* feat: add LINE support to multiple language README files

* feat(core): add plugin error hook for custom error routing (#5192)

* feat(core): add plugin error hook for custom error routing

* fix(core): align plugin error suppression with event stop state

* refactor: extract Voice_messages_forbidden fallback into shared helper with typed BadRequest exception (#5204)

- Add _send_voice_with_fallback helper to deduplicate voice forbidden handling
- Catch telegram.error.BadRequest instead of bare Exception with string matching
- Add text field to Record component to preserve TTS source text
- Store original text in Record during TTS conversion for use as document caption
- Skip _send_chat_action when chat_id is empty to avoid unnecessary warnings

* chore: bump version to 4.17.5

* feat: add admin permission checks for Python and Shell execution (#5214)

* fix: 改进微信公众号被动回复处理机制,引入缓冲与分片回复,并优化超时行为 (#5224)

* 修复wechat official 被动回复功能

* ruff format

---------

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

* fix: 修复仅发送 JSON 消息段时的空消息回复报错 (#5208)

* Fix Register_Stage

· 补全 JSON 消息判断,修复发送 JSON 消息时遇到 “消息为空,跳过发送阶段” 的问题。
· 顺带补全其它消息类型判断。
Co-authored-by: Pizero <zhaory200707@outlook.com>

* Fix formatting and comments in stage.py

* Format stage.py

---------

Co-authored-by: Pizero <zhaory200707@outlook.com>

* docs: update related repo links

* fix(core): terminate active events on reset/new/del to prevent stale responses (#5225)

* fix(core): terminate active events on reset/new/del to prevent stale responses

Closes #5222

* style: fix import sorting in scheduler.py

* chore: remove Electron desktop pipeline and switch to tauri repo (#5226)

* ci: remove Electron desktop build from release pipeline

* chore: remove electron desktop and switch to tauri release trigger

* ci: remove desktop workflow dispatch trigger

* refactor: migrate data paths to astrbot_path helpers

* fix: point desktop update prompt to AstrBot-desktop releases

* fix: update feature request template for clarity and consistency in English and Chinese

* Feat/config leave confirm (#5249)

* feat: 配置文件增加未保存提示弹窗

* fix: 移除unsavedChangesDialog插件使用组件方式实现弹窗

* feat: add support for plugin astrbot-version and platform requirement checks (#5235)

* feat: add support for plugin astrbot-version and platform requirement checks

* fix: remove unsupported platform and version constraints from metadata.yaml

* fix: remove restriction on 'v' in astrbot_version specification format

* ruff format

* feat: add password confirmation when changing password (#5247)

* feat: add password confirmation when changing password

Fixes #5177

Adds a password confirmation field to prevent accidental password typos.

Changes:
- Backend: validate confirm_password matches new_password
- Frontend: add confirmation input with validation
- i18n: add labels and error messages for password mismatch

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

* fix(auth): improve error message for password confirmation mismatch

* fix(auth): update password hashing logic and improve confirmation validation

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(provider): 修复 dict 格式 content 导致的 JSON 残留问题 (#5250)

* fix(provider): 修复 dict 格式 content 导致的 JSON 残留问题

修复 _normalize_content 函数未处理 dict 类型 content 的问题。
当 LLM 返回 {"type": "text", "text": "..."} 格式的 content 时,
现在会正确提取 text 字段而非直接转为字符串。

同时改进 fallback 行为,对 None 值返回空字符串。

Fixes #5244

* Update warning message for unexpected dict format

---------

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

* chore: remove outdated heihe.md documentation file

* fix: all mcp tools exposed to main agent (#5252)

* fix: enhance PersonaForm layout and improve tool selection display

* fix: update tool status display and add localization for inactive tools

* fix: remove additionalProperties from tool schema properties (#5253)

fixes: #5217

* fix: simplify error messages for account edit validation

* fix: streamline error response for empty new username and password in account edit

* chore: bump vertion to 4.17.6

* feat: add OpenRouter provider support and icon

* chore: ruff format

* refactor(dashboard): replace legacy isElectron bridge fields with isDesktop (#5269)

* refactor dashboard desktop bridge fields from isElectron to isDesktop

* refactor dashboard runtime detection into shared helper

* fix: update contributor avatar image URL to include max size and columns (#5268)

* feat: astrbot http api (#5280)

* feat: astrbot http api

* Potential fix for code scanning alert no. 34: Use of a broken or weak cryptographic hashing algorithm on sensitive data

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix: improve error handling for missing attachment path in file upload

* feat: implement paginated retrieval of platform sessions for creators

* feat: refactor attachment directory handling in ChatRoute

* feat: update API endpoint paths for file and message handling

* feat: add documentation link to API key management section in settings

* feat: update API key scopes and related configurations in API routes and tests

* feat: enhance API key expiration options and add warning for permanent keys

* feat: add UTC normalization and serialization for API key timestamps

* feat: implement chat session management and validation for usernames

* feat: ignore session_id type chunks in message processing

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* feat(dashboard): improve plugin platform support display and mobile accessibility (#5271)

* feat(dashboard): improve plugin platform support display and mobile accessibility

- Replace hover-based tooltips with interactive click menus for platform support information.
- Fix mobile touch issues by introducing explicit state control for status capsules.
- Enhance UI aesthetics with platform-specific icons and a structured vertical list layout.
- Add dynamic chevron icons to provide clear visual cues for expandable content.

* refactor(dashboard): refactor market card with computed properties for performance

* refactor(dashboard): unify plugin platform support UI with new reusable chip component

- Create shared 'PluginPlatformChip' component to encapsulate platform meta display.
- Fix mobile interaction bugs by simplifying menu triggers and event handling.
- Add stacked platform icon previews and dynamic chevron indicators within capsules.
- Improve information hierarchy using structured vertical lists for platform details.
- Optimize rendering efficiency with computed properties across both card views.

* fix: qq official guild message send error (#5287)

* fix: qq official guild message send error

* Update astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py

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

---------

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

* 更新readme文档,补充桌面app说明,并向前移动位置 (#5297)

* docs: update desktop deployment section in README

* docs: refine desktop and launcher deployment descriptions

* Update README.md

* feat: add Anthropic Claude Code OAuth provider and adaptive thinking support (#5209)

* feat: add Anthropic Claude Code OAuth provider and adaptive thinking support

* fix: add defensive guard for metadata overrides and align budget condition with docs

* refactor: adopt sourcery-ai suggestions for OAuth provider

- Use use_api_key=False in OAuth subclass to avoid redundant
  API-key client construction before replacing with auth_token client
- Generalize metadata override helper to merge all dict keys
  instead of only handling 'limit', improving extensibility

* Feat/telegram command alias register  #5233 (#5234)

* feat: support registering command aliases for Telegram

Now when registering commands with aliases, all aliases will be
registered as Telegram bot commands in addition to the main command.

Example:
    @register_command(command_name="draw", alias={"画", "gen"})
Now /draw, /画, and /gen will all appear in the Telegram command menu.

* feat(telegram): add duplicate command name warning when registering commands

Log a warning when duplicate command names are detected during Telegram
command registration to help identify configuration conflicts.

* refactor: remove Anthropic OAuth provider implementation and related metadata overrides

* fix: 修复新建对话时因缺少会话ID导致配置绑定失败的问题 (#5292)

* fix:尝试修改

* fix:添加详细日志

* fix:进行详细修改,并添加日志

* fix:删除所有日志

* fix: 增加安全访问函数

- 给 localStorage 访问加了 try/catch + 可用性判断:dashboard/src/utils/chatConfigBinding.ts:13
- 新增 getFromLocalStorage/setToLocalStorage(在受限存储/无痕模式下异常时回退/忽略)
- getStoredDashboardUsername() / getStoredSelectedChatConfigId() 改为走安全读取:dashboard/src/utils/chatConfigBinding.ts:36       - 新增 setStoredSelectedChatConfigId(),写入失败静默忽略:dashboard/src/utils/chatConfigBinding.ts:44
- 把 ConfigSelector.vue 里直接 localStorage.getItem/setItem 全部替换为上述安全方法:dashboard/src/components/chat/ConfigSelector.vue:81
- 已重新跑过 pnpm run typecheck,通过。

* rm:删除个人用的文档文件

* Revert "rm:删除个人用的文档文件"

This reverts commit 0fceee0543.

* rm:删除个人用的文档文件

* rm:删除个人用的文档文件

* chore: bump version to 4.18.0

* fix(SubAgentPage): 当中间的介绍文本非常长时,Flex 布局会自动挤压右侧的控制按钮区域 (#5306)

* fix: 修复新版本插件市场出现插件显示为空白的 bug;纠正已安装插件卡片的排版,统一大小 (#5309)

* fix(ExtensionCard): 解决插件卡片大小不统一的问题

* fix(MarketPluginCard): 解决插件市场不加载插件的问题 (#5303)

* feat: supports spawn subagent as a background task that not block the main agent workflow (#5081)

* feat:为subagent添加后台任务参数

* ruff

* fix: update terminology from 'handoff mission' to 'background task' and refactor related logic

* fix: update terminology from 'background_mission' to 'background_task' in HandoffTool and related logic

* fix(HandoffTool): update background_task description for clarity on usage

---------

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

* cho

* fix: 修复 aiohttp 版本过新导致 qq-botpy 报错的问题 (#5316)

* chore: ruff format

* fix: remove hard-coded 6s timeout from tavily request

* fix: remove changelogs directory from .dockerignore

* feat(dashboard): make release redirect base URL configurable (#5330)

* feat(dashboard): make desktop release base URL configurable

* refactor(dashboard): use generic release base URL env with upstream default

* fix(dashboard): guard release base URL normalization when env is unset

* refactor(dashboard): use generic release URL helpers and avoid latest suffix duplication

* feat: add stop functionality for active agent sessions and improve handling of stop requests (#5380)

* feat: add stop functionality for active agent sessions and improve handling of stop requests

* feat: update stop button icon and tooltip in ChatInput component

* fix: correct indentation in tool call handling within ChatRoute class

* fix: chatui cannot persist file segment (#5386)

* fix(plugin): update plugin directory handling for reserved plugins (#5369)

* fix(plugin): update plugin directory handling for reserved plugins

* fix(plugin): add warning logs for missing plugin name, object, directory, and changelog

* chore(README): updated with README.md (#5375)

* chore(README): updated with README.md

* Update README_fr.md

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

* Update README_zh-TW.md

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

---------

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

* feat: add image urls / paths supports for subagent (#5348)

* fix: 修复5081号PR在子代理执行后台任务时,未正确使用系统配置的流式/非流请求的问题(#5081)

* feat:为子代理增加远程图片URL参数支持

* fix: update description for image_urls parameter in HandoffTool to clarify usage in multimodal tasks

* ruff format

---------

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

* feat: add hot reload when failed to load plugins (#5334)

* feat:add hot reload when failed to load plugins

* apply bot suggestions

* fix(chatui): add copy rollback path and error message. (#5352)

* fix(chatui): add copy rollback path and error message.

* fix(chatui): fixed textarea leak in the copy button.

* fix(chatui): use color styles from the component library.

* fix: 处理配置文件中的 UTF-8 BOM 编码问题 (#5376)

* fix(config): handle UTF-8 BOM in configuration file loading

Problem:
On Windows, some text editors (like Notepad) automatically add UTF-8 BOM
to JSON files when saving. This causes json.decoder.JSONDecodeError:
"Unexpected UTF-8 BOM" and AstrBot fails to start when cmd_config.json
contains BOM.

Solution:
Add defensive check to strip UTF-8 BOM (\ufeff) if present before
parsing JSON configuration file.

Impact:
- Improves robustness and cross-platform compatibility
- No breaking changes to existing functionality
- Fixes startup failure when configuration file has UTF-8 BOM encoding

Relates-to: Windows editor compatibility issues

* style: fix code formatting with ruff

Fix single quote to double quote to comply with project code style.

* feat: add plugin load&unload hook (#5331)

* 添加了插件的加载完成和卸载完成的钩子事件

* 添加了插件的加载完成和卸载完成的钩子事件

* format code with ruff

* ruff format

---------

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

* test: enhance test framework with comprehensive fixtures and mocks (#5354)

* test: enhance test framework with comprehensive fixtures and mocks

- Add shared mock builders for aiocqhttp, discord, telegram
- Add test helpers for platform configs and mock objects
- Expand conftest.py with test profile support
- Update coverage test workflow configuration

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

* refactor(tests): 移动并重构模拟 LLM 响应和消息组件函数

* fix(tests): 优化 pytest_runtest_setup 中的标记检查逻辑

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: add comprehensive tests for message event handling (#5355)

* test: add comprehensive tests for message event handling

- Add AstrMessageEvent unit tests (688 lines)
- Add AstrBotMessage unit tests
- Enhance smoke tests with message event scenarios

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

* fix: improve message type handling and add defensive tests

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add support for showing tool call results in agent execution (#5388)

closes: #5329

* fix: resolve pipeline and star import cycles (#5353)

* fix: resolve pipeline and star import cycles

- Add bootstrap.py and stage_order.py to break circular dependencies
- Export Context, PluginManager, StarTools from star module
- Update pipeline __init__ to defer imports
- Split pipeline initialization into separate bootstrap module

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

* fix: add logging for get_config() failure in Star class

* fix: reorder logger initialization in base.py

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: enable computer-use tools for subagent handoff (#5399)

* fix: enforce admin guard for sandbox file transfer tools (#5402)

* fix: enforce admin guard for sandbox file transfer tools

* refactor: deduplicate computer tools admin permission checks

* fix: add missing space in permission error message

* fix(core): 优化 File 组件处理逻辑并增强 OneBot 驱动层路径兼容性 (#5391)

* fix(core): 优化 File 组件处理逻辑并增强 OneBot 驱动层路径兼容性

原因 (Necessity):
1. 内核一致性:AstrBot 内核的 Record 和 Video 组件均具备识别 `file:///` 协议头的逻辑,但 File 组件此前缺失此功能,导致行为不统一。
2. OneBot 协议合规:OneBot 11 标准要求本地文件路径必须使用 `file:///` 协议头。此前驱动层未对裸路径进行自动转换,导致发送本地文件时常触发 retcode 1200 (识别URL失败) 错误。
3. 容器环境适配:在 Docker 等路径隔离环境下,裸路径更容易因驱动或协议端的解析歧义而失效。

更改 (Changes):
- [astrbot/core/message/components.py]:
  - 在 File.get_file() 中增加对 `file:///` 前缀的识别与剥离逻辑,使其与 Record/Video 组件行为对齐。
- [astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py]:
  - 在发送文件前增加自动修正逻辑:若路径为绝对路径且未包含协议头,驱动层将自动补全 `file:///` 前缀。
  - 对 http、base64 及已有协议头,确保不干扰原有的正常传输逻辑。

影响 (Impact):
- 以完全兼容的方式增强了文件发送的鲁棒性。
- 解决了插件在发送日志等本地生成的压缩包时,因路径格式不规范导致的发送失败问题。

* refactor(core): 根据 cr 建议,规范化文件 URI 生成与解析逻辑,优化跨平台兼容性

原因 (Necessity):
1. 修复原生路径与 URI 转换在 Windows 下的不对称问题。
2. 规范化 file: 协议头处理,确保符合 RFC 标准并能在 Linux/Windows 间稳健切换。
3. 增强协议判定准确度,防止对普通绝对路径的误处理。

更改 (Changes):
- [astrbot/core/platform/sources/aiocqhttp]:
  - 弃用手动拼接,改用 `pathlib.Path.as_uri()` 生成标准 URI。
  - 将协议检测逻辑从前缀匹配优化为包含性检测 ("://")。
- [astrbot/core/message/components]:
  - 重构 `File.get_file` 解析逻辑,支持对称处理 2/3 斜杠格式。
  - 针对 Windows 环境增加了对 `file:///C:/` 格式的自动修正,避免 `os.path` 识别失效。
- [data/plugins/astrbot_plugin_logplus]:
  - 在直接 API 调用中同步应用 URI 规范化处理。

影响 (Impact):
- 解决 Docker 环境中因路径不规范导致的 "识别URL失败" 报错。
- 提升了本体框架在 Windows 系统下的文件操作鲁棒性。

* i18n(SubAgentPage): complete internationalization for subagent orchestration page (#5400)

* i18n: complete internationalization for subagent orchestration page

- Replace hardcoded English strings in [SubAgentPage.vue] with i18n keys.
- Update `en-US` and `zh-CN` locales with missing hints, validation messages, and empty state translations.
- Fix translation typos and improve consistency across the SubAgent orchestration UI.

* fix(bug_risk): 避免在模板中的翻译调用上使用 || 'Close' 作为回退值。

* fix(aiocqhttp): enhance shutdown process for aiocqhttp adapter (#5412)

* fix: pass embedding dimensions to provider apis (#5411)

* fix(context): log warning when platform not found for session

* fix(context): improve logging for platform not found in session

* chore: bump version to 4.18.2

* chore: bump version to 4.18.2

* chore: bump version to 4.18.2

* fix: Telegram voice message format (OGG instead of WAV) causing issues with OpenAI STT API (#5389)

* chore: ruff format

* feat(dashboard): add generic desktop app updater bridge (#5424)

* feat(dashboard): add generic desktop app updater bridge

* fix(dashboard): address updater bridge review feedback

* fix(dashboard): unify updater bridge types and error logging

* fix(dashboard): consolidate updater bridge typings

* fix(conversation): retain existing persona_id when updating conversation

* fix(dashboard): 修复设置页新建 API Key 后复制失败问题 (#5439)

* Fix: GitHub proxy not displaying correctly in WebUI (#5438)

* fix(dashboard): preserve custom GitHub proxy setting on reload

* fix(dashboard): keep github proxy selection persisted in settings

* fix(persona): enhance persona resolution logic for conversations and sessions

* fix: ensure tool call/response pairing in context truncation (#5417)

* fix: ensure tool call/response pairing in context truncation

* refactor: simplify fix_messages to single-pass state machine

* perf(cron): enhance future task session isolation

fixes: #5392

* feat: add useExtensionPage composable for managing plugin extensions

- 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.

* fix: clear markdown field when sending media messages via QQ Official 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

* fix: cannot automatically get embedding dim when create embedding provider (#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

* 回退检测逻辑

* fix: 修复Pyright静态类型检查报错 (#5437)

* refactor: 修正 Sqlite 查询、下载回调、接口重构与类型调整

* feat: 为 OneBotClient 增加 CallAction 协议与异步调用支持

* fix(telegram): avoid duplicate message_thread_id in streaming (#5430)

* perf: batch metadata query in KB retrieval to fix N+1 problem (#5463)

* 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

* fix:fix the issue where incomplete cleanup of residual plugins occurs… (#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>

* chore: 为类型检查添加 TYPE_CHECKING 的导入与阶段类型引用 (#5474)

* fix(line): line adapter does not appear in the add platform dialog

fixes: #5477

* [bug]查看介入教程line前往错误界面的问题 (#5479)

Fixes #5478

* chore: bump version to 4.18.3

* feat: implement follow-up message handling in ToolLoopAgentRunner (#5484)

* feat: implement follow-up message handling in ToolLoopAgentRunner

* fix: correct import path for follow-up module in InternalAgentSubStage

* feat: implement websockets transport mode selection for chat (#5410)

* 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

* Revert "可选后端,实现前后端分离" (#5536)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: can <51474963+weijintaocode@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: letr <123731298+letr007@users.noreply.github.com>
Co-authored-by: 搁浅 <id6543156918@gmail.com>
Co-authored-by: Helian Nuits <sxp20061207@163.com>
Co-authored-by: Gao Jinzhe <2968474907@qq.com>
Co-authored-by: DD斩首 <155905740+DDZS987@users.noreply.github.com>
Co-authored-by: Ubuntu <ubuntu@localhost.localdomain>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: エイカク <62183434+zouyonghe@users.noreply.github.com>
Co-authored-by: 鸦羽 <Raven95676@gmail.com>
Co-authored-by: Dt8333 <25431943+Dt8333@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Li-shi-ling <114913764+Li-shi-ling@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Limitless <127183162+Limitless2023@users.noreply.github.com>
Co-authored-by: Limitless2023 <limitless@users.noreply.github.com>
Co-authored-by: evpeople <54983536+evpeople@users.noreply.github.com>
Co-authored-by: SnowNightt <127504703+SnowNightt@users.noreply.github.com>
Co-authored-by: xzj0898 <62733743+xzj0898@users.noreply.github.com>
Co-authored-by: stevessr <89645372+stevessr@users.noreply.github.com>
Co-authored-by: Waterwzy <2916963017@qq.com>
Co-authored-by: NayukiMeko <MekoNayuki@outlook.com>
Co-authored-by: 時壹 <137363396+KBVsent@users.noreply.github.com>
Co-authored-by: sanyekana <Clhikari@qq.com>
Co-authored-by: Chiu Chun-Hsien <95356121+911218sky@users.noreply.github.com>
Co-authored-by: Dream Tokenizer <60459821+Trance-0@users.noreply.github.com>
Co-authored-by: NanoRocky <76585834+NanoRocky@users.noreply.github.com>
Co-authored-by: Pizero <zhaory200707@outlook.com>
Co-authored-by: 雪語 <167516635+YukiRa1n@users.noreply.github.com>
Co-authored-by: whatevertogo <1879483647@qq.com>
Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: 香草味的纳西妲喵 <151599587+VanillaNahida@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Lovely Moe Moli <44719954+moemoli@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Minidoracat <minidora0702@gmail.com>
Co-authored-by: Chen <42998804+a61995987@users.noreply.github.com>
Co-authored-by: hanbings <hanbings@hanbings.io>
Co-authored-by: tangsenfei <155090747+tangsenfei@users.noreply.github.com>
Co-authored-by: PyuraMazo <1605025385@qq.com>
Co-authored-by: Axi404 <118950647+Axi404@users.noreply.github.com>
Co-authored-by: 氕氙 <2014440212@qq.com>
Co-authored-by: Yunhao Cao <18230652+realquantumcookie@users.noreply.github.com>
Co-authored-by: exynos <110159911+exynos967@users.noreply.github.com>
Co-authored-by: Luna_Dol <86590429+Luna-channel@users.noreply.github.com>
Co-authored-by: CCCCCCTV <64309817+CCCCCCTV@users.noreply.github.com>
Co-authored-by: CAICAII <3360776475@qq.com>
Co-authored-by: 圣达生物多 <qq3258819795@163.com>
2026-02-27 22:06:40 +08:00
LIghtJUNction
483048e3dc 同步主分支 (#5533)
* feat: add bocha web search tool (#4902)

* add bocha web search tool

* Revert "add bocha web search tool"

This reverts commit 1b36d75a17.

* 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 (#4928)

* fix: messages[x] assistant content must contain at least one part

fixes: #4876

* ruff format

* chore: bump version to 4.14.5 (#4930)

* feat: implement feishu / lark media file handling utilities for file, 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

* fix: correct spelling of 'temporary' in SharedPreferences class

* perf: optimize webchat and wecom ai queue lifecycle (#4941)

* perf: optimize webchat and wecom ai queue lifecycle

* perf: enhance webchat back queue management with conversation ID support

* fix: localize provider source config UI (#4933)

* 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>

* chore: bump version to 4.14.6

* feat: add provider-souce-level proxy (#4949)

* 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>

* feat(ComponentPanel):  implement permission management for dashboard (#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 预览工具返回的图片并自主决定是否发送 (#4895)

* 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 (#4893)

* 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)**:明确指出缺少结束标志或总数信息
  https://github.com/tdlib/telegram-bot-api/issues/643

- **Telegram Bot API 服务器 issue**:讨论媒体组处理的不便性,推荐使用超时机制
  https://github.com/tdlib/telegram-bot-api/issues/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 社区**:确认媒体组消息单独到达,需手动处理
  https://github.com/python-telegram-bot/python-telegram-bot/discussions/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 welcome feature with localized content and onboarding steps

* fix: correct height attribute to max-height for dialog component

* feat: supports electron app (#4952)

* 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>

* fix: dedupe preset messages (#4961)

* feat: enhance package.json with resource filters and compression settings

* chore: update Python version requirements to 3.12 (#4963)

* chore: bump version to 4.14.7

* feat: refactor release workflow and add special update handling for electron app (#4969)

* chore: bump version to 4.14.8 and bump faiss-cpu version up to date

* chore: auto ann fix by ruff (#4903)

* 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>

* fix: prepare OpenSSL via vcpkg for Windows ARM64

* ci: change ghcr namespace

* chore: update pydantic dependency version (#4980)

* feat: add delete button to persona management dialog (#4978)

* 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>

* feat: enhance Dingtalk adapter with active push message and image, video, audio message type (#4986)

* fix: handle pip install execution in frozen runtime (#4985)

* fix: handle pip install execution in frozen runtime

* fix: harden pip subprocess fallback handling

* fix: collect certifi data in desktop backend build (#4995)

* feat: 企业微信应用 支持主动消息推送,并优化企微应用、微信公众号、微信客服音频相关的处理 (#4998)

* feat: 企业微信智能机器人支持主动消息推送以及发送视频、文件等消息类型支持 (#4999)

* feat: enhance WecomAIBotAdapter and WecomAIBotMessageEvent for improved streaming message handling (#5000)

fixes: #3965

* feat: enhance persona tool management and update UI localization for subagent orchestration (#4990)

* feat: enhance persona tool management and update UI localization for subagent orchestration

* fix: remove debug logging for final ProviderRequest in build_main_agent function

* perf: 稳定源码与 Electron 打包环境下的 pip 安装行为,并修复非 Electron 环境下点击 WebUI 更新按钮时出现跳转对话框的问题 (#4996)

* fix: handle pip install execution in frozen runtime

* fix: harden pip subprocess fallback handling

* fix: scope global data root to packaged electron runtime

* refactor: inline frozen runtime check for electron guard

* fix: prefer current interpreter for source pip installs

* fix: avoid resolving venv python symlink for pip

* refactor: share runtime environment detection utilities

* fix: improve error message when pip module is unavailable

* fix: raise ImportError when pip module is unavailable

* fix: preserve ImportError semantics for missing pip

* fix: 修复非electron app环境更新时仍然显示electron更新对话框的问题

---------

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

* fix: 'HandoffTool' object has no attribute 'agent' (#5005)

* fix: 移动agent的位置到super().__init__之后

* add: 添加一行注释

* chore(deps): bump the github-actions group with 2 updates (#5006)

Bumps the github-actions group with 2 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [actions/download-artifact](https://github.com/actions/download-artifact).


Updates `astral-sh/setup-uv` from 6 to 7
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v6...v7)

Updates `actions/download-artifact` from 6 to 7
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: stabilize packaged runtime pip/ssl behavior and mac font fallback (#5007)

* fix: patch pip distlib finder for frozen electron runtime

* fix: use certifi CA bundle for runtime SSL requests

* fix: configure certifi CA before core imports

* fix: improve mac font fallback for dashboard text

* fix: harden frozen pip patch and unify TLS connector

* refactor: centralize dashboard CJK font fallback stacks

* perf: reuse TLS context and avoid repeated frozen pip patch

* refactor: bootstrap TLS setup before core imports

* fix: use async confirm dialog for provider deletions

* fix: replace native confirm dialogs in dashboard

- Add shared confirm helper in dashboard/src/utils/confirmDialog.ts for async dialog usage with safe fallback.

- Migrate provider, chat, config, session, platform, persona, MCP, backup, and knowledge-base delete/close confirmations to use the shared helper.

- Remove scattered inline confirm handling to keep behavior consistent and avoid native blocking dialog focus/caret issues in Electron.

* fix: capture runtime bootstrap logs after logger init

- Add bootstrap record buffer in runtime_bootstrap for early TLS patch logs before logger is ready.

- Flush buffered bootstrap logs to astrbot logger at process startup in main.py.

- Include concrete exception details for TLS bootstrap failures to improve diagnosis.

* fix: harden runtime bootstrap and unify confirm handling

- Simplify bootstrap log buffering and add a public initialize hook for non-main startup paths.

- Guard aiohttp TLS patching with feature/type checks and keep graceful fallback when internals are unavailable.

- Standardize dashboard confirmation flow via shared confirm helpers across composition and options API components.

* refactor: simplify runtime tls bootstrap and tighten confirm typing

* refactor: align ssl helper namespace and confirm usage

* fix: 修复 Windows 打包版后端重启失败问题 (#5009)

* fix: patch pip distlib finder for frozen electron runtime

* fix: use certifi CA bundle for runtime SSL requests

* fix: configure certifi CA before core imports

* fix: improve mac font fallback for dashboard text

* fix: harden frozen pip patch and unify TLS connector

* refactor: centralize dashboard CJK font fallback stacks

* perf: reuse TLS context and avoid repeated frozen pip patch

* refactor: bootstrap TLS setup before core imports

* fix: use async confirm dialog for provider deletions

* fix: replace native confirm dialogs in dashboard

- Add shared confirm helper in dashboard/src/utils/confirmDialog.ts for async dialog usage with safe fallback.

- Migrate provider, chat, config, session, platform, persona, MCP, backup, and knowledge-base delete/close confirmations to use the shared helper.

- Remove scattered inline confirm handling to keep behavior consistent and avoid native blocking dialog focus/caret issues in Electron.

* fix: capture runtime bootstrap logs after logger init

- Add bootstrap record buffer in runtime_bootstrap for early TLS patch logs before logger is ready.

- Flush buffered bootstrap logs to astrbot logger at process startup in main.py.

- Include concrete exception details for TLS bootstrap failures to improve diagnosis.

* fix: harden runtime bootstrap and unify confirm handling

- Simplify bootstrap log buffering and add a public initialize hook for non-main startup paths.

- Guard aiohttp TLS patching with feature/type checks and keep graceful fallback when internals are unavailable.

- Standardize dashboard confirmation flow via shared confirm helpers across composition and options API components.

* refactor: simplify runtime tls bootstrap and tighten confirm typing

* refactor: align ssl helper namespace and confirm usage

* fix: avoid frozen restart crash from multiprocessing import

* fix: include missing frozen dependencies for windows backend

* fix: use execv for stable backend reboot args

* Revert "fix: use execv for stable backend reboot args"

This reverts commit 9cc27becff.

* Revert "fix: include missing frozen dependencies for windows backend"

This reverts commit 52554bea1f.

* Revert "fix: avoid frozen restart crash from multiprocessing import"

This reverts commit 10548645b0.

* fix: reset pyinstaller onefile env before reboot

* fix: unify electron restart path and tray-exit backend cleanup

* fix: stabilize desktop restart detection and frozen reboot args

* fix: make dashboard restart wait detection robust

* fix: revert dashboard restart waiting interaction tweaks

* fix: pass auth token for desktop graceful restart

* fix: avoid false failure during graceful restart wait

* fix: start restart waiting before electron restart call

* fix: harden restart waiting and reboot arg parsing

* fix: parse start_time as numeric timestamp

* fix: 修复app内重启异常,修复app内点击重启不能立刻提示重启,以及在后端就绪时及时刷新界面的问题 (#5013)

* fix: patch pip distlib finder for frozen electron runtime

* fix: use certifi CA bundle for runtime SSL requests

* fix: configure certifi CA before core imports

* fix: improve mac font fallback for dashboard text

* fix: harden frozen pip patch and unify TLS connector

* refactor: centralize dashboard CJK font fallback stacks

* perf: reuse TLS context and avoid repeated frozen pip patch

* refactor: bootstrap TLS setup before core imports

* fix: use async confirm dialog for provider deletions

* fix: replace native confirm dialogs in dashboard

- Add shared confirm helper in dashboard/src/utils/confirmDialog.ts for async dialog usage with safe fallback.

- Migrate provider, chat, config, session, platform, persona, MCP, backup, and knowledge-base delete/close confirmations to use the shared helper.

- Remove scattered inline confirm handling to keep behavior consistent and avoid native blocking dialog focus/caret issues in Electron.

* fix: capture runtime bootstrap logs after logger init

- Add bootstrap record buffer in runtime_bootstrap for early TLS patch logs before logger is ready.

- Flush buffered bootstrap logs to astrbot logger at process startup in main.py.

- Include concrete exception details for TLS bootstrap failures to improve diagnosis.

* fix: harden runtime bootstrap and unify confirm handling

- Simplify bootstrap log buffering and add a public initialize hook for non-main startup paths.

- Guard aiohttp TLS patching with feature/type checks and keep graceful fallback when internals are unavailable.

- Standardize dashboard confirmation flow via shared confirm helpers across composition and options API components.

* refactor: simplify runtime tls bootstrap and tighten confirm typing

* refactor: align ssl helper namespace and confirm usage

* fix: avoid frozen restart crash from multiprocessing import

* fix: include missing frozen dependencies for windows backend

* fix: use execv for stable backend reboot args

* Revert "fix: use execv for stable backend reboot args"

This reverts commit 9cc27becff.

* Revert "fix: include missing frozen dependencies for windows backend"

This reverts commit 52554bea1f.

* Revert "fix: avoid frozen restart crash from multiprocessing import"

This reverts commit 10548645b0.

* fix: reset pyinstaller onefile env before reboot

* fix: unify electron restart path and tray-exit backend cleanup

* fix: stabilize desktop restart detection and frozen reboot args

* fix: make dashboard restart wait detection robust

* fix: revert dashboard restart waiting interaction tweaks

* fix: pass auth token for desktop graceful restart

* fix: avoid false failure during graceful restart wait

* fix: start restart waiting before electron restart call

* fix: harden restart waiting and reboot arg parsing

* fix: parse start_time as numeric timestamp

* fix: preserve windows frozen reboot argv quoting

* fix: align restart waiting with electron restart timing

* fix: tighten graceful restart and unmanaged kill safety

* chore: bump version to 4.15.0 (#5003)

* fix: add reminder for v4.14.8 users regarding manual redeployment due to a bug

* fix: harden plugin dependency loading in frozen app runtime (#5015)

* fix: compare plugin versions semantically in market updates

* fix: prioritize plugin site-packages for in-process pip

* fix: reload starlette from plugin target site-packages

* fix: harden plugin dependency import precedence in frozen runtime

* fix: improve plugin dependency conflict handling

* refactor: simplify plugin conflict checks and version utils

* fix: expand transitive plugin dependencies for conflict checks

* fix: recover conflicting plugin dependencies during module prefer

* fix: reuse renderer restart flow for tray backend restart

* fix: add recoverable plugin dependency conflict handling

* revert: remove plugin version comparison changes

* fix: add missing tray restart backend labels

* feat: adding support for media and quoted message attachments for feishu (#5018)

* docs: add AUR installation method (#4879)

* docs: sync system package manager installation instructions to all languages

* Update README.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update README.md

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

* fix/typo

* refactor: update system package manager installation instructions for Arch Linux across multiple language README files

* feat: add installation command for AstrBot in multiple language README files

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>

* fix(desktop): 为 Electron 与后端日志增加按大小轮转 (#5029)

* fix(desktop): rotate electron and backend logs

* refactor(desktop): centralize log rotation defaults and debug fs errors

* fix(desktop): harden rotation fs ops and buffer backend log writes

* refactor(desktop): extract buffered logger and reduce sync stat calls

* refactor(desktop): simplify rotation flow and harden logger config

* fix(desktop): make app logging async and flush-safe

* fix: harden app log path switching and debug-gated rotation errors

* fix: cap buffered log chunk size during path switch

* feat: add first notice feature with multilingual support and UI integration

* fix: 提升打包版桌面端启动稳定性并优化插件依赖处理 (#5031)

* fix(desktop): rotate electron and backend logs

* refactor(desktop): centralize log rotation defaults and debug fs errors

* fix(desktop): harden rotation fs ops and buffer backend log writes

* refactor(desktop): extract buffered logger and reduce sync stat calls

* refactor(desktop): simplify rotation flow and harden logger config

* fix(desktop): make app logging async and flush-safe

* fix: harden app log path switching and debug-gated rotation errors

* fix: cap buffered log chunk size during path switch

* fix: avoid redundant plugin reinstall and upgrade electron

* fix: stop webchat tasks cleanly and bind packaged backend to localhost

* fix: unify platform shutdown and await webchat listener cleanup

* fix: improve startup logs for dashboard and onebot listeners

* fix: revert extra startup service logs

* fix: harden plugin import recovery and webchat listener cleanup

* fix: pin dashboard ci node version to 24.13.0

* fix: avoid duplicate webchat listener cleanup on terminate

* refactor: clarify platform task lifecycle management

* fix: continue platform shutdown when terminate fails

* feat: temporary file handling and introduce TempDirCleaner (#5026)

* 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

* fix: close unawaited reset coroutine on early return (#5033)

When an OnLLMRequestEvent hook stops event propagation, the
reset_coro created by build_main_agent was never awaited, causing
a RuntimeWarning. Close the coroutine explicitly before returning.

Fixes #5032

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

* fix: update error logging message for connection failures

* docs: clean and sync README (#5014)

* fix: close missing div in README

* fix: sync README_zh-TW with README

* fix: sync README

* fix: correct typo

correct url in README_en README_fr README_ru

* docs: sync README_en with README

* Update README_en.md

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

---------

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

* fix: provider extra param dialog key display error

* chore: ruff format

* feat: add send_chat_action for Telegram platform adapter (#5037)

* feat: add send_chat_action for Telegram platform adapter

Add typing/upload indicator when sending messages via Telegram.
- Added _send_chat_action helper method for sending chat actions
- Send appropriate action (typing, upload_photo, upload_document, upload_voice)
  before sending different message types
- Support streaming mode with typing indicator
- Support supergroup with message_thread_id

* refactor(telegram): extract chat action helpers and add throttling

- Add ACTION_BY_TYPE mapping for message type to action priority
- Add _get_chat_action_for_chain() to determine action from message chain
- Add _send_media_with_action() for upload → send → restore typing pattern
- Add _ensure_typing() helper for typing status
- Add chat action throttling (0.5s) in streaming mode to avoid rate limits
- Update type annotation to ChatAction | str for better static checking

* feat(telegram): implement send_typing method for Telegram platform

---------

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

* fix: 修复更新日志、官方文档弹窗双滚动条问题 (#5060)

* docs: sync and fix readme typo (#5055)

* docs: fix index typo

* docs: fix typo in README_en.md

- 移除英文README中意外出现的俄语,并替换为英语

* docs: fix html typo

- remove unused '</p>'

* docs: sync table with README

* docs: sync README header format

- keep the README header format consistent

* doc: sync key features

* style: format files

- Fix formatting issues from previous PR

* fix: correct md anchor link

* docs: correct typo in README_fr.md

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

* docs: correct typo in README_zh-TW.md

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

---------

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

* fix: 修复备份时缺失的人格文件夹映射 (#5042)

* feat: QQ 官方机器人平台支持主动推送消息、私聊场景下支持接收文件 (#5066)

* feat: QQ 官方机器人平台支持主动推送消息、私聊场景下支持接收文件

* feat: enhance QQOfficialWebhook to remember session scenes for group, channel, and friend messages

* perf: 优化分段回复间隔时间的初始化逻辑 (#5068)

fixes: #5059

* fix: chunk err when using openrouter deepseek (#5069)

* feat: add i18n supports for custom platform adapters (#5045)

* Feat: 为插件提供的适配器的元数据&i18n提供数据通路

* chore: update docstrings with pull request references

Added references to pull request 5045 in docstrings.

---------

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

* fix: 完善转发引用解析与图片回退并支持配置化控制 (#5054)

* feat: support fallback image parsing for quoted messages

* fix: fallback parse quoted images when reply chain has placeholders

* style: format network utils with ruff

* test: expand quoted parser coverage and improve fallback diagnostics

* fix: fallback to text-only retry when image requests fail

* fix: tighten image fallback and resolve nested quoted forwards

* refactor: simplify quoted message extraction and dedupe images

* fix: harden quoted parsing and openai error candidates

* fix: harden quoted image ref normalization

* refactor: organize quoted parser settings and logging

* fix: cap quoted fallback images and avoid retry loops

* refactor: split quoted message parser into focused modules

* refactor: share onebot segment parsing logic

* refactor: unify quoted message parsing flow

* feat: move quoted parser tuning to provider settings

* fix: add missing i18n metadata for quoted parser settings

* chore: refine forwarded message setting labels

* fix: add config tabs and routing for normal and system configurations

* chore: bump version to 4.16.0 (#5074)

* feat: add LINE platform support with adapter and configuration (#5085)

* fix-correct-FIRST_NOTICE.md-locale-path-resolution (#5083) (#5082)

* fix:修改配置文件目录

* fix:添加备选的FIRST_NOTICE.zh-CN.md用于兼容

* fix: remove unnecessary frozen flag from requirements export in Dockerfile

fixes: #5089

* fix #5089: add uv lock step in Dockerfile before export (#5091)

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

* feat: support hot reload after plugin load failure (#5043)

* add :Support hot reload after plugin load failure

* Apply suggestions from code review

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

* fix:reformat code

* fix:reformat code

---------

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

* feat: add fallback chat model chain in tool loop runner (#5109)

* feat: implement fallback provider support for chat models and update configuration

* feat: enhance provider selection display with count and chips for selected providers

* feat: update fallback chat providers to use provider settings and add warning for non-list fallback models

* feat: add Afdian support card to resources section in WelcomePage

* feat: replace colorlog with loguru for enhanced logging support (#5115)

* feat: add SSL configuration options for WebUI and update related logging (#5117)

* chore: bump version to 4.17.0

* fix: handle list format content from OpenAI-compatible APIs (#5128)

* fix: handle list format content from OpenAI-compatible APIs

Some LLM providers (e.g., GLM-4.5V via SiliconFlow) return content as
list[dict] format like [{'type': 'text', 'text': '...'}] instead of
plain string. This causes the raw list representation to be displayed
to users.

Changes:
- Add _normalize_content() helper to extract text from various content formats
- Use json.loads instead of ast.literal_eval for safer parsing
- Add size limit check (8KB) before attempting JSON parsing
- Only convert lists that match OpenAI content-part schema (has 'type': 'text')
  to avoid collapsing legitimate list-literal replies like ['foo', 'bar']
- Add strip parameter to preserve whitespace in streaming chunks
- Clean up orphan </think> tags that may leak from some models

Fixes #5124

* fix: improve content normalization safety

- Try json.loads first, fallback to ast.literal_eval for single-quoted
  Python literals to avoid corrupting apostrophes (e.g., "don't")
- Coerce text values to str to handle null or non-string text fields

* fix: update retention logic in LogManager to handle backup count correctly

* chore: bump version to 4.17.1

* docs: Added instructions for deploying AstrBot using AstrBot Launcher. (#5136)

Added instructions for deploying AstrBot using AstrBot Launcher.

* fix: add MCP tools to function tool set in _plugin_tool_fix (#5144)

* fix: add support for collecting data from builtin stars in electron pyinstaller build (#5145)

* chore: bump version to 4.17.1

* chore: ruff format

* fix: prevent updates for AstrBot launched via launcher

* fix(desktop): include runtime deps for builtin plugins in backend build (#5146)

* fix: 'Plain' object has no attribute 'text' when using python 3.14 (#5154)

* fix: enhance plugin metadata handling by injecting attributes before instantiation (#5155)

* fix: enhance handle_result to support event context and webchat image sending

* chore: bump version to 4.17.3

* chore: ruff format

* feat: add NVIDIA provider template (#5157)

fixes: #5156

* feat: enhance provider sources panel with styled menu and mobile support

* fix: improve permission denied message for local execution in Python and shell tools

* feat: enhance PersonaForm component with responsive design and improved styling (#5162)

fix: #5159

* ui(CronJobPage): fix action column buttons overlapping in CronJobPage (#5163)

- 修改前:操作列容器仅使用 `d-flex`,在页面宽度变窄时,子元素(开关和删除按钮)会因为宽度挤压而发生视觉重叠,甚至堆叠在一起。
- 修改后:
    1. 为容器添加了 `flex-nowrap`,强制禁止子元素换行。
    2. 设置了 `min-width: 140px`,确保该列拥有固定的保护空间,防止被其他长文本列挤压。
    3. 增加了 `gap: 12px` 间距,提升了操作辨识度并优化了点击体验。

* feat: add unsaved changes notice to configuration page and update messages

* feat: implement search functionality in configuration components and update UI (#5168)

* feat: add FAQ link to vertical sidebar and update navigation for localization

* feat: add announcement section to WelcomePage and localize announcement title

* chore: bump version to 4.17.4

* feat: supports send markdown message in qqofficial (#5173)

* feat: supports send markdown message in qqofficial

closes: #1093 #918 #4180 #4264

* ruff format

* fix: prevent duplicate error message when all LLM providers fail (#5183)

* fix: 修复选择配置文件进入配置文件管理弹窗直接关闭弹窗显示的配置文件不正确 (#5174)

* feat: add MarketPluginCard component and integrate random plugin feature in ExtensionPage (#5190)

* feat: add MarketPluginCard component and integrate random plugin feature in ExtensionPage

* feat: update random plugin selection logic to use pluginMarketData and refresh on relevant events

* feat: supports aihubmix

* docs: update readme

* chore: ruff format

* feat: add LINE support to multiple language README files

* feat(core): add plugin error hook for custom error routing (#5192)

* feat(core): add plugin error hook for custom error routing

* fix(core): align plugin error suppression with event stop state

* refactor: extract Voice_messages_forbidden fallback into shared helper with typed BadRequest exception (#5204)

- Add _send_voice_with_fallback helper to deduplicate voice forbidden handling
- Catch telegram.error.BadRequest instead of bare Exception with string matching
- Add text field to Record component to preserve TTS source text
- Store original text in Record during TTS conversion for use as document caption
- Skip _send_chat_action when chat_id is empty to avoid unnecessary warnings

* chore: bump version to 4.17.5

* feat: add admin permission checks for Python and Shell execution (#5214)

* fix: 改进微信公众号被动回复处理机制,引入缓冲与分片回复,并优化超时行为 (#5224)

* 修复wechat official 被动回复功能

* ruff format

---------

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

* fix: 修复仅发送 JSON 消息段时的空消息回复报错 (#5208)

* Fix Register_Stage

· 补全 JSON 消息判断,修复发送 JSON 消息时遇到 “消息为空,跳过发送阶段” 的问题。
· 顺带补全其它消息类型判断。
Co-authored-by: Pizero <zhaory200707@outlook.com>

* Fix formatting and comments in stage.py

* Format stage.py

---------

Co-authored-by: Pizero <zhaory200707@outlook.com>

* docs: update related repo links

* fix(core): terminate active events on reset/new/del to prevent stale responses (#5225)

* fix(core): terminate active events on reset/new/del to prevent stale responses

Closes #5222

* style: fix import sorting in scheduler.py

* chore: remove Electron desktop pipeline and switch to tauri repo (#5226)

* ci: remove Electron desktop build from release pipeline

* chore: remove electron desktop and switch to tauri release trigger

* ci: remove desktop workflow dispatch trigger

* refactor: migrate data paths to astrbot_path helpers

* fix: point desktop update prompt to AstrBot-desktop releases

* fix: update feature request template for clarity and consistency in English and Chinese

* Feat/config leave confirm (#5249)

* feat: 配置文件增加未保存提示弹窗

* fix: 移除unsavedChangesDialog插件使用组件方式实现弹窗

* feat: add support for plugin astrbot-version and platform requirement checks (#5235)

* feat: add support for plugin astrbot-version and platform requirement checks

* fix: remove unsupported platform and version constraints from metadata.yaml

* fix: remove restriction on 'v' in astrbot_version specification format

* ruff format

* feat: add password confirmation when changing password (#5247)

* feat: add password confirmation when changing password

Fixes #5177

Adds a password confirmation field to prevent accidental password typos.

Changes:
- Backend: validate confirm_password matches new_password
- Frontend: add confirmation input with validation
- i18n: add labels and error messages for password mismatch

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

* fix(auth): improve error message for password confirmation mismatch

* fix(auth): update password hashing logic and improve confirmation validation

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(provider): 修复 dict 格式 content 导致的 JSON 残留问题 (#5250)

* fix(provider): 修复 dict 格式 content 导致的 JSON 残留问题

修复 _normalize_content 函数未处理 dict 类型 content 的问题。
当 LLM 返回 {"type": "text", "text": "..."} 格式的 content 时,
现在会正确提取 text 字段而非直接转为字符串。

同时改进 fallback 行为,对 None 值返回空字符串。

Fixes #5244

* Update warning message for unexpected dict format

---------

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

* chore: remove outdated heihe.md documentation file

* fix: all mcp tools exposed to main agent (#5252)

* fix: enhance PersonaForm layout and improve tool selection display

* fix: update tool status display and add localization for inactive tools

* fix: remove additionalProperties from tool schema properties (#5253)

fixes: #5217

* fix: simplify error messages for account edit validation

* fix: streamline error response for empty new username and password in account edit

* chore: bump vertion to 4.17.6

* feat: add OpenRouter provider support and icon

* chore: ruff format

* refactor(dashboard): replace legacy isElectron bridge fields with isDesktop (#5269)

* refactor dashboard desktop bridge fields from isElectron to isDesktop

* refactor dashboard runtime detection into shared helper

* fix: update contributor avatar image URL to include max size and columns (#5268)

* feat: astrbot http api (#5280)

* feat: astrbot http api

* Potential fix for code scanning alert no. 34: Use of a broken or weak cryptographic hashing algorithm on sensitive data

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix: improve error handling for missing attachment path in file upload

* feat: implement paginated retrieval of platform sessions for creators

* feat: refactor attachment directory handling in ChatRoute

* feat: update API endpoint paths for file and message handling

* feat: add documentation link to API key management section in settings

* feat: update API key scopes and related configurations in API routes and tests

* feat: enhance API key expiration options and add warning for permanent keys

* feat: add UTC normalization and serialization for API key timestamps

* feat: implement chat session management and validation for usernames

* feat: ignore session_id type chunks in message processing

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* feat(dashboard): improve plugin platform support display and mobile accessibility (#5271)

* feat(dashboard): improve plugin platform support display and mobile accessibility

- Replace hover-based tooltips with interactive click menus for platform support information.
- Fix mobile touch issues by introducing explicit state control for status capsules.
- Enhance UI aesthetics with platform-specific icons and a structured vertical list layout.
- Add dynamic chevron icons to provide clear visual cues for expandable content.

* refactor(dashboard): refactor market card with computed properties for performance

* refactor(dashboard): unify plugin platform support UI with new reusable chip component

- Create shared 'PluginPlatformChip' component to encapsulate platform meta display.
- Fix mobile interaction bugs by simplifying menu triggers and event handling.
- Add stacked platform icon previews and dynamic chevron indicators within capsules.
- Improve information hierarchy using structured vertical lists for platform details.
- Optimize rendering efficiency with computed properties across both card views.

* fix: qq official guild message send error (#5287)

* fix: qq official guild message send error

* Update astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py

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

---------

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

* 更新readme文档,补充桌面app说明,并向前移动位置 (#5297)

* docs: update desktop deployment section in README

* docs: refine desktop and launcher deployment descriptions

* Update README.md

* feat: add Anthropic Claude Code OAuth provider and adaptive thinking support (#5209)

* feat: add Anthropic Claude Code OAuth provider and adaptive thinking support

* fix: add defensive guard for metadata overrides and align budget condition with docs

* refactor: adopt sourcery-ai suggestions for OAuth provider

- Use use_api_key=False in OAuth subclass to avoid redundant
  API-key client construction before replacing with auth_token client
- Generalize metadata override helper to merge all dict keys
  instead of only handling 'limit', improving extensibility

* Feat/telegram command alias register  #5233 (#5234)

* feat: support registering command aliases for Telegram

Now when registering commands with aliases, all aliases will be
registered as Telegram bot commands in addition to the main command.

Example:
    @register_command(command_name="draw", alias={"画", "gen"})
Now /draw, /画, and /gen will all appear in the Telegram command menu.

* feat(telegram): add duplicate command name warning when registering commands

Log a warning when duplicate command names are detected during Telegram
command registration to help identify configuration conflicts.

* refactor: remove Anthropic OAuth provider implementation and related metadata overrides

* fix: 修复新建对话时因缺少会话ID导致配置绑定失败的问题 (#5292)

* fix:尝试修改

* fix:添加详细日志

* fix:进行详细修改,并添加日志

* fix:删除所有日志

* fix: 增加安全访问函数

- 给 localStorage 访问加了 try/catch + 可用性判断:dashboard/src/utils/chatConfigBinding.ts:13
- 新增 getFromLocalStorage/setToLocalStorage(在受限存储/无痕模式下异常时回退/忽略)
- getStoredDashboardUsername() / getStoredSelectedChatConfigId() 改为走安全读取:dashboard/src/utils/chatConfigBinding.ts:36       - 新增 setStoredSelectedChatConfigId(),写入失败静默忽略:dashboard/src/utils/chatConfigBinding.ts:44
- 把 ConfigSelector.vue 里直接 localStorage.getItem/setItem 全部替换为上述安全方法:dashboard/src/components/chat/ConfigSelector.vue:81
- 已重新跑过 pnpm run typecheck,通过。

* rm:删除个人用的文档文件

* Revert "rm:删除个人用的文档文件"

This reverts commit 0fceee0543.

* rm:删除个人用的文档文件

* rm:删除个人用的文档文件

* chore: bump version to 4.18.0

* fix(SubAgentPage): 当中间的介绍文本非常长时,Flex 布局会自动挤压右侧的控制按钮区域 (#5306)

* fix: 修复新版本插件市场出现插件显示为空白的 bug;纠正已安装插件卡片的排版,统一大小 (#5309)

* fix(ExtensionCard): 解决插件卡片大小不统一的问题

* fix(MarketPluginCard): 解决插件市场不加载插件的问题 (#5303)

* feat: supports spawn subagent as a background task that not block the main agent workflow (#5081)

* feat:为subagent添加后台任务参数

* ruff

* fix: update terminology from 'handoff mission' to 'background task' and refactor related logic

* fix: update terminology from 'background_mission' to 'background_task' in HandoffTool and related logic

* fix(HandoffTool): update background_task description for clarity on usage

---------

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

* cho

* fix: 修复 aiohttp 版本过新导致 qq-botpy 报错的问题 (#5316)

* chore: ruff format

* fix: remove hard-coded 6s timeout from tavily request

* fix: remove changelogs directory from .dockerignore

* feat(dashboard): make release redirect base URL configurable (#5330)

* feat(dashboard): make desktop release base URL configurable

* refactor(dashboard): use generic release base URL env with upstream default

* fix(dashboard): guard release base URL normalization when env is unset

* refactor(dashboard): use generic release URL helpers and avoid latest suffix duplication

* feat: add stop functionality for active agent sessions and improve handling of stop requests (#5380)

* feat: add stop functionality for active agent sessions and improve handling of stop requests

* feat: update stop button icon and tooltip in ChatInput component

* fix: correct indentation in tool call handling within ChatRoute class

* fix: chatui cannot persist file segment (#5386)

* fix(plugin): update plugin directory handling for reserved plugins (#5369)

* fix(plugin): update plugin directory handling for reserved plugins

* fix(plugin): add warning logs for missing plugin name, object, directory, and changelog

* chore(README): updated with README.md (#5375)

* chore(README): updated with README.md

* Update README_fr.md

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

* Update README_zh-TW.md

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

---------

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

* feat: add image urls / paths supports for subagent (#5348)

* fix: 修复5081号PR在子代理执行后台任务时,未正确使用系统配置的流式/非流请求的问题(#5081)

* feat:为子代理增加远程图片URL参数支持

* fix: update description for image_urls parameter in HandoffTool to clarify usage in multimodal tasks

* ruff format

---------

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

* feat: add hot reload when failed to load plugins (#5334)

* feat:add hot reload when failed to load plugins

* apply bot suggestions

* fix(chatui): add copy rollback path and error message. (#5352)

* fix(chatui): add copy rollback path and error message.

* fix(chatui): fixed textarea leak in the copy button.

* fix(chatui): use color styles from the component library.

* fix: 处理配置文件中的 UTF-8 BOM 编码问题 (#5376)

* fix(config): handle UTF-8 BOM in configuration file loading

Problem:
On Windows, some text editors (like Notepad) automatically add UTF-8 BOM
to JSON files when saving. This causes json.decoder.JSONDecodeError:
"Unexpected UTF-8 BOM" and AstrBot fails to start when cmd_config.json
contains BOM.

Solution:
Add defensive check to strip UTF-8 BOM (\ufeff) if present before
parsing JSON configuration file.

Impact:
- Improves robustness and cross-platform compatibility
- No breaking changes to existing functionality
- Fixes startup failure when configuration file has UTF-8 BOM encoding

Relates-to: Windows editor compatibility issues

* style: fix code formatting with ruff

Fix single quote to double quote to comply with project code style.

* feat: add plugin load&unload hook (#5331)

* 添加了插件的加载完成和卸载完成的钩子事件

* 添加了插件的加载完成和卸载完成的钩子事件

* format code with ruff

* ruff format

---------

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

* test: enhance test framework with comprehensive fixtures and mocks (#5354)

* test: enhance test framework with comprehensive fixtures and mocks

- Add shared mock builders for aiocqhttp, discord, telegram
- Add test helpers for platform configs and mock objects
- Expand conftest.py with test profile support
- Update coverage test workflow configuration

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

* refactor(tests): 移动并重构模拟 LLM 响应和消息组件函数

* fix(tests): 优化 pytest_runtest_setup 中的标记检查逻辑

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: add comprehensive tests for message event handling (#5355)

* test: add comprehensive tests for message event handling

- Add AstrMessageEvent unit tests (688 lines)
- Add AstrBotMessage unit tests
- Enhance smoke tests with message event scenarios

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

* fix: improve message type handling and add defensive tests

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add support for showing tool call results in agent execution (#5388)

closes: #5329

* fix: resolve pipeline and star import cycles (#5353)

* fix: resolve pipeline and star import cycles

- Add bootstrap.py and stage_order.py to break circular dependencies
- Export Context, PluginManager, StarTools from star module
- Update pipeline __init__ to defer imports
- Split pipeline initialization into separate bootstrap module

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

* fix: add logging for get_config() failure in Star class

* fix: reorder logger initialization in base.py

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: enable computer-use tools for subagent handoff (#5399)

* fix: enforce admin guard for sandbox file transfer tools (#5402)

* fix: enforce admin guard for sandbox file transfer tools

* refactor: deduplicate computer tools admin permission checks

* fix: add missing space in permission error message

* fix(core): 优化 File 组件处理逻辑并增强 OneBot 驱动层路径兼容性 (#5391)

* fix(core): 优化 File 组件处理逻辑并增强 OneBot 驱动层路径兼容性

原因 (Necessity):
1. 内核一致性:AstrBot 内核的 Record 和 Video 组件均具备识别 `file:///` 协议头的逻辑,但 File 组件此前缺失此功能,导致行为不统一。
2. OneBot 协议合规:OneBot 11 标准要求本地文件路径必须使用 `file:///` 协议头。此前驱动层未对裸路径进行自动转换,导致发送本地文件时常触发 retcode 1200 (识别URL失败) 错误。
3. 容器环境适配:在 Docker 等路径隔离环境下,裸路径更容易因驱动或协议端的解析歧义而失效。

更改 (Changes):
- [astrbot/core/message/components.py]:
  - 在 File.get_file() 中增加对 `file:///` 前缀的识别与剥离逻辑,使其与 Record/Video 组件行为对齐。
- [astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py]:
  - 在发送文件前增加自动修正逻辑:若路径为绝对路径且未包含协议头,驱动层将自动补全 `file:///` 前缀。
  - 对 http、base64 及已有协议头,确保不干扰原有的正常传输逻辑。

影响 (Impact):
- 以完全兼容的方式增强了文件发送的鲁棒性。
- 解决了插件在发送日志等本地生成的压缩包时,因路径格式不规范导致的发送失败问题。

* refactor(core): 根据 cr 建议,规范化文件 URI 生成与解析逻辑,优化跨平台兼容性

原因 (Necessity):
1. 修复原生路径与 URI 转换在 Windows 下的不对称问题。
2. 规范化 file: 协议头处理,确保符合 RFC 标准并能在 Linux/Windows 间稳健切换。
3. 增强协议判定准确度,防止对普通绝对路径的误处理。

更改 (Changes):
- [astrbot/core/platform/sources/aiocqhttp]:
  - 弃用手动拼接,改用 `pathlib.Path.as_uri()` 生成标准 URI。
  - 将协议检测逻辑从前缀匹配优化为包含性检测 ("://")。
- [astrbot/core/message/components]:
  - 重构 `File.get_file` 解析逻辑,支持对称处理 2/3 斜杠格式。
  - 针对 Windows 环境增加了对 `file:///C:/` 格式的自动修正,避免 `os.path` 识别失效。
- [data/plugins/astrbot_plugin_logplus]:
  - 在直接 API 调用中同步应用 URI 规范化处理。

影响 (Impact):
- 解决 Docker 环境中因路径不规范导致的 "识别URL失败" 报错。
- 提升了本体框架在 Windows 系统下的文件操作鲁棒性。

* i18n(SubAgentPage): complete internationalization for subagent orchestration page (#5400)

* i18n: complete internationalization for subagent orchestration page

- Replace hardcoded English strings in [SubAgentPage.vue] with i18n keys.
- Update `en-US` and `zh-CN` locales with missing hints, validation messages, and empty state translations.
- Fix translation typos and improve consistency across the SubAgent orchestration UI.

* fix(bug_risk): 避免在模板中的翻译调用上使用 || 'Close' 作为回退值。

* fix(aiocqhttp): enhance shutdown process for aiocqhttp adapter (#5412)

* fix: pass embedding dimensions to provider apis (#5411)

* fix(context): log warning when platform not found for session

* fix(context): improve logging for platform not found in session

* chore: bump version to 4.18.2

* chore: bump version to 4.18.2

* chore: bump version to 4.18.2

* fix: Telegram voice message format (OGG instead of WAV) causing issues with OpenAI STT API (#5389)

* chore: ruff format

* feat(dashboard): add generic desktop app updater bridge (#5424)

* feat(dashboard): add generic desktop app updater bridge

* fix(dashboard): address updater bridge review feedback

* fix(dashboard): unify updater bridge types and error logging

* fix(dashboard): consolidate updater bridge typings

* fix(conversation): retain existing persona_id when updating conversation

* fix(dashboard): 修复设置页新建 API Key 后复制失败问题 (#5439)

* Fix: GitHub proxy not displaying correctly in WebUI (#5438)

* fix(dashboard): preserve custom GitHub proxy setting on reload

* fix(dashboard): keep github proxy selection persisted in settings

* fix(persona): enhance persona resolution logic for conversations and sessions

* fix: ensure tool call/response pairing in context truncation (#5417)

* fix: ensure tool call/response pairing in context truncation

* refactor: simplify fix_messages to single-pass state machine

* perf(cron): enhance future task session isolation

fixes: #5392

* feat: add useExtensionPage composable for managing plugin extensions

- 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.

* fix: clear markdown field when sending media messages via QQ Official 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

* fix: cannot automatically get embedding dim when create embedding provider (#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

* 回退检测逻辑

* fix: 修复Pyright静态类型检查报错 (#5437)

* refactor: 修正 Sqlite 查询、下载回调、接口重构与类型调整

* feat: 为 OneBotClient 增加 CallAction 协议与异步调用支持

* fix(telegram): avoid duplicate message_thread_id in streaming (#5430)

* perf: batch metadata query in KB retrieval to fix N+1 problem (#5463)

* 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

* fix:fix the issue where incomplete cleanup of residual plugins occurs… (#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>

* chore: 为类型检查添加 TYPE_CHECKING 的导入与阶段类型引用 (#5474)

* fix(line): line adapter does not appear in the add platform dialog

fixes: #5477

* [bug]查看介入教程line前往错误界面的问题 (#5479)

Fixes #5478

* chore: bump version to 4.18.3

* feat: implement follow-up message handling in ToolLoopAgentRunner (#5484)

* feat: implement follow-up message handling in ToolLoopAgentRunner

* fix: correct import path for follow-up module in InternalAgentSubStage

* feat: implement websockets transport mode selection for chat (#5410)

* 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

* Revert "可选后端,实现前后端分离" (#5536)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: can <51474963+weijintaocode@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: letr <123731298+letr007@users.noreply.github.com>
Co-authored-by: 搁浅 <id6543156918@gmail.com>
Co-authored-by: Helian Nuits <sxp20061207@163.com>
Co-authored-by: Gao Jinzhe <2968474907@qq.com>
Co-authored-by: DD斩首 <155905740+DDZS987@users.noreply.github.com>
Co-authored-by: Ubuntu <ubuntu@localhost.localdomain>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: エイカク <62183434+zouyonghe@users.noreply.github.com>
Co-authored-by: 鸦羽 <Raven95676@gmail.com>
Co-authored-by: Dt8333 <25431943+Dt8333@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Li-shi-ling <114913764+Li-shi-ling@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Limitless <127183162+Limitless2023@users.noreply.github.com>
Co-authored-by: Limitless2023 <limitless@users.noreply.github.com>
Co-authored-by: evpeople <54983536+evpeople@users.noreply.github.com>
Co-authored-by: SnowNightt <127504703+SnowNightt@users.noreply.github.com>
Co-authored-by: xzj0898 <62733743+xzj0898@users.noreply.github.com>
Co-authored-by: stevessr <89645372+stevessr@users.noreply.github.com>
Co-authored-by: Waterwzy <2916963017@qq.com>
Co-authored-by: NayukiMeko <MekoNayuki@outlook.com>
Co-authored-by: 時壹 <137363396+KBVsent@users.noreply.github.com>
Co-authored-by: sanyekana <Clhikari@qq.com>
Co-authored-by: Chiu Chun-Hsien <95356121+911218sky@users.noreply.github.com>
Co-authored-by: Dream Tokenizer <60459821+Trance-0@users.noreply.github.com>
Co-authored-by: NanoRocky <76585834+NanoRocky@users.noreply.github.com>
Co-authored-by: Pizero <zhaory200707@outlook.com>
Co-authored-by: 雪語 <167516635+YukiRa1n@users.noreply.github.com>
Co-authored-by: whatevertogo <1879483647@qq.com>
Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: 香草味的纳西妲喵 <151599587+VanillaNahida@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Lovely Moe Moli <44719954+moemoli@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Minidoracat <minidora0702@gmail.com>
Co-authored-by: Chen <42998804+a61995987@users.noreply.github.com>
Co-authored-by: hanbings <hanbings@hanbings.io>
Co-authored-by: tangsenfei <155090747+tangsenfei@users.noreply.github.com>
Co-authored-by: PyuraMazo <1605025385@qq.com>
Co-authored-by: Axi404 <118950647+Axi404@users.noreply.github.com>
Co-authored-by: 氕氙 <2014440212@qq.com>
Co-authored-by: Yunhao Cao <18230652+realquantumcookie@users.noreply.github.com>
Co-authored-by: exynos <110159911+exynos967@users.noreply.github.com>
Co-authored-by: Luna_Dol <86590429+Luna-channel@users.noreply.github.com>
Co-authored-by: CCCCCCTV <64309817+CCCCCCTV@users.noreply.github.com>
Co-authored-by: CAICAII <3360776475@qq.com>
Co-authored-by: 圣达生物多 <qq3258819795@163.com>
2026-02-27 22:03:17 +08:00
LIghtJUNction
b8c73430fb Revert "可选后端,实现前后端分离" (#5536) 2026-02-27 22:02:37 +08:00
LIghtJUNction
3141ed52bd Merge branch 'feat/optional-backend' into master 2026-02-27 21:53:56 +08:00
RC-CHN
a219a8b70d Merge remote-tracking branch 'origin/master' into feat/neo-skill-self-iteration 2026-02-27 15:25:50 +08:00
RC-CHN
c1de265baf feat(skills): mark sandbox preset skills readonly
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.
2026-02-27 15:22:07 +08:00
RC-CHN
13c8fa3f92 fix(skills): use workspace path for sandbox skills
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.
2026-02-27 14:08:59 +08:00
Soulter
63ff234f10 feat: implement websockets transport mode selection for chat (#5410)
* 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
2026-02-27 14:02:10 +08:00
Soulter
5219ba5c4e feat: implement follow-up message handling in ToolLoopAgentRunner (#5484)
* feat: implement follow-up message handling in ToolLoopAgentRunner

* fix: correct import path for follow-up module in InternalAgentSubStage
2026-02-26 21:38:47 +08:00
Soulter
84994b5d98 chore: bump version to 4.18.3 2026-02-26 19:12:09 +08:00
圣达生物多
1554f71106 [bug]查看介入教程line前往错误界面的问题 (#5479)
Fixes #5478
2026-02-26 19:04:53 +08:00
RC-CHN
4ff4c5f1bf fix(skills): remove deleted skills from sandbox cache
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
2026-02-26 16:52:02 +08:00
RC-CHN
73e665bef7 feat(neo): guide skill lifecycle tool workflow
Add explicit Neo lifecycle instructions to the main agent prompt so
skill creation and updates follow payload -> candidate -> promotion
instead of direct local folder writes.

Clarify lifecycle tool descriptions and parameter semantics, including
skill_key/source_execution_ids usage and stable release sync_to_local
behavior, to reduce ambiguity and improve consistent skill publishing.
2026-02-26 16:14:16 +08:00
w31rd
4b1bda5f2e Merge pull request #2 from camera-2018/feat/neo-skill-self-iteration
Feat/neo skill self iteration
2026-02-26 16:13:42 +08:00
camera-2018
18114eafda fix(neo): sanitize skill name in frontmatter to prevent injection
Sanitized the name field in SKILL.md frontmatter within astrbot/core/skills/neo_skill_sync.py. This prevents potential frontmatter injection vulnerabilities by removing newlines and control characters from the skill name. Verified the fix with a reproduction script and ensured existing tests pass.
2026-02-26 16:04:42 +08:00
camera-2018
87cbcc9875 fix(neo): sanitize skill name in frontmatter to prevent injection
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.
2026-02-26 08:03:44 +00:00
RC-CHN
1ebc2070c0 fix(skills): gate neo mode by runtime config
Disable the Neo mode toggle unless runtime is sandbox with
shipyard_neo configured, and show a warning when Neo is unavailable.

Also avoid loading Neo data when the environment is not compatible and
fall back to local mode to prevent invalid requests and confusion.
2026-02-26 15:50:39 +08:00
RC-CHN
e95bd8d3a6 style: format code 2026-02-26 15:27:37 +08:00
Soulter
476c01469f fix(line): line adapter does not appear in the add platform dialog
fixes: #5477
2026-02-26 15:26:37 +08:00
RC-CHN
d5a3107f8f style: format code 2026-02-26 15:24:10 +08:00
RC-CHN
8d5841b71f feat(skills): add neo candidate and release deletion
Add backend routes to delete neo candidates and releases with optional
reason support and demo mode protection.

Expose delete actions in the Skills dashboard for candidate and release
rows, refresh data after success, and add localized success/failure
messages in en-US and zh-CN.
2026-02-26 14:48:20 +08:00
Dt8333
10163ec78a chore: 为类型检查添加 TYPE_CHECKING 的导入与阶段类型引用 (#5474) 2026-02-26 14:19:52 +08:00
RC-CHN
8faed949c2 fix(skills): ensure synced markdown has frontmatter
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.
2026-02-26 11:10:09 +08:00
RC-CHN
e1719efbc8 fix(skills): normalize release stage and handle rollback skip
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
2026-02-26 10:45:03 +08:00
RC-CHN
f01c23ad40 fix(agent): enforce relative paths for neo sandbox tools
append a Shipyard Neo-specific system prompt note for filesystem
tool calls so paths are provided relative to the workspace root.
this prevents models from prepending `/workspace` and causing tool
path resolution failures
2026-02-26 10:33:22 +08:00
RC-CHN
847ef0f3f4 Merge remote-tracking branch 'origin/master' into feat/neo-skill-self-iteration 2026-02-26 10:04:48 +08:00
Waterwzy
98b89ebcc5 fix:fix the issue where incomplete cleanup of residual plugins occurs… (#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>
2026-02-26 10:02:43 +08:00
CAICAII
39b9e55434 perf: batch metadata query in KB retrieval to fix N+1 problem (#5463)
* 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
2026-02-26 09:59:37 +08:00
CCCCCCTV
3eb15089af fix(telegram): avoid duplicate message_thread_id in streaming (#5430) 2026-02-25 19:53:17 +08:00
Dt8333
c5b23d12a8 fix: 修复Pyright静态类型检查报错 (#5437)
* refactor: 修正 Sqlite 查询、下载回调、接口重构与类型调整

* feat: 为 OneBotClient 增加 CallAction 协议与异步调用支持
2026-02-25 19:49:16 +08:00
exynos
69f2fb291a fix: cannot automatically get embedding dim when create embedding provider (#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

* 回退检测逻辑
2026-02-25 19:48:03 +08:00
時壹
78660da995 fix: clear markdown field when sending media messages via QQ Official 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
2026-02-25 19:45:27 +08:00
Soulter
c951b14aa2 feat: add useExtensionPage composable for managing plugin extensions
- 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.
2026-02-25 19:42:51 +08:00
Soulter
c384439b44 perf(cron): enhance future task session isolation
fixes: #5392
2026-02-25 16:32:09 +08:00
鸦羽
87d2750ff8 Merge pull request #5440 from Raven95676/fix/persona-loss
fix(persona): preserve conversation persona_id and unify session/conversation resolution
2026-02-25 16:11:19 +08:00
Luna_Dol
6d76d55452 fix: ensure tool call/response pairing in context truncation (#5417)
* fix: ensure tool call/response pairing in context truncation

* refactor: simplify fix_messages to single-pass state machine
2026-02-25 15:21:30 +08:00
Raven95676
d80598b9c3 fix(persona): enhance persona resolution logic for conversations and sessions 2026-02-25 15:14:46 +08:00
letr
c7d318304b Fix: GitHub proxy not displaying correctly in WebUI (#5438)
* fix(dashboard): preserve custom GitHub proxy setting on reload

* fix(dashboard): keep github proxy selection persisted in settings
2026-02-25 14:54:54 +08:00
exynos
bcdbc15635 fix(dashboard): 修复设置页新建 API Key 后复制失败问题 (#5439) 2026-02-25 14:54:06 +08:00
Raven95676
4749159bb9 fix(conversation): retain existing persona_id when updating conversation 2026-02-25 14:48:46 +08:00
エイカク
5530a2260a feat(dashboard): add generic desktop app updater bridge (#5424)
* feat(dashboard): add generic desktop app updater bridge

* fix(dashboard): address updater bridge review feedback

* fix(dashboard): unify updater bridge types and error logging

* fix(dashboard): consolidate updater bridge typings
2026-02-25 10:01:13 +09:00
Soulter
c24de24ca4 chore: ruff format 2026-02-24 23:12:18 +08:00
Yunhao Cao
b54b4c79ed fix: Telegram voice message format (OGG instead of WAV) causing issues with OpenAI STT API (#5389) 2026-02-24 23:11:56 +08:00
Soulter
c6cc7aae84 chore: bump version to 4.18.2 2026-02-24 23:08:53 +08:00
Soulter
84cd209074 chore: bump version to 4.18.2 2026-02-24 22:48:27 +08:00
Soulter
afda44fbe3 chore: bump version to 4.18.2 2026-02-24 22:44:35 +08:00
Soulter
f5d3b93437 fix(context): improve logging for platform not found in session 2026-02-24 22:37:51 +08:00
Soulter
069a3628fa fix(context): log warning when platform not found for session 2026-02-24 22:37:10 +08:00
氕氙
c81ef2672a fix: pass embedding dimensions to provider apis (#5411) 2026-02-24 22:09:44 +08:00
Soulter
a5ae27cae0 fix(aiocqhttp): enhance shutdown process for aiocqhttp adapter (#5412) 2026-02-24 22:07:42 +08:00
Helian Nuits
73faaf6577 i18n(SubAgentPage): complete internationalization for subagent orchestration page (#5400)
* i18n: complete internationalization for subagent orchestration page

- Replace hardcoded English strings in [SubAgentPage.vue] with i18n keys.
- Update `en-US` and `zh-CN` locales with missing hints, validation messages, and empty state translations.
- Fix translation typos and improve consistency across the SubAgent orchestration UI.

* fix(bug_risk): 避免在模板中的翻译调用上使用 || 'Close' 作为回退值。
2026-02-24 21:04:01 +08:00
Helian Nuits
29dbd085d4 fix(core): 优化 File 组件处理逻辑并增强 OneBot 驱动层路径兼容性 (#5391)
* fix(core): 优化 File 组件处理逻辑并增强 OneBot 驱动层路径兼容性

原因 (Necessity):
1. 内核一致性:AstrBot 内核的 Record 和 Video 组件均具备识别 `file:///` 协议头的逻辑,但 File 组件此前缺失此功能,导致行为不统一。
2. OneBot 协议合规:OneBot 11 标准要求本地文件路径必须使用 `file:///` 协议头。此前驱动层未对裸路径进行自动转换,导致发送本地文件时常触发 retcode 1200 (识别URL失败) 错误。
3. 容器环境适配:在 Docker 等路径隔离环境下,裸路径更容易因驱动或协议端的解析歧义而失效。

更改 (Changes):
- [astrbot/core/message/components.py]:
  - 在 File.get_file() 中增加对 `file:///` 前缀的识别与剥离逻辑,使其与 Record/Video 组件行为对齐。
- [astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py]:
  - 在发送文件前增加自动修正逻辑:若路径为绝对路径且未包含协议头,驱动层将自动补全 `file:///` 前缀。
  - 对 http、base64 及已有协议头,确保不干扰原有的正常传输逻辑。

影响 (Impact):
- 以完全兼容的方式增强了文件发送的鲁棒性。
- 解决了插件在发送日志等本地生成的压缩包时,因路径格式不规范导致的发送失败问题。

* refactor(core): 根据 cr 建议,规范化文件 URI 生成与解析逻辑,优化跨平台兼容性

原因 (Necessity):
1. 修复原生路径与 URI 转换在 Windows 下的不对称问题。
2. 规范化 file: 协议头处理,确保符合 RFC 标准并能在 Linux/Windows 间稳健切换。
3. 增强协议判定准确度,防止对普通绝对路径的误处理。

更改 (Changes):
- [astrbot/core/platform/sources/aiocqhttp]:
  - 弃用手动拼接,改用 `pathlib.Path.as_uri()` 生成标准 URI。
  - 将协议检测逻辑从前缀匹配优化为包含性检测 ("://")。
- [astrbot/core/message/components]:
  - 重构 `File.get_file` 解析逻辑,支持对称处理 2/3 斜杠格式。
  - 针对 Windows 环境增加了对 `file:///C:/` 格式的自动修正,避免 `os.path` 识别失效。
- [data/plugins/astrbot_plugin_logplus]:
  - 在直接 API 调用中同步应用 URI 规范化处理。

影响 (Impact):
- 解决 Docker 环境中因路径不规范导致的 "识别URL失败" 报错。
- 提升了本体框架在 Windows 系统下的文件操作鲁棒性。
2026-02-24 21:03:06 +08:00
Axi404
00b011809a fix: enforce admin guard for sandbox file transfer tools (#5402)
* fix: enforce admin guard for sandbox file transfer tools

* refactor: deduplicate computer tools admin permission checks

* fix: add missing space in permission error message
2026-02-24 20:59:44 +08:00
Axi404
0b46ca7ff3 feat: enable computer-use tools for subagent handoff (#5399) 2026-02-24 16:32:12 +08:00
whatevertogo
9294b44831 fix: resolve pipeline and star import cycles (#5353)
* fix: resolve pipeline and star import cycles

- Add bootstrap.py and stage_order.py to break circular dependencies
- Export Context, PluginManager, StarTools from star module
- Update pipeline __init__ to defer imports
- Split pipeline initialization into separate bootstrap module

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

* fix: add logging for get_config() failure in Star class

* fix: reorder logger initialization in base.py

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 13:53:29 +08:00
Soulter
80fd51119b feat: add support for showing tool call results in agent execution (#5388)
closes: #5329
2026-02-24 00:46:45 +08:00
whatevertogo
5af5ad9e36 test: add comprehensive tests for message event handling (#5355)
* test: add comprehensive tests for message event handling

- Add AstrMessageEvent unit tests (688 lines)
- Add AstrBotMessage unit tests
- Enhance smoke tests with message event scenarios

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

* fix: improve message type handling and add defensive tests

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 23:36:39 +08:00
whatevertogo
7b731ebda8 test: enhance test framework with comprehensive fixtures and mocks (#5354)
* test: enhance test framework with comprehensive fixtures and mocks

- Add shared mock builders for aiocqhttp, discord, telegram
- Add test helpers for platform configs and mock objects
- Expand conftest.py with test profile support
- Update coverage test workflow configuration

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

* refactor(tests): 移动并重构模拟 LLM 响应和消息组件函数

* fix(tests): 优化 pytest_runtest_setup 中的标记检查逻辑

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 23:35:15 +08:00
PyuraMazo
28bfb3b8b2 feat: add plugin load&unload hook (#5331)
* 添加了插件的加载完成和卸载完成的钩子事件

* 添加了插件的加载完成和卸载完成的钩子事件

* format code with ruff

* ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-02-23 23:13:41 +08:00
tangsenfei
351895ae66 fix: 处理配置文件中的 UTF-8 BOM 编码问题 (#5376)
* fix(config): handle UTF-8 BOM in configuration file loading

Problem:
On Windows, some text editors (like Notepad) automatically add UTF-8 BOM
to JSON files when saving. This causes json.decoder.JSONDecodeError:
"Unexpected UTF-8 BOM" and AstrBot fails to start when cmd_config.json
contains BOM.

Solution:
Add defensive check to strip UTF-8 BOM (\ufeff) if present before
parsing JSON configuration file.

Impact:
- Improves robustness and cross-platform compatibility
- No breaking changes to existing functionality
- Fixes startup failure when configuration file has UTF-8 BOM encoding

Relates-to: Windows editor compatibility issues

* style: fix code formatting with ruff

Fix single quote to double quote to comply with project code style.
2026-02-23 22:27:56 +08:00
hanbings
c1009adf52 fix(chatui): add copy rollback path and error message. (#5352)
* fix(chatui): add copy rollback path and error message.

* fix(chatui): fixed textarea leak in the copy button.

* fix(chatui): use color styles from the component library.
2026-02-23 22:24:41 +08:00
Waterwzy
ecaec41208 feat: add hot reload when failed to load plugins (#5334)
* feat:add hot reload when failed to load plugins

* apply bot suggestions
2026-02-23 22:17:48 +08:00
Chen
997b51102b feat: add image urls / paths supports for subagent (#5348)
* fix: 修复5081号PR在子代理执行后台任务时,未正确使用系统配置的流式/非流请求的问题(#5081)

* feat:为子代理增加远程图片URL参数支持

* fix: update description for image_urls parameter in HandoffTool to clarify usage in multimodal tasks

* ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-02-23 22:16:14 +08:00
Helian Nuits
c5bd074c28 chore(README): updated with README.md (#5375)
* chore(README): updated with README.md

* Update README_fr.md

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

* Update README_zh-TW.md

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

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-02-23 22:05:22 +08:00
鸦羽
4c09ed3c09 fix(plugin): update plugin directory handling for reserved plugins (#5369)
* fix(plugin): update plugin directory handling for reserved plugins

* fix(plugin): add warning logs for missing plugin name, object, directory, and changelog
2026-02-23 22:04:47 +08:00
Soulter
a56e43d17e fix: chatui cannot persist file segment (#5386) 2026-02-23 22:02:49 +08:00
Soulter
e357d9de74 feat: add stop functionality for active agent sessions and improve handling of stop requests (#5380)
* feat: add stop functionality for active agent sessions and improve handling of stop requests

* feat: update stop button icon and tooltip in ChatInput component

* fix: correct indentation in tool call handling within ChatRoute class
2026-02-23 20:21:30 +08:00
エイカク
94736ff199 feat(dashboard): make release redirect base URL configurable (#5330)
* feat(dashboard): make desktop release base URL configurable

* refactor(dashboard): use generic release base URL env with upstream default

* fix(dashboard): guard release base URL normalization when env is unset

* refactor(dashboard): use generic release URL helpers and avoid latest suffix duplication
2026-02-22 20:23:32 +09:00
Soulter
aff92a48bf fix: remove changelogs directory from .dockerignore 2026-02-22 17:15:07 +08:00
Soulter
d0998a9dfb fix: remove hard-coded 6s timeout from tavily request 2026-02-22 16:58:49 +08:00
Soulter
3678688433 chore: ruff format 2026-02-22 16:51:46 +08:00
Lovely Moe Moli
0c03177840 fix: 修复 aiohttp 版本过新导致 qq-botpy 报错的问题 (#5316) 2026-02-22 16:45:28 +08:00
Soulter
20ff719c00 cho 2026-02-22 16:43:00 +08:00
Gao Jinzhe
8a8ec492d7 feat: supports spawn subagent as a background task that not block the main agent workflow (#5081)
* feat:为subagent添加后台任务参数

* ruff

* fix: update terminology from 'handoff mission' to 'background task' and refactor related logic

* fix: update terminology from 'background_mission' to 'background_task' in HandoffTool and related logic

* fix(HandoffTool): update background_task description for clarity on usage

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-02-22 13:57:42 +08:00
Helian Nuits
02c1443dd1 fix: 修复新版本插件市场出现插件显示为空白的 bug;纠正已安装插件卡片的排版,统一大小 (#5309)
* fix(ExtensionCard): 解决插件卡片大小不统一的问题

* fix(MarketPluginCard): 解决插件市场不加载插件的问题 (#5303)
2026-02-22 10:32:39 +08:00
Helian Nuits
79301f192c fix(SubAgentPage): 当中间的介绍文本非常长时,Flex 布局会自动挤压右侧的控制按钮区域 (#5306) 2026-02-22 10:31:49 +08:00
Soulter
4b2c854c42 chore: bump version to 4.18.0 2026-02-22 00:17:13 +08:00
Li-shi-ling
d02ee7be8b fix: 修复新建对话时因缺少会话ID导致配置绑定失败的问题 (#5292)
* fix:尝试修改

* fix:添加详细日志

* fix:进行详细修改,并添加日志

* fix:删除所有日志

* fix: 增加安全访问函数

- 给 localStorage 访问加了 try/catch + 可用性判断:dashboard/src/utils/chatConfigBinding.ts:13
- 新增 getFromLocalStorage/setToLocalStorage(在受限存储/无痕模式下异常时回退/忽略)
- getStoredDashboardUsername() / getStoredSelectedChatConfigId() 改为走安全读取:dashboard/src/utils/chatConfigBinding.ts:36       - 新增 setStoredSelectedChatConfigId(),写入失败静默忽略:dashboard/src/utils/chatConfigBinding.ts:44
- 把 ConfigSelector.vue 里直接 localStorage.getItem/setItem 全部替换为上述安全方法:dashboard/src/components/chat/ConfigSelector.vue:81
- 已重新跑过 pnpm run typecheck,通过。

* rm:删除个人用的文档文件

* Revert "rm:删除个人用的文档文件"

This reverts commit 0fceee0543.

* rm:删除个人用的文档文件

* rm:删除个人用的文档文件
2026-02-21 23:50:13 +08:00
Soulter
dbeadb6833 refactor: remove Anthropic OAuth provider implementation and related metadata overrides 2026-02-21 23:40:04 +08:00
evpeople
478cc32de1 Feat/telegram command alias register #5233 (#5234)
* feat: support registering command aliases for Telegram

Now when registering commands with aliases, all aliases will be
registered as Telegram bot commands in addition to the main command.

Example:
    @register_command(command_name="draw", alias={"画", "gen"})
Now /draw, /画, and /gen will all appear in the Telegram command menu.

* feat(telegram): add duplicate command name warning when registering commands

Log a warning when duplicate command names are detected during Telegram
command registration to help identify configuration conflicts.
2026-02-21 23:30:46 +08:00
Minidoracat
7b302445c2 feat: add Anthropic Claude Code OAuth provider and adaptive thinking support (#5209)
* feat: add Anthropic Claude Code OAuth provider and adaptive thinking support

* fix: add defensive guard for metadata overrides and align budget condition with docs

* refactor: adopt sourcery-ai suggestions for OAuth provider

- Use use_api_key=False in OAuth subclass to avoid redundant
  API-key client construction before replacing with auth_token client
- Generalize metadata override helper to merge all dict keys
  instead of only handling 'limit', improving extensibility
2026-02-21 23:29:15 +08:00
エイカク
ae839ef6d8 更新readme文档,补充桌面app说明,并向前移动位置 (#5297)
* docs: update desktop deployment section in README

* docs: refine desktop and launcher deployment descriptions

* Update README.md
2026-02-22 00:26:29 +09:00
Lovely Moe Moli
144a53f4b3 fix: qq official guild message send error (#5287)
* fix: qq official guild message send error

* Update astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py

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

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-02-21 17:24:25 +08:00
Helian Nuits
fa1d1e6034 feat(dashboard): improve plugin platform support display and mobile accessibility (#5271)
* feat(dashboard): improve plugin platform support display and mobile accessibility

- Replace hover-based tooltips with interactive click menus for platform support information.
- Fix mobile touch issues by introducing explicit state control for status capsules.
- Enhance UI aesthetics with platform-specific icons and a structured vertical list layout.
- Add dynamic chevron icons to provide clear visual cues for expandable content.

* refactor(dashboard): refactor market card with computed properties for performance

* refactor(dashboard): unify plugin platform support UI with new reusable chip component

- Create shared 'PluginPlatformChip' component to encapsulate platform meta display.
- Fix mobile interaction bugs by simplifying menu triggers and event handling.
- Add stacked platform icon previews and dynamic chevron indicators within capsules.
- Improve information hierarchy using structured vertical lists for platform details.
- Optimize rendering efficiency with computed properties across both card views.
2026-02-21 17:22:22 +08:00
Soulter
a404436f2c feat: astrbot http api (#5280)
* feat: astrbot http api

* Potential fix for code scanning alert no. 34: Use of a broken or weak cryptographic hashing algorithm on sensitive data

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* fix: improve error handling for missing attachment path in file upload

* feat: implement paginated retrieval of platform sessions for creators

* feat: refactor attachment directory handling in ChatRoute

* feat: update API endpoint paths for file and message handling

* feat: add documentation link to API key management section in settings

* feat: update API key scopes and related configurations in API routes and tests

* feat: enhance API key expiration options and add warning for permanent keys

* feat: add UTC normalization and serialization for API key timestamps

* feat: implement chat session management and validation for usernames

* feat: ignore session_id type chunks in message processing

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-02-21 17:20:26 +08:00
zenfun
48a0b97ac0 test(skills): add skill metadata enrichment tests
11 tests covering:
- _parse_frontmatter_description: standard, description-only, empty,
  missing delimiter, quoted values
- build_skills_prompt: format, absolute path in example, progressive
  disclosure rules, absence of legacy custom fields
- SkillManager.list_skills: local frontmatter parsing, sandbox cache
  description passthrough
2026-02-21 01:06:39 +08:00
zenfun
d21212d0e4 test(computer): add profile-aware sandbox selection tests
17 tests covering:
- ShipyardNeoBooter.capabilities property (tuple, immutability, pre/post boot)
- _apply_sandbox_tools conditional browser tool registration
- _resolve_profile smart selection (user-specified, browser preference,
  API error fallback, empty profiles, auth error pass-through)
- ComputerBooter base class defaults
2026-02-21 01:03:58 +08:00
zenfun
c1917ebf4f fix(computer): resolve absolute skill paths at runtime in scan command
- Resolve skills root via Path.resolve() so LLM prompts always
  reference absolute paths regardless of sandbox cwd
- Use resolved path in skill metadata for reliable cat/head commands
- Add DRY cross-reference comment for frontmatter parser
- Remove dead skills_root_abs field from JSON output (no consumer)
- Remove unnecessary os import and fake resolve/abspath branch
2026-02-21 01:03:45 +08:00
zenfun
b816045f37 refactor(skills): rewrite skills prompt and sanitize example paths
- 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
2026-02-21 01:03:32 +08:00
zenfun
1df1138d04 feat(agent): conditionally register browser tools based on sandbox capabilities
_apply_sandbox_tools now checks the booted session's capabilities
before registering browser tools (BrowserExecTool, BrowserBatchExecTool,
RunBrowserSkillTool).

- If no session exists yet (first request), all tools are registered
  conservatively to avoid breaking the initial interaction
- If a session exists without browser capability, browser tools are
  omitted, preventing CapabilityNotSupportedError from Bay
- Skill lifecycle tools remain unconditionally registered
2026-02-21 01:03:19 +08:00
zenfun
1962ff2def feat(computer): expose sandbox capabilities and smart profile selection
Add capabilities property to ComputerBooter base class (returns None)
and ShipyardNeoBooter (returns immutable tuple from sandbox).

- Extract DEFAULT_PROFILE class constant to replace scattered magic string
- Use tuple[str, ...] for immutability (no defensive copy needed)
- Add _resolve_profile() for smart profile selection:
  - honour user-specified profile
  - query Bay API, prefer browser-capable profiles
  - re-raise auth errors (401/403), fallback on transient failures
- Conditionally create NeoBrowserComponent only when profile has browser
- Log resolved profile and capabilities at boot
2026-02-21 01:03:05 +08:00
香草味的纳西妲喵
bcb12a0717 fix: update contributor avatar image URL to include max size and columns (#5268) 2026-02-21 00:38:11 +08:00
エイカク
5d0fc8ac7a refactor(dashboard): replace legacy isElectron bridge fields with isDesktop (#5269)
* refactor dashboard desktop bridge fields from isElectron to isDesktop

* refactor dashboard runtime detection into shared helper
2026-02-21 01:35:23 +09:00
zenfun
92a8e40cde feat(computer): auto-start Bay container for zero-config Neo integration
Add BayContainerManager to manage Bay container lifecycle via Docker
Engine API, similar to how BoxliteBooter manages Ship containers.

When ShipyardNeoBooter endpoint is empty or set to '__auto__', Bay is
automatically pulled, started, health-checked, and credentials are
read from the container.

- New bay_manager.py: ensure_running, wait_healthy, read_credentials
- Integrate auto-start into ShipyardNeoBooter boot/shutdown
- Reuse Bay container across sessions (unless-stopped policy)
- Friendly error messages for Docker and credential failures
2026-02-20 23:11:19 +08:00
Soulter
a4d37e2c20 chore: ruff format 2026-02-20 23:06:37 +08:00
Soulter
c599fb75ed feat: add OpenRouter provider support and icon 2026-02-20 22:57:20 +08:00
Soulter
e7e0f84edf chore: bump vertion to 4.17.6 2026-02-20 18:40:45 +08:00
Soulter
e19a282c59 fix: streamline error response for empty new username and password in account edit 2026-02-20 18:35:26 +08:00
Raven95676
fbc8667968 fix: simplify error messages for account edit validation 2026-02-20 16:27:28 +08:00
Soulter
cda49c3a9a fix: remove additionalProperties from tool schema properties (#5253)
fixes: #5217
2026-02-20 16:13:20 +08:00
Soulter
4be1027444 fix: update tool status display and add localization for inactive tools 2026-02-20 16:01:55 +08:00
Soulter
46152d3faf fix: enhance PersonaForm layout and improve tool selection display 2026-02-20 15:54:06 +08:00
Soulter
ed4cacfffb fix: all mcp tools exposed to main agent (#5252) 2026-02-20 15:40:13 +08:00
Soulter
52d1979937 chore: remove outdated heihe.md documentation file 2026-02-20 14:47:06 +08:00
NayukiMeko
b30cb12133 fix(provider): 修复 dict 格式 content 导致的 JSON 残留问题 (#5250)
* fix(provider): 修复 dict 格式 content 导致的 JSON 残留问题

修复 _normalize_content 函数未处理 dict 类型 content 的问题。
当 LLM 返回 {"type": "text", "text": "..."} 格式的 content 时,
现在会正确提取 text 字段而非直接转为字符串。

同时改进 fallback 行为,对 None 值返回空字符串。

Fixes #5244

* Update warning message for unexpected dict format

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-02-20 13:48:41 +08:00
whatevertogo
31d4e304fc feat: add password confirmation when changing password (#5247)
* feat: add password confirmation when changing password

Fixes #5177

Adds a password confirmation field to prevent accidental password typos.

Changes:
- Backend: validate confirm_password matches new_password
- Frontend: add confirmation input with validation
- i18n: add labels and error messages for password mismatch

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

* fix(auth): improve error message for password confirmation mismatch

* fix(auth): update password hashing logic and improve confirmation validation

---------

Co-authored-by: whatevertogo <whatevertogo@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 13:41:13 +08:00
Soulter
9a7a594cb5 feat: add support for plugin astrbot-version and platform requirement checks (#5235)
* feat: add support for plugin astrbot-version and platform requirement checks

* fix: remove unsupported platform and version constraints from metadata.yaml

* fix: remove restriction on 'v' in astrbot_version specification format

* ruff format
2026-02-20 13:35:45 +08:00
SnowNightt
e469178a6b Feat/config leave confirm (#5249)
* feat: 配置文件增加未保存提示弹窗

* fix: 移除unsavedChangesDialog插件使用组件方式实现弹窗
2026-02-20 12:55:21 +08:00
Soulter
0a517980b7 fix: update feature request template for clarity and consistency in English and Chinese 2026-02-20 12:07:42 +08:00
エイカク
9c691b2266 chore: remove Electron desktop pipeline and switch to tauri repo (#5226)
* ci: remove Electron desktop build from release pipeline

* chore: remove electron desktop and switch to tauri release trigger

* ci: remove desktop workflow dispatch trigger

* refactor: migrate data paths to astrbot_path helpers

* fix: point desktop update prompt to AstrBot-desktop releases
2026-02-19 23:04:18 +09:00
雪語
3597726aad fix(core): terminate active events on reset/new/del to prevent stale responses (#5225)
* fix(core): terminate active events on reset/new/del to prevent stale responses

Closes #5222

* style: fix import sorting in scheduler.py
2026-02-19 19:26:47 +08:00
Soulter
a4a37c268d docs: update related repo links 2026-02-19 18:11:07 +08:00
NanoRocky
651a0645c5 fix: 修复仅发送 JSON 消息段时的空消息回复报错 (#5208)
* Fix Register_Stage

· 补全 JSON 消息判断,修复发送 JSON 消息时遇到 “消息为空,跳过发送阶段” 的问题。
· 顺带补全其它消息类型判断。
Co-authored-by: Pizero <zhaory200707@outlook.com>

* Fix formatting and comments in stage.py

* Format stage.py

---------

Co-authored-by: Pizero <zhaory200707@outlook.com>
2026-02-19 17:47:08 +08:00
Dream Tokenizer
bf3fa3e918 fix: 改进微信公众号被动回复处理机制,引入缓冲与分片回复,并优化超时行为 (#5224)
* 修复wechat official 被动回复功能

* ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-02-19 17:42:38 +08:00
Soulter
3b2ce9f500 feat: add admin permission checks for Python and Shell execution (#5214) 2026-02-19 01:48:48 +08:00
zenfun
3769f145ee feat(dashboard): validate Bay connectivity on config save
When saving config with shipyard_neo sandbox, _validate_neo_connectivity()
performs an async /health check against the Bay endpoint. If Bay is
unreachable, a ⚠️ warning is appended to the success snackbar message.
Config still saves successfully — the warning is informational only.
2026-02-19 01:41:29 +08:00
zenfun
18ebeae318 test(computer): add tests for credentials discovery and config logging
19 tests in test_computer_config.py:
- TestDiscoverBayCredentials (9 tests): env priority, cwd fallback,
  missing file, empty key, malformed JSON, endpoint mismatch, slash normalization
- TestLogComputerConfigChanges (10 tests): runtime change, sandbox key change,
  token masking, empty token label, missing provider_settings, add/remove keys

Uses unittest.mock.patch on AstrBot custom logger for reliable assertions.
2026-02-19 01:26:04 +08:00
zenfun
7e246477f0 fix(dashboard): graceful error handling for Neo skills when unconfigured
- Add _discover_bay_credentials() auto-discovery in _get_neo_client_config()
- Catch ValueError separately in _with_neo_client(), log at DEBUG instead of
  ERROR with full traceback — prevents log spam when visiting Skills page
  without Bay configured
2026-02-19 01:25:50 +08:00
Soulter
20d6ff4620 chore: bump version to 4.17.5 2026-02-18 22:04:43 +08:00
Chiu Chun-Hsien
a2b61e2ab8 refactor: extract Voice_messages_forbidden fallback into shared helper with typed BadRequest exception (#5204)
- Add _send_voice_with_fallback helper to deduplicate voice forbidden handling
- Catch telegram.error.BadRequest instead of bare Exception with string matching
- Add text field to Record component to preserve TTS source text
- Store original text in Record during TTS conversion for use as document caption
- Skip _send_chat_action when chat_id is empty to avoid unnecessary warnings
2026-02-18 21:45:19 +08:00
sanyekana
c6289d8f75 feat(core): add plugin error hook for custom error routing (#5192)
* feat(core): add plugin error hook for custom error routing

* fix(core): align plugin error suppression with event stop state
2026-02-18 21:38:27 +08:00
Soulter
567390e27c feat: add LINE support to multiple language README files 2026-02-18 21:35:27 +08:00
Soulter
0c0f8bf484 chore: ruff format 2026-02-18 18:22:06 +08:00
Soulter
ae0a9cb591 docs: update readme 2026-02-18 18:20:08 +08:00
Soulter
3f4d7255a0 feat: supports aihubmix 2026-02-18 18:11:13 +08:00
Soulter
b8d2499475 feat: add MarketPluginCard component and integrate random plugin feature in ExtensionPage (#5190)
* feat: add MarketPluginCard component and integrate random plugin feature in ExtensionPage

* feat: update random plugin selection logic to use pluginMarketData and refresh on relevant events
2026-02-18 17:29:04 +08:00
SnowNightt
8cb26d886f fix: 修复选择配置文件进入配置文件管理弹窗直接关闭弹窗显示的配置文件不正确 (#5174) 2026-02-18 16:33:18 +08:00
時壹
3ca8dd204f fix: prevent duplicate error message when all LLM providers fail (#5183) 2026-02-18 16:29:35 +08:00
RC-CHN
bc3e09f47b refactor(computer): split sandbox skill sync phases
separate sandbox skill syncing into distinct apply and scan steps
while keeping the legacy combined command for compatibility

improve observability by adding phase-based logs and richer shell
error details that include exit code, stderr, and stdout tail

reuse a shared python-exec command builder to reduce duplication
and keep command generation consistent
2026-02-18 13:35:17 +08:00
Soulter
3476afce41 feat: supports send markdown message in qqofficial (#5173)
* feat: supports send markdown message in qqofficial

closes: #1093 #918 #4180 #4264

* ruff format
2026-02-18 00:35:52 +08:00
Soulter
9b0e24ec49 chore: bump version to 4.17.4 2026-02-17 21:19:53 +08:00
Soulter
92d71fffe9 feat: add announcement section to WelcomePage and localize announcement title 2026-02-17 21:15:12 +08:00
Soulter
80c22f4f72 feat: add FAQ link to vertical sidebar and update navigation for localization 2026-02-17 21:01:29 +08:00
Soulter
6e22d266dd feat: implement search functionality in configuration components and update UI (#5168) 2026-02-17 20:47:24 +08:00
Soulter
4c285fb521 feat: add unsaved changes notice to configuration page and update messages 2026-02-17 20:32:25 +08:00
Helian Nuits
51c3521aaa ui(CronJobPage): fix action column buttons overlapping in CronJobPage (#5163)
- 修改前:操作列容器仅使用 `d-flex`,在页面宽度变窄时,子元素(开关和删除按钮)会因为宽度挤压而发生视觉重叠,甚至堆叠在一起。
- 修改后:
    1. 为容器添加了 `flex-nowrap`,强制禁止子元素换行。
    2. 设置了 `min-width: 140px`,确保该列拥有固定的保护空间,防止被其他长文本列挤压。
    3. 增加了 `gap: 12px` 间距,提升了操作辨识度并优化了点击体验。
2026-02-17 18:58:05 +08:00
Soulter
32112a3326 feat: enhance PersonaForm component with responsive design and improved styling (#5162)
fix: #5159
2026-02-17 18:46:52 +08:00
Soulter
f22221f781 fix: improve permission denied message for local execution in Python and shell tools 2026-02-17 18:02:41 +08:00
RC-CHN
707db768ea style: format code 2026-02-17 17:26:37 +08:00
RC-CHN
591803d407 refactor(skills): centralize neo promote and sync flow
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
2026-02-17 17:20:42 +08:00
RC-CHN
b48919246d refactor(api): centralize neo client lifecycle in skills route
extract a shared `_with_neo_client` wrapper to handle neo client
setup, teardown, and error responses in one place.

reduce duplicated try/except and `BayClient` context boilerplate across
neo skills endpoints while preserving existing request validation and
response payloads.
2026-02-17 17:06:11 +08:00
RC-CHN
cf9a7235f7 fix(computer): return none for unsupported browser capability
set the base booter browser property to return None instead of
raising NotImplementedError so callers can handle missing browser
support through capability checks
2026-02-17 16:59:05 +08:00
RC-CHN
d62a6f107b fix(computer): mask bay api key in logs
Also add shipyard-neo-sdk dependency for neo support
2026-02-17 16:40:55 +08:00
Ruochen Pan
1a539830f8 Merge branch 'master' into feat/neo-skill-self-iteration 2026-02-17 16:23:14 +08:00
Soulter
4250d997b3 feat: enhance provider sources panel with styled menu and mobile support 2026-02-17 16:14:35 +08:00
Soulter
153d8cef6b feat: add NVIDIA provider template (#5157)
fixes: #5156
2026-02-17 16:08:35 +08:00
Soulter
c9cdf47603 chore: ruff format 2026-02-17 14:33:27 +08:00
Soulter
55ac878648 chore: bump version to 4.17.3 2026-02-17 14:09:10 +08:00
Soulter
60abddada3 fix: enhance handle_result to support event context and webchat image sending 2026-02-17 14:03:29 +08:00
Soulter
bbc583cc8d fix: enhance plugin metadata handling by injecting attributes before instantiation (#5155) 2026-02-17 14:01:31 +08:00
Soulter
7906030037 fix: 'Plain' object has no attribute 'text' when using python 3.14 (#5154) 2026-02-17 13:51:25 +08:00
エイカク
06b385697d fix(desktop): include runtime deps for builtin plugins in backend build (#5146) 2026-02-17 11:43:19 +09:00
Raven95676
059008a903 fix: prevent updates for AstrBot launched via launcher 2026-02-17 09:33:45 +08:00
zenfun
418913aa53 docs: add PR verification workflow to CONTRIBUTING.md
Document make pr-test-neo and make pr-test-full commands for local
CI-equivalent verification before submitting PRs.
2026-02-17 04:25:06 +08:00
zenfun
4b07aa2bc3 test(computer): add tests for credentials discovery and config logging
19 new tests in test_computer_config.py:
- TestDiscoverBayCredentials (9 tests): env priority, cwd fallback,
  missing file, empty key, malformed JSON, endpoint mismatch, slash normalization
- TestLogComputerConfigChanges (10 tests): runtime change, sandbox key change,
  token masking, empty token label, missing provider_settings, add/remove keys
2026-02-17 04:24:55 +08:00
zenfun
64d8daa67d feat(scripts): update start-with-neo.sh for auto-provisioned API key
- Generated config uses allow_anonymous: false (triggers auto-provision)
- Set BAY_DATA_DIR so credentials.json writes to pkgs/bay/
- Add read_bay_credentials() to extract auto-generated key after boot
- Display API key in config hints for easy AstrBot setup
2026-02-17 04:24:44 +08:00
zenfun
9d44947500 feat(dashboard): update Shipyard Neo config hints
- Endpoint hint: mention default port 8114
- Access Token hint: mention sk-bay-* format and credentials.json auto-discovery
- Updated in default.py, zh-CN, and en-US i18n files
2026-02-17 04:24:34 +08:00
zenfun
4043a10531 fix(computer): improve ShipyardNeoBooter error message
Include default endpoint URL (http://127.0.0.1:8114) and credentials.json
auto-discovery hint in the ValueError message when config is incomplete.
2026-02-17 04:24:24 +08:00
zenfun
7c8dac2fd5 feat(computer): add Bay credentials.json auto-discovery
When shipyard_neo_access_token is not configured, _discover_bay_credentials()
searches for Bay's credentials.json in:
1. BAY_DATA_DIR env var
2. Mono-repo relative path ../pkgs/bay/
3. Current working directory

Enables zero-config dev mode when Bay runs locally alongside AstrBot.
2026-02-17 04:24:12 -06:00
Soulter
97c9e95211 chore: ruff format 2026-02-17 02:31:38 +08:00
Soulter
a4be369e43 chore: bump version to 4.17.1 2026-02-17 02:30:13 +08:00
Soulter
bdaca78750 fix: add support for collecting data from builtin stars in electron pyinstaller build (#5145) 2026-02-17 02:27:07 +08:00
Soulter
6326d7e4ba fix: add MCP tools to function tool set in _plugin_tool_fix (#5144) 2026-02-17 02:19:36 +08:00
Soulter
a809a09e55 docs: Added instructions for deploying AstrBot using AstrBot Launcher. (#5136)
Added instructions for deploying AstrBot using AstrBot Launcher.
2026-02-16 17:06:56 +08:00
zenfun
963122b916 chore: update gitignore, Makefile, skills route, and test scaffolding 2026-02-16 02:38:01 +08:00
zenfun
aa3b012d60 feat: add Shipyard Neo quick-start script
Add scripts/start-with-neo.sh: one-click launcher that auto-generates
Bay config.yaml (anonymous mode, host_port), pulls Ship image, starts
Bay (port 8114) with health check, then starts AstrBot in foreground.
Ctrl+C stops both services. Supports BAY_PORT env var override.
2026-02-16 02:37:48 +08:00
zenfun
401dfb9ee2 feat(dashboard): log Computer/sandbox config changes on save
Add _log_computer_config_changes() to detect and log modifications to
computer_use_runtime and sandbox.* keys when saving config via Dashboard.
Sensitive fields (tokens/secrets) are masked in log output.
2026-02-16 02:37:24 +08:00
zenfun
1d81c52950 feat(computer): add INFO-level lifecycle logging to booter implementations
Add [Computer] prefixed INFO logs to:
- shipyard_neo.py: shutdown, upload_file, download_file, available
- shipyard.py: shutdown, upload_file, download_file, available
- boxlite.py: upload_file success path
- computer_client.py: sync_skills_to_active_sandboxes, _sync_skills_to_sandbox

Improves traceability of sandbox lifecycle events.
2026-02-16 02:37:14 +08:00
Soulter
52c4ef2d87 chore: bump version to 4.17.1 2026-02-15 23:45:34 +08:00
Soulter
52c31fabe2 fix: update retention logic in LogManager to handle backup count correctly 2026-02-15 23:42:12 +08:00
NayukiMeko
79e239ad97 fix: handle list format content from OpenAI-compatible APIs (#5128)
* fix: handle list format content from OpenAI-compatible APIs

Some LLM providers (e.g., GLM-4.5V via SiliconFlow) return content as
list[dict] format like [{'type': 'text', 'text': '...'}] instead of
plain string. This causes the raw list representation to be displayed
to users.

Changes:
- Add _normalize_content() helper to extract text from various content formats
- Use json.loads instead of ast.literal_eval for safer parsing
- Add size limit check (8KB) before attempting JSON parsing
- Only convert lists that match OpenAI content-part schema (has 'type': 'text')
  to avoid collapsing legitimate list-literal replies like ['foo', 'bar']
- Add strip parameter to preserve whitespace in streaming chunks
- Clean up orphan </think> tags that may leak from some models

Fixes #5124

* fix: improve content normalization safety

- Try json.loads first, fallback to ast.literal_eval for single-quoted
  Python literals to avoid corrupting apostrophes (e.g., "don't")
- Coerce text values to str to handle null or non-string text fields
2026-02-15 23:30:47 +08:00
Soulter
8abaf1015d chore: bump version to 4.17.0 2026-02-15 21:51:00 +08:00
Soulter
9a0c814fd4 feat: add SSL configuration options for WebUI and update related logging (#5117) 2026-02-15 17:43:36 +08:00
Soulter
c64e1b42a4 feat: replace colorlog with loguru for enhanced logging support (#5115) 2026-02-15 17:11:03 +08:00
Soulter
2d23c36067 feat: add Afdian support card to resources section in WelcomePage 2026-02-15 16:20:34 +08:00
Soulter
754144ad99 feat: add fallback chat model chain in tool loop runner (#5109)
* feat: implement fallback provider support for chat models and update configuration

* feat: enhance provider selection display with count and chips for selected providers

* feat: update fallback chat providers to use provider settings and add warning for non-list fallback models
2026-02-15 11:51:34 +08:00
Waterwzy
0faf109c2a feat: support hot reload after plugin load failure (#5043)
* add :Support hot reload after plugin load failure

* Apply suggestions from code review

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

* fix:reformat code

* fix:reformat code

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-02-13 18:37:20 +08:00
evpeople
7d1eff3ec4 fix #5089: add uv lock step in Dockerfile before export (#5091)
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-02-13 18:34:26 +08:00
Soulter
e295c470a5 fix: remove unnecessary frozen flag from requirements export in Dockerfile
fixes: #5089
2026-02-13 18:09:49 +08:00
Li-shi-ling
935168c024 fix-correct-FIRST_NOTICE.md-locale-path-resolution (#5083) (#5082)
* fix:修改配置文件目录

* fix:添加备选的FIRST_NOTICE.zh-CN.md用于兼容
2026-02-13 13:15:08 +08:00
Soulter
f44961d065 feat: add LINE platform support with adapter and configuration (#5085) 2026-02-13 13:01:48 +08:00
zenfun
40c7cf3901 feat(skills): merge sandbox built-ins with uploaded skill sync 2026-02-13 03:20:51 +08:00
Soulter
0c7a95ccd8 chore: bump version to 4.16.0 (#5074) 2026-02-12 22:55:42 +08:00
Soulter
09215bad57 fix: add config tabs and routing for normal and system configurations 2026-02-12 22:48:17 +08:00
エイカク
4ff07e3c74 fix: 完善转发引用解析与图片回退并支持配置化控制 (#5054)
* feat: support fallback image parsing for quoted messages

* fix: fallback parse quoted images when reply chain has placeholders

* style: format network utils with ruff

* test: expand quoted parser coverage and improve fallback diagnostics

* fix: fallback to text-only retry when image requests fail

* fix: tighten image fallback and resolve nested quoted forwards

* refactor: simplify quoted message extraction and dedupe images

* fix: harden quoted parsing and openai error candidates

* fix: harden quoted image ref normalization

* refactor: organize quoted parser settings and logging

* fix: cap quoted fallback images and avoid retry loops

* refactor: split quoted message parser into focused modules

* refactor: share onebot segment parsing logic

* refactor: unify quoted message parsing flow

* feat: move quoted parser tuning to provider settings

* fix: add missing i18n metadata for quoted parser settings

* chore: refine forwarded message setting labels
2026-02-12 23:42:29 +09:00
stevessr
473e01aadd feat: add i18n supports for custom platform adapters (#5045)
* Feat: 为插件提供的适配器的元数据&i18n提供数据通路

* chore: update docstrings with pull request references

Added references to pull request 5045 in docstrings.

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-02-12 21:49:12 +08:00
Soulter
cd5312ba77 fix: chunk err when using openrouter deepseek (#5069) 2026-02-12 19:26:12 +08:00
Soulter
d87bfb0d5d perf: 优化分段回复间隔时间的初始化逻辑 (#5068)
fixes: #5059
2026-02-12 19:18:23 +08:00
Soulter
d2de0ea5ad feat: QQ 官方机器人平台支持主动推送消息、私聊场景下支持接收文件 (#5066)
* feat: QQ 官方机器人平台支持主动推送消息、私聊场景下支持接收文件

* feat: enhance QQOfficialWebhook to remember session scenes for group, channel, and friend messages
2026-02-12 19:07:53 +08:00
xzj0898
4af064fd17 fix: 修复备份时缺失的人格文件夹映射 (#5042) 2026-02-12 16:40:45 +08:00
letr
8ab2b515f6 docs: sync and fix readme typo (#5055)
* docs: fix index typo

* docs: fix typo in README_en.md

- 移除英文README中意外出现的俄语,并替换为英语

* docs: fix html typo

- remove unused '</p>'

* docs: sync table with README

* docs: sync README header format

- keep the README header format consistent

* doc: sync key features

* style: format files

- Fix formatting issues from previous PR

* fix: correct md anchor link

* docs: correct typo in README_fr.md

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

* docs: correct typo in README_zh-TW.md

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

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-02-12 16:37:25 +08:00
SnowNightt
51a1c0e375 fix: 修复更新日志、官方文档弹窗双滚动条问题 (#5060) 2026-02-12 16:36:05 +08:00
evpeople
30a0098b2a feat: add send_chat_action for Telegram platform adapter (#5037)
* feat: add send_chat_action for Telegram platform adapter

Add typing/upload indicator when sending messages via Telegram.
- Added _send_chat_action helper method for sending chat actions
- Send appropriate action (typing, upload_photo, upload_document, upload_voice)
  before sending different message types
- Support streaming mode with typing indicator
- Support supergroup with message_thread_id

* refactor(telegram): extract chat action helpers and add throttling

- Add ACTION_BY_TYPE mapping for message type to action priority
- Add _get_chat_action_for_chain() to determine action from message chain
- Add _send_media_with_action() for upload → send → restore typing pattern
- Add _ensure_typing() helper for typing status
- Add chat action throttling (0.5s) in streaming mode to avoid rate limits
- Update type annotation to ChatAction | str for better static checking

* feat(telegram): implement send_typing method for Telegram platform

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-02-12 14:46:06 +08:00
Soulter
e3cb9eb8af chore: ruff format 2026-02-12 13:56:33 +08:00
Soulter
b0de33c801 fix: provider extra param dialog key display error 2026-02-12 13:09:34 +08:00
letr
bcdd8c463c docs: clean and sync README (#5014)
* fix: close missing div in README

* fix: sync README_zh-TW with README

* fix: sync README

* fix: correct typo

correct url in README_en README_fr README_ru

* docs: sync README_en with README

* Update README_en.md

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

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-02-12 01:17:15 +08:00
Soulter
336e2a2c40 fix: update error logging message for connection failures 2026-02-12 01:14:49 +08:00
Limitless
338d8a6610 fix: close unawaited reset coroutine on early return (#5033)
When an OnLLMRequestEvent hook stops event propagation, the
reset_coro created by build_main_agent was never awaited, causing
a RuntimeWarning. Close the coroutine explicitly before returning.

Fixes #5032

Co-authored-by: Limitless2023 <limitless@users.noreply.github.com>
2026-02-12 01:07:13 +08:00
Soulter
9d93bda3fe feat: temporary file handling and introduce TempDirCleaner (#5026)
* 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
2026-02-12 01:04:48 +08:00
エイカク
a8dda20a30 fix: 提升打包版桌面端启动稳定性并优化插件依赖处理 (#5031)
* fix(desktop): rotate electron and backend logs

* refactor(desktop): centralize log rotation defaults and debug fs errors

* fix(desktop): harden rotation fs ops and buffer backend log writes

* refactor(desktop): extract buffered logger and reduce sync stat calls

* refactor(desktop): simplify rotation flow and harden logger config

* fix(desktop): make app logging async and flush-safe

* fix: harden app log path switching and debug-gated rotation errors

* fix: cap buffered log chunk size during path switch

* fix: avoid redundant plugin reinstall and upgrade electron

* fix: stop webchat tasks cleanly and bind packaged backend to localhost

* fix: unify platform shutdown and await webchat listener cleanup

* fix: improve startup logs for dashboard and onebot listeners

* fix: revert extra startup service logs

* fix: harden plugin import recovery and webchat listener cleanup

* fix: pin dashboard ci node version to 24.13.0

* fix: avoid duplicate webchat listener cleanup on terminate

* refactor: clarify platform task lifecycle management

* fix: continue platform shutdown when terminate fails
2026-02-12 01:04:04 +08:00
Soulter
cd7755fe07 feat: add first notice feature with multilingual support and UI integration 2026-02-12 00:00:53 +08:00
zenfun
afe292de35 fix: address neo skill review findings 2026-02-11 19:35:01 +08:00
エイカク
dc995af34b fix(desktop): 为 Electron 与后端日志增加按大小轮转 (#5029)
* fix(desktop): rotate electron and backend logs

* refactor(desktop): centralize log rotation defaults and debug fs errors

* fix(desktop): harden rotation fs ops and buffer backend log writes

* refactor(desktop): extract buffered logger and reduce sync stat calls

* refactor(desktop): simplify rotation flow and harden logger config

* fix(desktop): make app logging async and flush-safe

* fix: harden app log path switching and debug-gated rotation errors

* fix: cap buffered log chunk size during path switch
2026-02-11 20:17:57 +09:00
zenfun
d4dcc6430f chore: apply pre-commit formatting fixes for neo integration 2026-02-11 17:34:07 +08:00
zenfun
a8cc995633 feat(dashboard): add neo skills APIs and management UI 2026-02-11 17:14:55 +08:00
zenfun
73251db1da feat(skills): add neo lifecycle tools and stable sync manager 2026-02-11 17:14:47 +08:00
zenfun
d16398a0e8 feat(computer): add shipyard_neo booter runtime and sandbox config 2026-02-11 17:14:38 +08:00
LIghtJUNction
331ada02fd docs: add AUR installation method (#4879)
* docs: sync system package manager installation instructions to all languages

* Update README.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update README.md

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

* fix/typo

* refactor: update system package manager installation instructions for Arch Linux across multiple language README files

* feat: add installation command for AstrBot in multiple language README files

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-02-11 13:36:17 +08:00
Soulter
80e1231e9a feat: adding support for media and quoted message attachments for feishu (#5018) 2026-02-11 13:26:27 +08:00
エイカク
e61b29ec6a fix: harden plugin dependency loading in frozen app runtime (#5015)
* fix: compare plugin versions semantically in market updates

* fix: prioritize plugin site-packages for in-process pip

* fix: reload starlette from plugin target site-packages

* fix: harden plugin dependency import precedence in frozen runtime

* fix: improve plugin dependency conflict handling

* refactor: simplify plugin conflict checks and version utils

* fix: expand transitive plugin dependencies for conflict checks

* fix: recover conflicting plugin dependencies during module prefer

* fix: reuse renderer restart flow for tray backend restart

* fix: add recoverable plugin dependency conflict handling

* revert: remove plugin version comparison changes

* fix: add missing tray restart backend labels
2026-02-11 13:01:44 +09:00
Soulter
16d49d568b fix: add reminder for v4.14.8 users regarding manual redeployment due to a bug 2026-02-10 23:20:49 +08:00
Soulter
776e17062c chore: bump version to 4.15.0 (#5003) 2026-02-10 23:17:23 +08:00
エイカク
8fa8c14b0b fix: 修复app内重启异常,修复app内点击重启不能立刻提示重启,以及在后端就绪时及时刷新界面的问题 (#5013)
* fix: patch pip distlib finder for frozen electron runtime

* fix: use certifi CA bundle for runtime SSL requests

* fix: configure certifi CA before core imports

* fix: improve mac font fallback for dashboard text

* fix: harden frozen pip patch and unify TLS connector

* refactor: centralize dashboard CJK font fallback stacks

* perf: reuse TLS context and avoid repeated frozen pip patch

* refactor: bootstrap TLS setup before core imports

* fix: use async confirm dialog for provider deletions

* fix: replace native confirm dialogs in dashboard

- Add shared confirm helper in dashboard/src/utils/confirmDialog.ts for async dialog usage with safe fallback.

- Migrate provider, chat, config, session, platform, persona, MCP, backup, and knowledge-base delete/close confirmations to use the shared helper.

- Remove scattered inline confirm handling to keep behavior consistent and avoid native blocking dialog focus/caret issues in Electron.

* fix: capture runtime bootstrap logs after logger init

- Add bootstrap record buffer in runtime_bootstrap for early TLS patch logs before logger is ready.

- Flush buffered bootstrap logs to astrbot logger at process startup in main.py.

- Include concrete exception details for TLS bootstrap failures to improve diagnosis.

* fix: harden runtime bootstrap and unify confirm handling

- Simplify bootstrap log buffering and add a public initialize hook for non-main startup paths.

- Guard aiohttp TLS patching with feature/type checks and keep graceful fallback when internals are unavailable.

- Standardize dashboard confirmation flow via shared confirm helpers across composition and options API components.

* refactor: simplify runtime tls bootstrap and tighten confirm typing

* refactor: align ssl helper namespace and confirm usage

* fix: avoid frozen restart crash from multiprocessing import

* fix: include missing frozen dependencies for windows backend

* fix: use execv for stable backend reboot args

* Revert "fix: use execv for stable backend reboot args"

This reverts commit 9cc27becff.

* Revert "fix: include missing frozen dependencies for windows backend"

This reverts commit 52554bea1f.

* Revert "fix: avoid frozen restart crash from multiprocessing import"

This reverts commit 10548645b0.

* fix: reset pyinstaller onefile env before reboot

* fix: unify electron restart path and tray-exit backend cleanup

* fix: stabilize desktop restart detection and frozen reboot args

* fix: make dashboard restart wait detection robust

* fix: revert dashboard restart waiting interaction tweaks

* fix: pass auth token for desktop graceful restart

* fix: avoid false failure during graceful restart wait

* fix: start restart waiting before electron restart call

* fix: harden restart waiting and reboot arg parsing

* fix: parse start_time as numeric timestamp

* fix: preserve windows frozen reboot argv quoting

* fix: align restart waiting with electron restart timing

* fix: tighten graceful restart and unmanaged kill safety
2026-02-10 22:21:04 +09:00
エイカク
64de474139 fix: 修复 Windows 打包版后端重启失败问题 (#5009)
* fix: patch pip distlib finder for frozen electron runtime

* fix: use certifi CA bundle for runtime SSL requests

* fix: configure certifi CA before core imports

* fix: improve mac font fallback for dashboard text

* fix: harden frozen pip patch and unify TLS connector

* refactor: centralize dashboard CJK font fallback stacks

* perf: reuse TLS context and avoid repeated frozen pip patch

* refactor: bootstrap TLS setup before core imports

* fix: use async confirm dialog for provider deletions

* fix: replace native confirm dialogs in dashboard

- Add shared confirm helper in dashboard/src/utils/confirmDialog.ts for async dialog usage with safe fallback.

- Migrate provider, chat, config, session, platform, persona, MCP, backup, and knowledge-base delete/close confirmations to use the shared helper.

- Remove scattered inline confirm handling to keep behavior consistent and avoid native blocking dialog focus/caret issues in Electron.

* fix: capture runtime bootstrap logs after logger init

- Add bootstrap record buffer in runtime_bootstrap for early TLS patch logs before logger is ready.

- Flush buffered bootstrap logs to astrbot logger at process startup in main.py.

- Include concrete exception details for TLS bootstrap failures to improve diagnosis.

* fix: harden runtime bootstrap and unify confirm handling

- Simplify bootstrap log buffering and add a public initialize hook for non-main startup paths.

- Guard aiohttp TLS patching with feature/type checks and keep graceful fallback when internals are unavailable.

- Standardize dashboard confirmation flow via shared confirm helpers across composition and options API components.

* refactor: simplify runtime tls bootstrap and tighten confirm typing

* refactor: align ssl helper namespace and confirm usage

* fix: avoid frozen restart crash from multiprocessing import

* fix: include missing frozen dependencies for windows backend

* fix: use execv for stable backend reboot args

* Revert "fix: use execv for stable backend reboot args"

This reverts commit 9cc27becff.

* Revert "fix: include missing frozen dependencies for windows backend"

This reverts commit 52554bea1f.

* Revert "fix: avoid frozen restart crash from multiprocessing import"

This reverts commit 10548645b0.

* fix: reset pyinstaller onefile env before reboot

* fix: unify electron restart path and tray-exit backend cleanup

* fix: stabilize desktop restart detection and frozen reboot args

* fix: make dashboard restart wait detection robust

* fix: revert dashboard restart waiting interaction tweaks

* fix: pass auth token for desktop graceful restart

* fix: avoid false failure during graceful restart wait

* fix: start restart waiting before electron restart call

* fix: harden restart waiting and reboot arg parsing

* fix: parse start_time as numeric timestamp
2026-02-10 21:33:06 +09:00
エイカク
d35771f97d fix: stabilize packaged runtime pip/ssl behavior and mac font fallback (#5007)
* fix: patch pip distlib finder for frozen electron runtime

* fix: use certifi CA bundle for runtime SSL requests

* fix: configure certifi CA before core imports

* fix: improve mac font fallback for dashboard text

* fix: harden frozen pip patch and unify TLS connector

* refactor: centralize dashboard CJK font fallback stacks

* perf: reuse TLS context and avoid repeated frozen pip patch

* refactor: bootstrap TLS setup before core imports

* fix: use async confirm dialog for provider deletions

* fix: replace native confirm dialogs in dashboard

- Add shared confirm helper in dashboard/src/utils/confirmDialog.ts for async dialog usage with safe fallback.

- Migrate provider, chat, config, session, platform, persona, MCP, backup, and knowledge-base delete/close confirmations to use the shared helper.

- Remove scattered inline confirm handling to keep behavior consistent and avoid native blocking dialog focus/caret issues in Electron.

* fix: capture runtime bootstrap logs after logger init

- Add bootstrap record buffer in runtime_bootstrap for early TLS patch logs before logger is ready.

- Flush buffered bootstrap logs to astrbot logger at process startup in main.py.

- Include concrete exception details for TLS bootstrap failures to improve diagnosis.

* fix: harden runtime bootstrap and unify confirm handling

- Simplify bootstrap log buffering and add a public initialize hook for non-main startup paths.

- Guard aiohttp TLS patching with feature/type checks and keep graceful fallback when internals are unavailable.

- Standardize dashboard confirmation flow via shared confirm helpers across composition and options API components.

* refactor: simplify runtime tls bootstrap and tighten confirm typing

* refactor: align ssl helper namespace and confirm usage
2026-02-10 16:42:43 +09:00
圣达生物多
4667729752 Merge branch 'AstrBotDevs:master' into Sjshi763/issue4409 2026-02-10 11:39:41 +08:00
dependabot[bot]
7a4d20d329 chore(deps): bump the github-actions group with 2 updates (#5006)
Bumps the github-actions group with 2 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [actions/download-artifact](https://github.com/actions/download-artifact).


Updates `astral-sh/setup-uv` from 6 to 7
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v6...v7)

Updates `actions/download-artifact` from 6 to 7
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-10 11:10:26 +08:00
Li-shi-ling
aab095347f fix: 'HandoffTool' object has no attribute 'agent' (#5005)
* fix: 移动agent的位置到super().__init__之后

* add: 添加一行注释
2026-02-10 11:01:49 +08:00
エイカク
1addd5b2ab perf: 稳定源码与 Electron 打包环境下的 pip 安装行为,并修复非 Electron 环境下点击 WebUI 更新按钮时出现跳转对话框的问题 (#4996)
* fix: handle pip install execution in frozen runtime

* fix: harden pip subprocess fallback handling

* fix: scope global data root to packaged electron runtime

* refactor: inline frozen runtime check for electron guard

* fix: prefer current interpreter for source pip installs

* fix: avoid resolving venv python symlink for pip

* refactor: share runtime environment detection utilities

* fix: improve error message when pip module is unavailable

* fix: raise ImportError when pip module is unavailable

* fix: preserve ImportError semantics for missing pip

* fix: 修复非electron app环境更新时仍然显示electron更新对话框的问题

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-02-09 23:12:18 +08:00
Soulter
da4bb6549c feat: enhance persona tool management and update UI localization for subagent orchestration (#4990)
* feat: enhance persona tool management and update UI localization for subagent orchestration

* fix: remove debug logging for final ProviderRequest in build_main_agent function
2026-02-09 22:38:05 +08:00
Soulter
7193454d50 feat: enhance WecomAIBotAdapter and WecomAIBotMessageEvent for improved streaming message handling (#5000)
fixes: #3965
2026-02-09 22:30:24 +08:00
Soulter
d204b92877 feat: 企业微信智能机器人支持主动消息推送以及发送视频、文件等消息类型支持 (#4999) 2026-02-09 22:16:44 +08:00
Soulter
04faf26140 feat: 企业微信应用 支持主动消息推送,并优化企微应用、微信公众号、微信客服音频相关的处理 (#4998) 2026-02-09 22:15:11 +08:00
鸦羽
67b81c279b fix: collect certifi data in desktop backend build (#4995) 2026-02-09 19:40:32 +09:00
エイカク
2afb08d8b2 fix: handle pip install execution in frozen runtime (#4985)
* fix: handle pip install execution in frozen runtime

* fix: harden pip subprocess fallback handling
2026-02-09 15:19:01 +08:00
Soulter
06b2c7cb16 feat: enhance Dingtalk adapter with active push message and image, video, audio message type (#4986) 2026-02-09 15:17:55 +08:00
Copilot
9c12803ddd feat: add delete button to persona management dialog (#4978)
* 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>
2026-02-09 11:59:28 +08:00
Soulter
ce65491d55 chore: update pydantic dependency version (#4980) 2026-02-09 11:59:05 +08:00
Soulter
b67adcf481 ci: change ghcr namespace 2026-02-09 11:51:56 +08:00
Soulter
1707d55c02 fix: prepare OpenSSL via vcpkg for Windows ARM64 2026-02-09 11:04:31 +08:00
LIghtJUNction
48c2d98dde 删除 bun.lock,让行数看起来没那么夸张 2026-02-09 00:22:46 +08:00
Dt8333
7dd95d8a59 chore: auto ann fix by ruff (#4903)
* 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>
2026-02-09 00:22:24 +08:00
LIghtJUNction
af09b5cb16 Update astrbot/dashboard/server.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-09 00:21:37 +08:00
Soulter
e1b71540c7 chore: bump version to 4.14.8 and bump faiss-cpu version up to date 2026-02-09 00:19:12 +08:00
Soulter
85e1764857 feat: refactor release workflow and add special update handling for electron app (#4969) 2026-02-08 23:56:30 +08:00
Soulter
0553f84d6c chore: bump version to 4.14.7 2026-02-08 23:20:34 +08:00
Soulter
3fd89808ee chore: update Python version requirements to 3.12 (#4963) 2026-02-08 23:13:51 +08:00
Soulter
96753821b7 feat: enhance package.json with resource filters and compression settings 2026-02-08 22:58:58 +08:00
鸦羽
eca3ede7b0 fix: dedupe preset messages (#4961) 2026-02-08 22:18:13 +08:00
エイカク
a7e580407c feat: supports electron app (#4952)
* 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>
2026-02-08 21:49:54 +08:00
Soulter
8bd1565696 fix: correct height attribute to max-height for dialog component 2026-02-08 21:13:38 +08:00
Soulter
03e0949067 feat: add welcome feature with localized content and onboarding steps 2026-02-08 21:11:34 +08:00
DD斩首
dbe8e33c4b feat(telegram): 添加媒体组(相册)支持 / add media group (album) support (#4893)
* 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)**:明确指出缺少结束标志或总数信息
  https://github.com/tdlib/telegram-bot-api/issues/643

- **Telegram Bot API 服务器 issue**:讨论媒体组处理的不便性,推荐使用超时机制
  https://github.com/tdlib/telegram-bot-api/issues/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 社区**:确认媒体组消息单独到达,需手动处理
  https://github.com/python-telegram-bot/python-telegram-bot/discussions/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>
2026-02-08 13:22:45 +08:00
Gao Jinzhe
952023db30 feat: 允许 LLM 预览工具返回的图片并自主决定是否发送 (#4895)
* 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>
2026-02-08 13:16:16 +08:00
Helian Nuits
4e0b5063c6 feat(ComponentPanel): implement permission management for dashboard (#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>
2026-02-08 12:27:32 +08:00
搁浅
30d1d55e3c feat: add provider-souce-level proxy (#4949)
* 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>
2026-02-08 12:22:01 +08:00
Soulter
1e9026d44c chore: bump version to 4.14.6 2026-02-08 10:43:25 +08:00
letr
e48950d260 fix: localize provider source config UI (#4933)
* 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>
2026-02-08 10:40:26 +08:00
LIghtJUNction
31f46045d7 修正/修正一个错误 2026-02-07 20:17:44 +08:00
LIghtJUNction
d6455d774b 修正/一个导入问题 2026-02-07 20:02:44 +08:00
LIghtJUNction
3e928b9659 修正/CI工作流反馈的一些问题 2026-02-07 19:54:54 +08:00
圣达生物多
ddddd8a2ef Merge branch 'AstrBotDevs:master' into Sjshi763/issue4409 2026-02-07 14:11:16 +08:00
Soulter
5e5207da95 perf: optimize webchat and wecom ai queue lifecycle (#4941)
* perf: optimize webchat and wecom ai queue lifecycle

* perf: enhance webchat back queue management with conversation ID support
2026-02-07 14:03:33 +08:00
Soulter
def8b730b7 fix: correct spelling of 'temporary' in SharedPreferences class 2026-02-07 14:01:08 +08:00
Soulter
22a109c2ae feat: implement feishu / lark media file handling utilities for file, 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
2026-02-07 12:40:05 +08:00
Soulter
6416707e35 chore: bump version to 4.14.5 (#4930) 2026-02-07 00:55:16 +08:00
Soulter
4658998b85 fix: messages[x] assistant content must contain at least one part (#4928)
* fix: messages[x] assistant content must contain at least one part

fixes: #4876

* ruff format
2026-02-07 00:33:07 +08:00
can
d233fb8b1e feat: add bocha web search tool (#4902)
* add bocha web search tool

* Revert "add bocha web search tool"

This reverts commit 1b36d75a17.

* 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>
2026-02-06 21:43:42 +08:00
LIghtJUNction
df1299b192 移除自定义的一个协议 2026-02-06 12:38:55 +08:00
LIghtJUNction
15ee17724d Merge branch 'feat/optional-backend' of https://github.com/AstrBotDevs/AstrBot into feat/optional-backend 2026-02-06 12:37:58 +08:00
LIghtJUNction
437c186a66 类型标注 2026-02-06 12:37:41 +08:00
LIghtJUNction
3610a42ebf Merge branch 'master' into feat/optional-backend 2026-02-06 04:22:49 +08:00
LIghtJUNction
bf1bde79ec Update astrbot/core/utils/io.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-06 04:22:03 +08:00
LIghtJUNction
f309638192 Update astrbot/dashboard/server.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-06 04:21:40 +08:00
LIghtJUNction
6439e4e152 Update astrbot/cli/commands/cmd_run.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-06 04:21:02 +08:00
LIghtJUNction
4b1395b2c9 Update astrbot/dashboard/routes/route.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-06 04:19:41 +08:00
LIghtJUNction
1859206007 feat: 支持前后端分离部署与动态后端地址配置
后端:
- 支持通过 DASHBOARD_ENABLE 环境变量分离 WebUI 服务
- 修复 CORS 跨域预检请求(OPTIONS) 鉴权问题
- 优化 IPv6 地址过滤逻辑
- CLI 新增 --backend-only 模式支持

前端:
- 新增 API 地址动态配置与预设管理功能 (登录页/设置页)
- 修复 WebSocket/SSE 连接地址适配非同源环境
- 修复 TypeScript 配置报错
- 完善新增功能的国际化支持
2026-02-06 04:06:52 +08:00
LIghtJUNction
3b93429353 新增cors配置项 2026-02-06 04:01:30 +08:00
LIghtJUNction
d68ccfcc96 1.前端的后端配置页面新增新增按钮,允许新增后端,自由切换后端。2.一些必要的改进,比如astrbot init初始化时候询问是否下载前端,可选择不下载,使用--backend-only选项时候,不再提示要下载前端 2026-02-06 03:47:53 +08:00
LIghtJUNction
68b8a1a01c 将enable变量含义释为:是否启用集成前端,如果为False,保留后端能力,而不是后端也关闭了 2026-02-06 03:13:46 +08:00
LIghtJUNction
75ee46715a 支持ipv6并完善astrbot run子命令
* 默认host修改为::,同时新增两个环境变量DASHBOARD_HOST,DASHBOARD_ENABLE,和DASHBOARD_PORT对齐

* feat: systemd support (#4880)

* fix: pyright lint (#4874)

* feat: 将 MessageSession 的 platform_id 改为 init=False,实例化时无需传入

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* refactor: 将 isinstance 检查改为元组、将默认模型值设为空字符串、将类型注解改为 Any 并导入

* refactor: 为 _serialize_job 增加返回类型注解 dict

* fix: 使用 cast 获取百度 AIP 的 msg 并对 psutil_addr 引入 type: ignore

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* refactor: 引入 _AddrWithPort 协议并替换 conn.laddr 的 cast

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* fix: 在构建 AstrBotMessage 时对 ctx.channel 可能为 None 进行兜底处理

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

---------

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* fix: TypeError when MCP schema type is a list (#4867)

* Fix TypeError when MCP schema type is a list

Fixes crash in Gemini native tools with VRChat MCP.

* Refactor: avoid modifying schema in place per feedback

* Fix formatting and cleanup comments

* docs: update watashiwakoseinodesukara

Removed duplicate text and added a new image.

* 修复/跨平台一致性

* 琐事/类型标注和一些简单错误修正

* 修复/检查端口时候包含ipv6

* 修复/enable变量的赋值逻辑

---------

Co-authored-by: Dt8333 <25431943+Dt8333@users.noreply.github.com>
Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>
Co-authored-by: boushi1111 <95118141+boushi1111@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-02-06 02:46:16 +08:00
LIghtJUNction
a8cad50f27 新功能/可选的分离前后端 2026-02-06 02:38:58 +08:00
Soulter
fc2a67188f docs: update watashiwakoseinodesukara
Removed duplicate text and added a new image.
2026-02-05 23:08:14 +08:00
boushi1111
d69592aaa8 fix: TypeError when MCP schema type is a list (#4867)
* Fix TypeError when MCP schema type is a list

Fixes crash in Gemini native tools with VRChat MCP.

* Refactor: avoid modifying schema in place per feedback

* Fix formatting and cleanup comments
2026-02-05 22:51:29 +08:00
Dt8333
f3397f6f08 fix: pyright lint (#4874)
* feat: 将 MessageSession 的 platform_id 改为 init=False,实例化时无需传入

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* refactor: 将 isinstance 检查改为元组、将默认模型值设为空字符串、将类型注解改为 Any 并导入

* refactor: 为 _serialize_job 增加返回类型注解 dict

* fix: 使用 cast 获取百度 AIP 的 msg 并对 psutil_addr 引入 type: ignore

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* refactor: 引入 _AddrWithPort 协议并替换 conn.laddr 的 cast

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

* fix: 在构建 AstrBotMessage 时对 ctx.channel 可能为 None 进行兜底处理

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>

---------

Co-authored-by: aider (openai/gpt-5.2) <aider@aider.chat>
2026-02-05 21:54:12 +08:00
LIghtJUNction
be92e4f395 feat: systemd support (#4880) 2026-02-05 21:52:21 +08:00
圣达生物多
fbc7b2b06e Merge branch 'AstrBotDevs:master' into Sjshi763/issue4409 2026-02-05 13:18:02 +08:00
Soulter
912e40e7f0 chore: delete unused file 2026-02-05 10:40:53 +08:00
Xican
2876c43387 fix: 修复特定提供商导致的定时任务执行失败的问题 (#4872)
* fix: 修复特定提供商导致的定时任务执行失败的问题

* ruff format

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-02-05 10:14:31 +08:00
Soulter
464882f206 chore: bump version to 4.14.4 2026-02-04 23:21:08 +08:00
Soulter
6736fb85c2 fix: conversation token usage calculate wrongly and fix tool call infinitely (#4869) 2026-02-04 23:18:32 +08:00
Soulter
1f75255950 chore: bump version to 4.14.3 2026-02-04 20:31:19 +08:00
Soulter
a954e75547 fix: add apply_reset parameter to build_main_agent and handle coroutine reset in InternalAgentSubStage 2026-02-04 20:25:31 +08:00
advent259141
d2b9997620 chore: bump version to 4.14.2 2026-02-04 17:42:41 +08:00
圣达生物多
75e2f997e6 Merge branch 'AstrBotDevs:master' into Sjshi763/issue4409 2026-02-04 15:41:13 +08:00
Gao Jinzhe
36432c4361 fix: 修复插件热重载时平台适配器未清理导致注册冲突的问题 (#4859) 2026-02-04 15:06:03 +08:00
圣达生物多
36f0d1f0f9 feat: add debug hint to console page and localization files (#4852) 2026-02-04 15:02:15 +08:00
Anima-IGCenter
f65b268bb2 chore: create robots.txt (#4847) 2026-02-04 15:00:08 +08:00
Raven95676
fe06dfcca3 fix: update ruff version to 0.15.0 and add ASYNC240 to ignore list 2026-02-04 11:45:59 +08:00
Soulter
bc9043bc3f fix: update ruff exclude list to include tests directory 2026-02-04 10:08:48 +08:00
Soulter
430694aae9 chore: update readme 2026-02-04 10:05:35 +08:00
圣达生物多
edb0166a13 Merge branch 'AstrBotDevs:master' into Sjshi763/issue4409 2026-02-04 01:33:25 +08:00
Soulter
c643e3c093 chore: ruff format 2026-02-03 23:40:23 +08:00
Soulter
ff46eef3b2 chore: bump version to 4.14.1 2026-02-03 23:35:21 +08:00
Soulter
a0c364aa81 fix: active reply function does not work caused by event.request_llm() outdated 2026-02-03 23:34:42 +08:00
Anima-IGCenter
0e0f923a49 chore(seo): prevent indexing with noindex, nofollow (#4844) 2026-02-03 23:19:25 +08:00
Soulter
f2d637b935 fix: downgrade monaco-editor to version 0.52.2 2026-02-03 22:12:29 +08:00
Soulter
96e61a4a92 chore: bump version to 4.14.0 2026-02-03 22:08:29 +08:00
香草味的纳西妲喵
e42c1b6da8 fix: add error handling to avoid ghost plugins (#4836)
* fix: add error handling to avoid ghost plugins

Add null checks to filter out incomplete plugin metadata objects that would appear as ghost plugins in the API response.

This fix ensures that plugins with all null key fields (name, author, desc, version, display_name) are not included in the plugin list response, preventing ghost plugins from appearing in the UI.

Issue: #4833

* fix: improve ghost plugin detection logic for better accuracy

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-02-03 20:40:47 +08:00
Soulter
387bba093e fix: missing 2 required positional arguments: 'filter1' and 'filter2' (#4840)
fixes: #4777
2026-02-03 20:37:18 +08:00
Soulter
123cf9cb11 docs: revise README.md for clarity and feature updates (#4839)
Updated project description and added details about deployment and features.
2026-02-03 20:24:10 +08:00
Soulter
93277ffac9 fix: improve skills bundle extraction process to prevent overwriting existing files 2026-02-03 16:54:53 +08:00
Soulter
c091053ea8 fix: skills bundle unzip failed in sandbox 2026-02-03 16:34:07 +08:00
Soulter
8b9f2f1e70 feat: enhance user experience with runtime hints and improved UI elements in skills management 2026-02-03 16:28:17 +08:00
Soulter
25ca7bd71e fix: add missing newline for code readability in _apply_local_env_tools function 2026-02-03 16:09:17 +08:00
Soulter
093b37e04b feat: add computer use runtime config and handling for skills execution (#4831)
* feat: add computer use runtime configuration and handling for skills execution

* fix: improve user notification for disabled Computer Use feature in skills execution
2026-02-03 16:08:15 +08:00
Soulter
a12e27f9ab feat: implement theme customization with primary and secondary color options 2026-02-03 14:41:48 +08:00
Soulter
ae6e0db053 perf: webui
Co-authored-by: IGCrystal <IGCrystal@wenturc.com>
2026-02-03 14:40:45 +08:00
SJ
cd6bef4d78 fix: MCP tools being filtered out when a specific plugin set is configured in the WebUI (#4825)
* fix: preserve MCP tools in _plugin_tool_fix filter

Tools without handler_module_path (such as MCP tools and built-in tools)
were being incorrectly skipped during plugin-based tool filtering.

This fix ensures that tools without plugin association are preserved,
as they should not be affected by plugin-level filtering logic.

* fix: retain MCP tools in _plugin_tool_fix function

---------

Co-authored-by: idiotsj <idiotsj@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-02-03 10:53:20 +08:00
Copilot
de1304dc6a feat: add edit button to persona selector dialog (#4826)
* Initial plan

* feat: add edit persona functionality in chatui selector dialog

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

* fix: address code review feedback - improve null checks and i18n consistency

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>
2026-02-03 10:32:20 +08:00
Soulter
f835f63542 feat: add trace settings management and UI for enabling/disabling trace logging (#4822)
* feat: add trace settings management and UI for enabling/disabling trace logging

* feat: enhance trace feature with internationalization support for hints and status messages

* fix: improve tool info extraction in run_agent function
2026-02-03 10:24:41 +08:00
Soulter
5deb045e47 fix: merge chatui pop-up prompt into chatui default persona and improve chatui persona handle (#4824)
* fix: merge chatui pop-up prompt into chatui default persona and improve chatui persona handle

* fix: update webchat persona handling to avoid default assignment for None
2026-02-03 01:29:21 +08:00
Sjshi763
c7eb1b85b9 重复检查 2026-02-02 15:12:35 +08:00
Sjshi763
351ce77147 新格式导入 2026-02-02 14:53:31 +08:00
Sjshi763
d3e71046ae 修改导出格式 2026-02-02 14:38:59 +08:00
Sjshi763
986549b844 在导出时说明不包含tools Skills 2026-02-02 14:24:18 +08:00
Soulter
42e84afd89 perf: improve cron job page 2026-02-02 14:13:17 +08:00
Sjshi763
3d3926b98e 保证相同的i18n 2026-02-02 14:12:52 +08:00
Soulter
a7ed6b8c76 fix: reasoning block style 2026-02-02 14:11:17 +08:00
Sjshi763
fbe0d05dfc 写错地方了,更正i18n 2026-02-02 14:09:53 +08:00
Sjshi763
d1e7105bd7 [Feature] 人格设定支持导出/导入。
Fixes #4409

找回需要的i18n
2026-02-02 14:05:31 +08:00
圣达生物多
e79df4a565 Merge branch 'AstrBotDevs:master' into Sjshi763/issue4409 2026-02-02 13:44:39 +08:00
Soulter
ee43b98ce6 fix: add missing comma in truncate_and_compress hint in config-metadata.json 2026-02-01 23:34:21 +08:00
Soulter
681b4747a6 feat: add proactive capability configuration with cron tools support 2026-02-01 23:33:45 +08:00
Soulter
a6da4ebe5e feat: add styles for embedded images and audio in MessagePartsRenderer 2026-02-01 23:29:08 +08:00
Soulter
e35a604b30 Merge pull request #4697 from advent259141/Astrbot_skill
feat: implemented proactive agents and subagents orchestrator
2026-02-01 22:57:47 +08:00
Soulter
45c9db258d feat: add support for resolving file paths from sandbox and downloading files if necessary 2026-02-01 22:30:22 +08:00
Soulter
382aaaf053 feat: i18n 2026-02-01 22:04:44 +08:00
Soulter
f66edc8d45 feat: implement CronJob system with support for one-time tasks and enhanced UI for task management 2026-02-01 22:04:30 +08:00
Soulter
3f8d8b5033 feat: integrate subagent orchestrator with configuration options for tool management 2026-02-01 20:43:08 +08:00
Soulter
bf587765de feat: enhance FileDownloadTool to confirm file removal and successful download 2026-02-01 18:13:23 +08:00
Soulter
313a6d8a24 fix: improve error handling for temporary file removal in FileDownloadTool 2026-02-01 18:12:40 +08:00
Soulter
2213fb1ebf feat: add proactive messaging support in CronJobPage and enhance file download tool with user notification option 2026-02-01 18:12:11 +08:00
Soulter
9bf63354be feat: enhance UI for SubAgent and CronJob management with beta indicators 2026-02-01 17:58:30 +08:00
Soulter
cd6cb1d60c chore: remove reminder 2026-02-01 17:50:29 +08:00
Soulter
193676012f feat: implement history persistence for agent interactions and enhance cron job permission handling 2026-02-01 17:42:08 +08:00
Soulter
bddf7b8623 feat: add proactive messaging support and enhance message handling in SendMessageToUserTool 2026-02-01 16:49:10 +08:00
Soulter
4c8c87d3fd feat: enhance cron job management and update UI terminology 2026-02-01 15:49:14 +08:00
Soulter
83288ca43e ruff format 2026-02-01 14:33:17 +08:00
Soulter
7f58a83833 Refactor cron job handling and enhance proactive agent capabilities
- Updated FunctionToolExecutor to improve background task handling and integrate new system prompts for proactive agents.
- Enhanced MainAgentBuildConfig with additional configuration options for tool management and context handling.
- Introduced new system prompts for proactive agents triggered by cron jobs and background tasks to improve user interaction.
- Refactored cron job management to utilize ProviderRequest for better context management and tool integration.
- Renamed cron job tools for clarity, changing "create_cron_job" to "create_future_task" and similar adjustments for consistency.
- Improved error handling and logging for cron job execution and agent responses.
- Added support for image captioning and persona management in agent requests.
2026-02-01 14:32:30 +08:00
Soulter
19651d24bb fix(skills): remove sandbox runtime handling from skill upload process (#4798) 2026-02-01 13:13:27 +08:00
Soulter
dba08edd0d style: enhance dialog titles with padding and text styles in MCP and Skills sections 2026-02-01 11:09:32 +08:00
letr
dc06bc943a fix(mcp): cannot rename MCP Server (#4766)
* fix(mcp): support renaming when editing MCP servers

When editing the MCP server configuration, you can now change the server name. The frontend will save the original name in edit mode, and the backend will recognize the rename operation through the oldName field.

* fix(mcp): fixed an issue where renaming the MCP server did not check for name conflicts

When renaming an MCP server, add a check to see if the target name already exists. If the name exists and it is a rename operation, return an error message to avoid overwriting the configuration.
2026-02-01 11:01:49 +08:00
Soulter
b48e6fb1b3 Merge remote-tracking branch 'origin/master' into Astrbot_skill 2026-02-01 00:46:05 +08:00
Soulter
0c5308a132 refactor: extract main agent 2026-02-01 00:43:41 +08:00
Soulter
339d98be35 chore: bump version to 4.13.2 (#4782) 2026-02-01 00:39:37 +08:00
Soulter
e8be624794 fix(context): append 'main' to module_part for handler module path (#4776) 2026-01-31 22:26:50 +08:00
Soulter
b2c6471ab0 fix: skill like tool (#4775) 2026-01-31 22:11:42 +08:00
Soulter
4ea865f017 feat: add cron job management tools and dashboard integration
- Implemented proactive cron job tools in InternalAgentSubStage for scheduling tasks.
- Created SendMessageToUserTool for sending messages to users based on cron job triggers.
- Added CreateActiveCronTool, DeleteCronJobTool, and ListCronJobsTool for cron job management.
- Introduced CronRoute for handling cron job API requests in the dashboard.
- Developed CronJobPage.vue for managing cron jobs in the dashboard UI.
- Updated SubAgentPage.vue to include persona selection for subagents.
2026-01-31 17:08:37 +08:00
sanyekana
106f352017 fix: Fixed a bug where the front end still displayed a success messag… (#4768)
* fix: Fixed a bug where the front end still displayed a success message when Skills upload failed.

* refactor(dashboard): unify API response handling in SkillsSection
2026-01-31 11:31:02 +08:00
Soulter
5b7805e8d7 feat: trace and log file config (#4747)
* feat: trace

* fix(log): increase log cache size from 200 to 500

* feat(logging): add file and trace logging configuration options
2026-01-31 00:05:54 +08:00
圣达生物多
ebcc15bb72 Merge branch 'AstrBotDevs:master' into Sjshi763/issue4409 2026-01-30 17:09:39 +08:00
Soulter
831c2150d6 Merge remote-tracking branch 'origin/master' into Astrbot_skill 2026-01-29 23:46:21 +08:00
Soulter
a500f2edc8 chore: bump version to 4.13.1 2026-01-29 23:31:49 +08:00
Soulter
d27099f2da fix(skills): update SANDBOX_SKILLS_ROOT path to use relative directory 2026-01-29 23:25:56 +08:00
Helian Nuits
2aa0986295 fix(db): using lambda expression to ensure updated_at field (#4730)
* fix(db): 使用 lambda 表达式确保 updated_at 字段正确更新

updated_at 字段原先在 sa_column_kwargs["onupdate"] 中直接使用了 datetime.now(),导致时间戳仅在模块导入时被计算一次,之后不再变化,结果所有记录的更新时间都被设成了程序启动时间。

本次修改将时间戳生成逻辑封装进 lambda 表达式,使 SQLAlchemy 在每次更新记录时才惰性求值,从而保证时间戳实时更新。

* refactor(db): 根据建议引入 TimestampMixin 统一时间戳定义,提取 `created_at`/`updated_at` 至 [TimestampMixin]
2026-01-29 19:07:21 +08:00
Soulter
34c6ceb67c fix(docs): update feature description to include 'Skills' in README files 2026-01-29 17:22:48 +08:00
Soulter
906877cbe6 feat(i18n): add localized message for tool usage in chat 2026-01-29 16:29:44 +08:00
Soulter
609180022e feat(chat): refactor message rendering and introduce ToolCallItem component 2026-01-29 16:07:57 +08:00
Soulter
49c087a141 docs: replace demo banner in readme
Updated the image in the README file.
2026-01-29 12:17:11 +08:00
Soulter
70f12cd686 docs(readme): update language links and enhance feature descriptions 2026-01-29 12:09:38 +08:00
advent259141
738e69a8af add 3-mode selector and main tool mounting policy 2026-01-29 11:27:50 +08:00
Gao Jinzhe
60492d46ee Merge branch 'master' into Astrbot_skill 2026-01-29 10:57:30 +08:00
Soulter
ea82e00359 fix(changelog): clarify support for Anthropic Skills with usage reference 2026-01-29 00:54:39 +08:00
Soulter
928c557a25 fix: update markstream-vue and stream-monaco dependencies 2026-01-29 00:48:51 +08:00
Soulter
0500ee8e2b chore: bump version to 4.13.0 2026-01-29 00:21:58 +08:00
Sjshi763
03bdb51c43 移动到 persona 的 i18n JSON 2026-01-28 23:42:32 +08:00
Sjshi763
0e32d62950 移除导入和导出按钮的本地化文本(上一次修改的 2026-01-28 23:35:45 +08:00
Sjshi763
60dfaf02b3 修复bug 405 2026-01-28 23:32:47 +08:00
Sjshi763
92cf0bc9ef 再次完成 2026-01-28 23:10:56 +08:00
vmoranv
f92f0a3e5d feat(core): supports anthropic-skills-like tool call mode (#4681)
* feat(core): change llmtool to claude skills like func call

* feat: refactor tool execution logic in ToolLoopAgentRunner for improved clarity and efficiency

* feat(core): 添加工具调用模式配置选项

新增 tool_schema_mode 配置项,支持两种工具调用模式:
- skills_like:先发送工具名称和描述,再查询参数(两阶段)
- full:一次性发送完整工具模式

更新了默认配置、配置元数据定义以及代理子阶段处理逻辑,
添加了完整的工具调用提示语句,并在仪表板中提供了国际化支持。

* feat: 优化工具集获取逻辑,添加轻量和参数工具集返回方法

* refactor(runner): 重构工具模式处理逻辑到ToolLoopAgentRunner

- 将工具集激活逻辑提取到新的_build_active_tool_set方法中
- 实现工具模式配置功能,支持full和light模式的动态切换
- 移除InternalAgentSubStage中的工具模式应用逻辑,统一在runner中处理
- 添加_tool_schema_full_set和_tool_schema_param_set实例变量来管理工具集状态
- 修改工具查询逻辑以使用新的工具集管理方式

* fix: update default tool_schema_mode to 'full' in InternalAgentSubStage

* refactor: rename TOOL_CALL_PROMPT_FULL to TOOL_CALL_PROMPT_SKILLS_LIKE_MODE and update prompt logic

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-01-28 22:49:34 +08:00
Sjshi763
1f75682dea [Feature] 人格设定支持导出/导入。
Fixes #4409
2026-01-28 22:29:45 +08:00
圣达生物多
3ec909ca57 Merge pull request #1 from Sjshi763/fix-persona-conflict-v2
update
2026-01-28 22:16:22 +08:00
Sjshi763
fd95665fe3 update 2026-01-28 22:13:38 +08:00
Sjshi763
125d10a4e1 [Feature] 人格设定支持导出/导入。
Fixes #4409
2026-01-28 22:04:03 +08:00
Soulter
c1b764da04 fix: webui github proxy selector and bugs after uninstalling plugins (#4724)
fixes: #4709
2026-01-28 21:04:13 +08:00
Soulter
22bd8d6824 feat: support anthropic skills (#4715)
* 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
2026-01-28 01:48:57 +08:00
xunxiing
a4fc92e803 feat: add file upload to plugin config (#4539)
Co-authored-by: Soulter <905617992@qq.com>
2026-01-27 14:56:19 +08:00
advent259141
053c4e989b 优化tool选择的下拉框:根据插件分组 2026-01-27 00:21:57 +08:00
advent259141
1bd8eae25a 按照comment进行一些小改动 2026-01-26 23:30:29 +08:00
Soulter
a41391f9f2 feat: resolve provider api keys from env (#4696) 2026-01-26 22:37:30 +08:00
advent259141
b3a1f4ca7d 再次修复格式 2026-01-26 22:36:25 +08:00
advent259141
c3e4a52e5f 修复格式 2026-01-26 22:31:18 +08:00
advent259141
3cf0880f98 修复bug,优化前端页面 2026-01-26 22:14:56 +08:00
Soulter
b04dad1fd2 docs: add AGENTS.md 2026-01-26 21:21:26 +08:00
advent259141
6d47663842 修复了一些已知问题 2026-01-26 17:22:20 +08:00
xunxiing
3765dd46f7 fix: gemini toolcall repetition call (#4686)
* 修复gemini toolcall 的名称导致的循环调用

* Apply suggestions from code review

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

* Refactor function response creation for tool role

Refactor function response handling for tool role to ensure proper ID injection.

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-01-26 17:14:58 +08:00
advent259141
6b39717695 增加subagent编排功能 2026-01-26 14:57:20 +08:00
Soulter
17d642efc9 fix: update configuration metadata hints for segmented reply settings 2026-01-25 14:28:07 +08:00
時壹
4839cc6119 feat: add configurable Dashboard API access log toggle (#4661)
* feat: add configurable Dashboard API access log toggle

* chore: remove Dashboard API access log configuration
2026-01-24 16:31:23 +08:00
搁浅
127e8c31c2 feat: add confirmation dialog for update all plugins button to prevent accidental clicks #4300 (#4658) 2026-01-24 16:08:47 +08:00
Soulter
1cf673154c chore: bump version to 4.12.4 2026-01-24 14:55:32 +08:00
Soulter
f7c228ede2 fix: markdown keyerror or unbound error in aiocqhttp adapter (#4656)
* fix: markdown keyerror or unbound error in aiocqhttp adapter

* fix: improve exception handling and logging in aiocqhttp adapter
2026-01-24 14:43:49 +08:00
Soulter
78617ec7ce fix: enhance provider selection error handling and logging (#4654) 2026-01-24 14:25:41 +08:00
Soulter
e5048bddeb chore: remove deprecated tool commands
closes: #4599
2026-01-23 20:00:59 +08:00
Soulter
eebe31f69d fix: update web_search_tavily handling for webchat platform (#4633)
* fix: update web_search_tavily handling for webchat platform

* chore: style consistent
2026-01-23 19:52:31 +08:00
Copilot
90b57eb5cb fix: provider selector button hidden by long model names (#4631)
* Initial plan

* Fix long model name overflow in ProviderSelector

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>
2026-01-23 19:42:12 +08:00
Soulter
2b2edf4852 fix: genie tts config 2026-01-23 19:00:57 +08:00
Soulter
a920e45f96 feat: AstrBot Live Chat Mode on ChatUI (#4534)
* feat: astr live

* chore: remove

* feat: metrics

* feat: enhance audio processing and metrics display in live mode

* feat: genie tts

* feat: enhance live mode audio processing and text handling

* feat: add metrics

* feat: eyes

* feat: nervous

* chore: update readme

Added '自动压缩对话' feature and updated features list.

* feat: skip saving head system messages in history (#4538)

* feat: skip saving the first system message in history

* fix: rename variable for clarity in system message handling

* fix: update logic to skip all system messages until the first non-system message

* fix: clarify logic for skipping initial system messages in conversation

* chore: bump version to 4.12.2

* docs: update 4.12.2 changelog

* refactor: update event types for LLM tool usage and response

* chore: bump version to 4.12.3

* fix: ensure embedding dimensions are returned as integers in providers (#4547)

* fix: ensure embedding dimensions are returned as integers in providers

* chore: ruff format

* perf: T2I template editor preview (#4574)

* feat: add file drag upload feature for ChatUI (#4583)

* feat(chat): add drag-drop upload and fix batch file upload

* style(chat): adjust drop overlay to only cover input container

* fix: streaming response for DingTalk (#4590)

closes: #4384

* #4384 钉钉消息回复卡片模板

* chore: ruff format

* chore: ruff format

---------

Co-authored-by: ManJiang <man.jiang@jg-robust.com>
Co-authored-by: Soulter <905617992@qq.com>

* feat: implement persona folder for advanced persona management (#4443)

* feat(db): add persona folder management for hierarchical organization

Implement hierarchical folder structure for organizing personas:
- Add PersonaFolder model with recursive parent-child relationships
- Add folder_id and sort_order fields to Persona model
- Implement CRUD operations for persona folders in database layer
- Add migration support for existing databases
- Extend PersonaManager with folder management methods
- Add dashboard API routes for folder operations

* feat(persona): add batch sort order update endpoint for personas and folders

Add new API endpoint POST /persona/reorder to batch update sort_order
for both personas and folders. This enables drag-and-drop reordering
in the dashboard UI.

Changes:
- Add abstract batch_update_sort_order method to BaseDatabase
- Implement batch_update_sort_order in SQLiteDatabase
- Add batch_update_sort_order to PersonaManager with cache refresh
- Add reorder_items route handler with input validation

* feat(persona): add folder_id and sort_order params to persona creation

Extend persona creation flow to support folder placement and ordering:
- Add folder_id and sort_order parameters to insert_persona in db layer
- Update PersonaManager.create_persona to accept and pass folder params
- Add get_folder_detail API endpoint for retrieving folder information
- Include folder_id and sort_order in persona creation response
- Add session flush/refresh to return complete persona object

* feat(dashboard): implement persona folder management UI

- Add folder management system with tree view and breadcrumbs
- Implement create, rename, delete, and move operations for folders
- Add drag-and-drop support for organizing personas and folders
- Create new PersonaManager component and Pinia store for state management
- Refactor PersonaPage to support hierarchical structure
- Update locale files with folder-related translations
- Handle empty parent_id correctly in backend route

* feat(dashboard): centralize folder expansion state in persona store

Move folder expansion logic from local component state to global Pinia
store to persist expansion state.
- Add `expandedFolderIds` state and toggle actions to `personaStore`
- Update `FolderTreeNode` to use store state instead of local data
- Automatically navigate to target folder after moving a persona

* feat(dashboard): add reusable folder management component library

Extract folder management UI into reusable base components and create
persona-specific wrapper components that integrate with personaStore.

- Add base folder components (tree, breadcrumb, card, dialogs) with
  customizable labels for i18n support
- Create useFolderManager composable for folder state management
- Implement drag-and-drop support for moving personas between folders
- Add persona-specific wrapper components connecting to personaStore
- Reorganize PersonaManager into views/persona directory structure
- Include comprehensive README documentation for component usage

* refactor(dashboard): remove legacy persona folder management components

Remove deprecated persona folder management Vue components that have been
superseded by the new reusable folder management component library.

Deleted components:
- CreateFolderDialog.vue
- FolderBreadcrumb.vue
- FolderCard.vue
- FolderTree.vue
- FolderTreeNode.vue
- MoveTargetNode.vue
- MoveToFolderDialog.vue
- PersonaCard.vue
- PersonaManager.vue

These components are replaced by the centralized folder management
implementation introduced in commit 3fbb3db2.

* fix(dashboard): add delayed skeleton loading to prevent UI flicker

Implement a 150ms delay before showing the skeleton loader in
PersonaManager to prevent visual flicker during fast loading operations.

- Add showSkeleton state with timer-based delay mechanism
- Use v-fade-transition for smooth skeleton visibility transitions
- Clean up timer on component unmount to prevent memory leaks
- Only display skeleton when loading exceeds threshold duration

* feat(dashboard): add generic folder item selector component for persona selection

Introduce BaseFolderItemSelector.vue as a reusable component for selecting
items within folder hierarchies. Refactor PersonaSelector to use this new
base component instead of its previous flat list implementation.

Changes:
- Add BaseFolderItemSelector with folder tree navigation and item selection
- Extend folder types with SelectableItem and FolderItemSelectorLabels
- Refactor PersonaSelector to leverage the new base component
- Add i18n translations for rootFolder and emptyFolder labels

* feat(persona): add tree-view display for persona list command

Add hierarchical folder tree output for the persona list command,
showing personas organized by folders with visual tree connectors.

- Add _build_tree_output method for recursive tree structure rendering
- Display folders with 📁 icon and personas with 👤 icon
- Show root-level personas separately from folder contents
- Include total persona count in output

* refactor(persona): simplify tree-view output with shorter indentation lines

Replace complex tree connector logic with simpler depth-based indentation
using "│ " prefix. Remove unnecessary parameters (prefix, is_last) and
computed variables (has_content, total_items, item_idx) in favor of a
cleaner depth-based approach.

* feat(dashboard): add duplicate persona ID validation in create form

Add frontend validation to prevent creating personas with duplicate IDs.
Load existing persona IDs when opening the create form and validate
against them in real-time.

- Add existingPersonaIds array and loadExistingPersonaIds method
- Add validation rule to check for duplicate persona IDs
- Add i18n messages for duplicate ID error (en-US and zh-CN)
- Fix minLength validation to require at least 1 character

* i18n(persona): add createButton translation key for folder dialog

Move create button label to folder-specific translation path
instead of using generic buttons.create key.

* feat(persona): show target folder name in persona creation dialog

Add visual feedback showing which folder a new persona will be created in.

- Add info alert in PersonaForm displaying the target folder name
- Pass currentFolderName prop from PersonaManager and PersonaSelector
- Add recursive findFolderName helper to resolve folder ID to name
- Add i18n translations for createInFolder and rootFolder labels

* style:format code

* fix: remove 'persistent' attribute from dialog components

---------

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

* perf: live mode entry

* chore: remove japanese prompt

---------

Co-authored-by: Anima-IGCenter <cacheigcrystal2@gmail.com>
Co-authored-by: Clhikari <Clhikari@qq.com>
Co-authored-by: jiangman202506 <jiangman202506@163.com>
Co-authored-by: ManJiang <man.jiang@jg-robust.com>
Co-authored-by: Ruochen Pan <67079377+RC-CHN@users.noreply.github.com>
2026-01-22 16:24:40 +08:00
Ruochen Pan
8910ab3a47 feat: implement persona folder for advanced persona management (#4443)
* feat(db): add persona folder management for hierarchical organization

Implement hierarchical folder structure for organizing personas:
- Add PersonaFolder model with recursive parent-child relationships
- Add folder_id and sort_order fields to Persona model
- Implement CRUD operations for persona folders in database layer
- Add migration support for existing databases
- Extend PersonaManager with folder management methods
- Add dashboard API routes for folder operations

* feat(persona): add batch sort order update endpoint for personas and folders

Add new API endpoint POST /persona/reorder to batch update sort_order
for both personas and folders. This enables drag-and-drop reordering
in the dashboard UI.

Changes:
- Add abstract batch_update_sort_order method to BaseDatabase
- Implement batch_update_sort_order in SQLiteDatabase
- Add batch_update_sort_order to PersonaManager with cache refresh
- Add reorder_items route handler with input validation

* feat(persona): add folder_id and sort_order params to persona creation

Extend persona creation flow to support folder placement and ordering:
- Add folder_id and sort_order parameters to insert_persona in db layer
- Update PersonaManager.create_persona to accept and pass folder params
- Add get_folder_detail API endpoint for retrieving folder information
- Include folder_id and sort_order in persona creation response
- Add session flush/refresh to return complete persona object

* feat(dashboard): implement persona folder management UI

- Add folder management system with tree view and breadcrumbs
- Implement create, rename, delete, and move operations for folders
- Add drag-and-drop support for organizing personas and folders
- Create new PersonaManager component and Pinia store for state management
- Refactor PersonaPage to support hierarchical structure
- Update locale files with folder-related translations
- Handle empty parent_id correctly in backend route

* feat(dashboard): centralize folder expansion state in persona store

Move folder expansion logic from local component state to global Pinia
store to persist expansion state.
- Add `expandedFolderIds` state and toggle actions to `personaStore`
- Update `FolderTreeNode` to use store state instead of local data
- Automatically navigate to target folder after moving a persona

* feat(dashboard): add reusable folder management component library

Extract folder management UI into reusable base components and create
persona-specific wrapper components that integrate with personaStore.

- Add base folder components (tree, breadcrumb, card, dialogs) with
  customizable labels for i18n support
- Create useFolderManager composable for folder state management
- Implement drag-and-drop support for moving personas between folders
- Add persona-specific wrapper components connecting to personaStore
- Reorganize PersonaManager into views/persona directory structure
- Include comprehensive README documentation for component usage

* refactor(dashboard): remove legacy persona folder management components

Remove deprecated persona folder management Vue components that have been
superseded by the new reusable folder management component library.

Deleted components:
- CreateFolderDialog.vue
- FolderBreadcrumb.vue
- FolderCard.vue
- FolderTree.vue
- FolderTreeNode.vue
- MoveTargetNode.vue
- MoveToFolderDialog.vue
- PersonaCard.vue
- PersonaManager.vue

These components are replaced by the centralized folder management
implementation introduced in commit 3fbb3db2.

* fix(dashboard): add delayed skeleton loading to prevent UI flicker

Implement a 150ms delay before showing the skeleton loader in
PersonaManager to prevent visual flicker during fast loading operations.

- Add showSkeleton state with timer-based delay mechanism
- Use v-fade-transition for smooth skeleton visibility transitions
- Clean up timer on component unmount to prevent memory leaks
- Only display skeleton when loading exceeds threshold duration

* feat(dashboard): add generic folder item selector component for persona selection

Introduce BaseFolderItemSelector.vue as a reusable component for selecting
items within folder hierarchies. Refactor PersonaSelector to use this new
base component instead of its previous flat list implementation.

Changes:
- Add BaseFolderItemSelector with folder tree navigation and item selection
- Extend folder types with SelectableItem and FolderItemSelectorLabels
- Refactor PersonaSelector to leverage the new base component
- Add i18n translations for rootFolder and emptyFolder labels

* feat(persona): add tree-view display for persona list command

Add hierarchical folder tree output for the persona list command,
showing personas organized by folders with visual tree connectors.

- Add _build_tree_output method for recursive tree structure rendering
- Display folders with 📁 icon and personas with 👤 icon
- Show root-level personas separately from folder contents
- Include total persona count in output

* refactor(persona): simplify tree-view output with shorter indentation lines

Replace complex tree connector logic with simpler depth-based indentation
using "│ " prefix. Remove unnecessary parameters (prefix, is_last) and
computed variables (has_content, total_items, item_idx) in favor of a
cleaner depth-based approach.

* feat(dashboard): add duplicate persona ID validation in create form

Add frontend validation to prevent creating personas with duplicate IDs.
Load existing persona IDs when opening the create form and validate
against them in real-time.

- Add existingPersonaIds array and loadExistingPersonaIds method
- Add validation rule to check for duplicate persona IDs
- Add i18n messages for duplicate ID error (en-US and zh-CN)
- Fix minLength validation to require at least 1 character

* i18n(persona): add createButton translation key for folder dialog

Move create button label to folder-specific translation path
instead of using generic buttons.create key.

* feat(persona): show target folder name in persona creation dialog

Add visual feedback showing which folder a new persona will be created in.

- Add info alert in PersonaForm displaying the target folder name
- Pass currentFolderName prop from PersonaManager and PersonaSelector
- Add recursive findFolderName helper to resolve folder ID to name
- Add i18n translations for createInFolder and rootFolder labels

* style:format code

* fix: remove 'persistent' attribute from dialog components

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-01-21 13:05:33 +08:00
jiangman202506
c09bbfb8ac fix: streaming response for DingTalk (#4590)
closes: #4384

* #4384 钉钉消息回复卡片模板

* chore: ruff format

* chore: ruff format

---------

Co-authored-by: ManJiang <man.jiang@jg-robust.com>
Co-authored-by: Soulter <905617992@qq.com>
2026-01-21 12:48:45 +08:00
Clhikari
02909c62ab feat: add file drag upload feature for ChatUI (#4583)
* feat(chat): add drag-drop upload and fix batch file upload

* style(chat): adjust drop overlay to only cover input container
2026-01-21 12:37:18 +08:00
Anima-IGCenter
978d9cbb6a perf: T2I template editor preview (#4574) 2026-01-20 10:23:37 +08:00
Soulter
cb3825bb00 fix: ensure embedding dimensions are returned as integers in providers (#4547)
* fix: ensure embedding dimensions are returned as integers in providers

* chore: ruff format
2026-01-18 17:09:25 +08:00
圣达生物多
98e7a9c903 Merge branch 'AstrBotDevs:master' into Sjshi763/issue4409 2026-01-18 15:05:36 +08:00
Sjshi763
ec3d25c55b PersonaForm.vue - savePersona 方法添加了白名单字段过滤 2026-01-17 19:33:32 +08:00
Sjshi763
13461f925b fix:仅白名单字段可以作为文件名 2026-01-17 19:20:41 +08:00
Soulter
5f54becbe2 chore: bump version to 4.12.3 2026-01-17 19:11:05 +08:00
Soulter
317b6fa475 refactor: update event types for LLM tool usage and response 2026-01-17 19:09:49 +08:00
Soulter
8199c83072 docs: update 4.12.2 changelog 2026-01-17 18:12:08 +08:00
Soulter
776c9ebfdd chore: bump version to 4.12.2 2026-01-17 18:07:54 +08:00
Soulter
73fca5d1a2 fix: clarify logic for skipping initial system messages in conversation 2026-01-17 18:02:31 +08:00
Soulter
844773a735 feat: skip saving head system messages in history (#4538)
* feat: skip saving the first system message in history

* fix: rename variable for clarity in system message handling

* fix: update logic to skip all system messages until the first non-system message
2026-01-17 17:57:11 +08:00
Sjshi763
d2ed543425 删除未使用的i18n键值 2026-01-17 13:33:00 +08:00
Sjshi763
d1c0122691 改为直接导出文件 2026-01-17 13:22:27 +08:00
Sjshi763
2285695cb0 稍微进化 2026-01-17 13:15:17 +08:00
Sjshi763
59e5a6fd83 导入(dev 2026-01-17 13:03:12 +08:00
Sjshi763
2e90c259ea [Feature] 人格设定支持导出/导入。
Fixes #4409

- 导出的json
2026-01-17 12:35:23 +08:00
Soulter
1a7e8456ab chore: update readme
Added '自动压缩对话' feature and updated features list.
2026-01-16 17:57:49 +08:00
Soulter
f6a189f118 feat: add event hooks for tool usage and response handling (#4516)
* feat: add event hooks for tool usage and response handling

* fix: update decorator for LLM tool response handling
2026-01-16 16:51:35 +08:00
Soulter
82e2e0d02f feat: add web search references feature with sidebar and extraction logic (#4515)
* feat: add web search references feature with sidebar and extraction logic

* fix: reorder import statements for consistency

* chore: remove log
2026-01-16 16:49:48 +08:00
Soulter
8771317a1e perf: chatui default persona (#4502) 2026-01-16 16:46:39 +08:00
Soulter
ebae70c514 chore: bump version to 4.12.1 2026-01-15 22:20:52 +08:00
Soulter
dbdb4f5185 fix: unique session not working (#4490)
* fix: unique session not working

* fix: correct session initialization and update unified_msg_origin setter

* fix: update session ID assignment in WakingCheckStage
2026-01-15 22:16:21 +08:00
Soulter
af2b3b3bfc fix: update stream-monaco dependency to version 0.0.15 2026-01-15 19:53:58 +08:00
Soulter
6497d9a46f fix: update stream-markdown dependency to version 0.0.13 2026-01-15 19:52:23 +08:00
Soulter
8f4a62a2cb chore: bump version to 4.12.0 2026-01-15 19:47:53 +08:00
Soulter
acbe83a2e2 chore: bump version to 4.12.0 2026-01-15 19:47:25 +08:00
Gao Jinzhe
e0f3fb3c3d Merge pull request #4194 from Luna-channel/feat/session-management
feat: add batch operation functionality for session management
2026-01-15 19:38:24 +08:00
Soulter
fef789e4d3 feat: add Docker Compose configuration for AstrBot and Shipyard services 2026-01-15 18:53:24 +08:00
Soulter
680b900c76 feat: implement iPython tool and reasoning blocks with enhanced UI components 2026-01-15 18:15:42 +08:00
Soulter
f797f132cf perf: refine tool call related prompts 2026-01-15 17:22:50 +08:00
Soulter
941ab6db84 chore: add requirement 2026-01-15 16:19:26 +08:00
Soulter
5eea508296 feat: astrbot agent sandbox env(improved code interpreter) (#4449)
* stage

* fix: update tool call logging to include tool call IDs and enhance sandbox ship creation parameters

* feat: file upload

* fix

* update

* fix: remove 'boxlite' option from booter and handle error in PythonTool execution

* feat: implement singleton pattern for ShipyardSandboxClient and add FileUploadTool for file uploads

* feat: sandbox

* fix

* beta

* uv lock

* remove

* chore: makes world better

* feat: implement localStorage persistence for showReservedPlugins state

* docs: refine EULA

* fix

* feat: add availability check for sandbox in Shipyard and base booters

* feat: add shipyard session configuration options and update related tools

* feat: add file download functionality and update shipyard SDK version

* fix: sending OpenAI-style image_url causes Anthropic 400 invalid tag error (#4444)

* feat: chatui project (#4477)

* feat: chatui-project

* fix: remove console log from getProjects function

* fix: title saving logic and update project sessions on changes

* docs: standardize Context class documentation formatting (#4436)

* docs: standardize Context class documentation formatting

- Unified all method docstrings to standard format
- Fixed mixed language and formatting issues
- Added complete parameter and return descriptions
- Enhanced developer experience for plugin creators
- Fixes #4429

* docs: fix Context class documentation issues per review

- Restored Sphinx directives for versionadded notes
- Fixed MessageSesion typo to MessageSession throughout file
- Added clarification for kwargs propagation in tool_loop_agent
- Unified deprecation marker format
- Fixes #4429

* Convert developer API comments to English

* chore: revise comments

---------

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

* fix: handle empty output case in PythonTool execution

* fix: update description for command parameter in ExecuteShellTool

* refactor: remove unused file tools and update PythonTool output handling

* project list

* fix: ensure message stream order (#4487)

* feat: enhance iPython tool rendering with Shiki syntax highlighting

* bugfixes

* feat: add sandbox mode prompt for enhanced user guidance in executing commands

* chore: remove skills prompt

---------

Co-authored-by: 時壹 <137363396+KBVsent@users.noreply.github.com>
Co-authored-by: Li-shi-ling <114913764+Li-shi-ling@users.noreply.github.com>
2026-01-15 16:17:56 +08:00
時壹
9782d1bff8 fix:exclude disabled commands from platform command registration (#4485) 2026-01-15 14:04:15 +08:00
Soulter
0e3d224c12 fix: ensure message stream order (#4487) 2026-01-15 13:11:27 +08:00
Soulter
8aeb2229ce fix: chatui title (#4486) 2026-01-15 12:47:55 +08:00
Li-shi-ling
179f3e6426 docs: standardize Context class documentation formatting (#4436)
* docs: standardize Context class documentation formatting

- Unified all method docstrings to standard format
- Fixed mixed language and formatting issues
- Added complete parameter and return descriptions
- Enhanced developer experience for plugin creators
- Fixes #4429

* docs: fix Context class documentation issues per review

- Restored Sphinx directives for versionadded notes
- Fixed MessageSesion typo to MessageSession throughout file
- Added clarification for kwargs propagation in tool_loop_agent
- Unified deprecation marker format
- Fixes #4429

* Convert developer API comments to English

* chore: revise comments

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2026-01-14 23:46:27 +08:00
Soulter
561741d43d fix: title saving logic and update project sessions on changes 2026-01-14 20:51:54 +08:00
Soulter
63e8d0634f feat: chatui project (#4477)
* feat: chatui-project

* fix: remove console log from getProjects function
2026-01-14 19:15:48 +08:00
時壹
350667b60f fix: sending OpenAI-style image_url causes Anthropic 400 invalid tag error (#4444) 2026-01-14 10:50:56 +08:00
Soulter
6a86dae76e docs: refine EULA 2026-01-13 12:19:05 +08:00
Soulter
a7eca40fe7 feat: implement localStorage persistence for showReservedPlugins state 2026-01-13 02:23:31 +08:00
Soulter
ef28dc5001 chore: makes world better 2026-01-13 02:20:24 +08:00
Soulter
d29ac4023a fix: typo 2026-01-12 21:24:11 +08:00
Soulter
c2af2c6d5e chore: bump version to 4.11.4 2026-01-12 20:42:49 +08:00
Soulter
d9fb29d314 docs: add initial EULA for user agreement and compliance 2026-01-12 20:32:28 +08:00
Soulter
981421ded6 docs: update readme 2026-01-12 20:31:17 +08:00
Soulter
49ad22ca82 fix(i18n): refine default source label in English and Chinese locales 2026-01-12 20:05:21 +08:00
Soulter
858e245108 chore: remove default provider source displayed in webui 2026-01-12 19:51:18 +08:00
Soulter
6ac37ecd60 chore: bump version to 4.11.3 2026-01-12 19:35:41 +08:00
Soulter
2bbe010747 Sanitize invalid platform IDs on load (#4432) 2026-01-12 19:04:44 +08:00
Soulter
52bba9026a feat(safety): LLM healthy mode (#4431)
* feat(safety): implement LLM safety mode

* chore: ruff format
2026-01-12 18:33:34 +08:00
clown145
3416e8990c fix(webui): optimize markdown rendering and remove redundant code (#4415)
* fix(dashboard): optimize markdown rendering and remove redundant code

* style: format code and refactor ReadmeDialog for i18n/isolation

* fix: robust clipboard fallback for http context

* refactor: optimize markdown rendering and fix table styles in ReadmeDialog
2026-01-12 17:39:53 +08:00
時壹
eedb62a5a3 fix: detect image MIME type from binary data for Anthropic API (#4426) 2026-01-12 17:35:23 +08:00
Oscar Shaw
e8bd821e72 feat(log): append version number tag to WARN and ERROR level logs (#4388)
* feat(log): 在 WARN 和 ERROR 级别日志中追加版本号标签

* refactor(core): 简化日志版本标签过滤逻辑以包含 WARNING 及以上级别
2026-01-12 17:30:38 +08:00
NayukiMeko
131950b909 fix (#4297): fix list config being saved as [""] instead of [] after deletion (#4401)
* fix: 修复列表配置项删除后保存为['']而非[]的问题 (#4297)

* fix: 添加类型检查以处理非字符串列表项

* refactor: 移除 ExtensionPage 中重复的 cleanEmptyListItems

过滤逻辑已在 ListConfigItem.vue 源头处理,保存配置时无需再次过滤。
2026-01-11 18:53:15 +08:00
Futureppo
2e172804e3 feat(context): sannitize llm context by modalities (#4367)
* feat(context): 添加按模型能力清理历史上下文

* fix(config): 更新历史上下文清理提示信息

* chore: ruff format

* fix: simplify modality checks and sanitize context handling

* fix(config): disable context sanitization by modalities

* fix(agent): skip messages with empty roles in InternalAgentSubStage

* fix(agent): refine tool call handling in InternalAgentSubStage

---------

Co-authored-by: Soulter <905617992@qq.com>
2026-01-11 15:39:23 +08:00
Gao Jinzhe
2f3a3f354f fix: add image placeholder for non-vision models to fix no response in private chat (#4411)
* fix: 修复私聊中单独发送图片无响应的问题,为非视觉模型添加图片占位符

* ruffcheck

* 修复占位符被重复添加的问题

* 简化逻辑
2026-01-11 15:11:35 +08:00
letr
86e9b41dde fix(core): correct duplicate word in agent logger warning (#4390)
- Fix duplicate '没有' in logger warning message
- Improve punctuation and readability of tool response comments
2026-01-11 15:00:35 +08:00
Gao Jinzhe
8dfe43f22f fix(webui): add null check for plugin list in config to fix empty list issue (#4392) 2026-01-11 14:39:54 +08:00
stevessr
6c2f738940 fix: when session_id including ":" (#4380) 2026-01-11 14:33:44 +08:00
letr
c1102f2f5c fix(webui): fix unexpected expansion of all rows in tool table (#4366)
Corrected the property from `item-key` to `item-value` to align with
Vuetify 3 API. This ensures each row has a unique identifier for
the expansion state.
2026-01-11 14:27:07 +08:00
Li-shi-ling
9a91f2fb11 fix: ensure atomic creation of knowledge base with proper cleanup on failure (#4406)
* fix: ensure atomic creation of knowledge base with proper cleanup on failure

- Added pre-validation for embedding_provider_id parameter
- Added check for existing knowledge base with same name
- Implemented proper rollback mechanism when KBHelper initialization fails
- Uses same session for cleanup to ensure data consistency
- Fixes #4403

* fix: ensure atomic KB creation with session.flush() to remove race condition risks

* fix: ensure change the annotation back
2026-01-11 14:24:26 +08:00
Soulter
81309bc908 perf: enhance reply functionality to support selected text quoting (#4387)
* feat(chat): enhance reply functionality to support selected text quoting

* perf: improve ui

* feat(chat): add label for tools used in tool calls and update translations

* feat(chat): simplify reply handling by removing text truncation logic
2026-01-09 18:04:43 +08:00
Soulter
f003b83443 docs: update demo banner 2026-01-09 16:49:03 +08:00
Soulter
34921e91f0 chore: bump version to 4.11.2 2026-01-08 15:32:37 +08:00
Soulter
6c15592cbb feat(metrics): add metrics tracking for plugin installation events 2026-01-08 15:29:32 +08:00
letr
8c7a4b87d0 fix(webui): maintain international consistency of the 'repo' button (#4358) 2026-01-08 13:34:13 +08:00
Gao Jinzhe
8ff12e3972 fix: on_waiting_llm_request hook did not check message validity (#4349)
* fix:修复waitingllmrequest没有检查消息有效性的问题

* 进行ruff修复
2026-01-07 12:51:00 +08:00
Gao Jinzhe
eefa3f2f00 fix: conversation was still saved to the context after stop_event (#4345) 2026-01-07 12:48:13 +08:00
Oscar Shaw
479284a8dd feat(extension): plugin marketplace search supports matching display names. (#4332) 2026-01-06 12:54:11 +08:00
clown145
9322218880 feat: supports to display plugin CHANGELOG.md (#4337)
* feat: optimize plugin update changelog feature, refactor to reuse ReadmeDialog and support independent view entry

* fix: distinguish error state from empty state in ReadmeDialog
2026-01-06 12:53:14 +08:00
Soulter
399062f14d chore: remove wechatpadpro 2026-01-06 11:14:54 +08:00
Soulter
de82df3c33 chore: bump version to 4.11.1 2026-01-05 20:22:18 +08:00
Soulter
9896aebfb5 feat: enhance provider source configuration with custom hints and tooltips 2026-01-05 20:20:09 +08:00
Soulter
df7653eb99 fix: 部分情况下选择提供商出现”暂无可用提供商的问题“,即使实际上有 2026-01-05 20:01:54 +08:00
Soulter
8e7b44185d chore: bump version to 4.11.0 2026-01-05 18:05:12 +08:00
RC-CHN
ef1c66a92e feat(webui): enable Range request support for backup downloads (#4329) 2026-01-05 17:27:03 +08:00
Soulter
241f1c26d3 feat: context compress (#4322)
* feat: context compressor

Co-authored-by: kawayiYokami <289104862@qq.com>

* Add comprehensive tests for ContextManager and ContextTruncator

- Implemented a full test suite for ContextManager covering initialization, message processing, token-based compression, and error handling.
- Added tests for ContextTruncator focusing on message fixing, truncation by turns, dropping oldest turns, and halving.
- Ensured that both test suites validate edge cases and maintain expected behavior with various message types, including system and tool messages.

* feat: add MockProvider for LLM compression tests

* chore: remove lock

* ruff fix

* fix

* perf

* feat: enhance context compression with token tracking and logging

* feat: update logging for context compression trigger

* feat: implement context compression logic with dynamic threshold and token tracking

* fix: reorder import statements for consistency

* feat: add token_usage tracking to conversations and update related processing logic

---------

Co-authored-by: kawayiYokami <289104862@qq.com>
2026-01-05 17:26:10 +08:00
Soulter
3615b7dde2 fix: token usage is always 0 in anthropic source (#4328) 2026-01-05 17:06:12 +08:00
RC-CHN
9bcf9bf2a0 fix(dashboard): complete i18n support for shared components (#4327)
* fix(dashboard): complete i18n support for shared components

- Replace hardcoded Chinese strings with i18n translations in:
  - PluginSetSelector.vue
  - ProviderSelector.vue
  - PersonaSelector.vue
  - KnowledgeBaseSelector.vue
  - T2ITemplateEditor.vue
  - AstrBotConfigV4.vue
  - ConfigItemRenderer.vue
  - ProxySelector.vue
  - ListConfigItem.vue

- Add missing translations to locale files:
  - core/shared.json: personaSelector, t2iTemplateEditor
  - core/common.json: autoDetect
  - features/settings.json: network.proxySelector

- Change prop defaults from hardcoded Chinese to empty strings,
  allowing components to use i18n fallback translations

* fix(i18n): 修正插件选择器标签的翻译格式,添加冒号

* fix(deployment): 添加持久化 machine-id PVC 和初始化容器,优化资源限制
2026-01-05 09:45:28 +08:00
Gao Jinzhe
7f5cc7cf1a feat: add on_waiting_llm_request event hook (#4319)
* 加入on_waiting_llm_request钩子

* ruff check
2026-01-04 16:11:12 +08:00
Oscar Shaw
f26867c77d ci(stale): 增加 stale action 每次运行的操作限制 (#4256) 2026-01-04 11:20:03 +08:00
Soulter
a14d588b44 docs: add Matrix adapter to community maintained section in multiple languages 2026-01-04 10:15:16 +08:00
Soulter
e236402d92 chore: update platform adapter name for clarity 2026-01-04 10:12:25 +08:00
Soulter
454841de10 fix: database is locked error when invoking tts command (#4313)
* fix: database is locked error when invoking /tts command

fixes: #4311

* chore: rm pnpm lockfile

* perf: 减少操作数据库的次数
2026-01-03 19:12:39 +08:00
clown145
442b5403df feat(webui): supports force update plugins (#4293) 2026-01-03 15:30:50 +08:00
Soulter
9db7bf59b8 docs: add new community group contact 2026-01-03 00:48:55 +08:00
雪語
3622504021 fix: retry failed due to a mismatch in the msg.id data type of a WeChat Official Account (#4292)
问题描述:
- 控制台显示正常发送消息,但公众号未收到
- 处理时间 > 5秒的消息几乎总是失败(如 AI 图片生成)
- 短消息(<5秒)正常工作

根本原因:
msg.id 是整数类型,但字典 key 使用字符串类型,导致类型不匹配。
检查时整数无法匹配字符串 key,导致每次都创建新的 future,
微信重试时无法重用,最终导致响应失败。

修复内容:
将 msg.id 转换为字符串后再检查字典
  if str(msg.id) in self.wexin_event_workers:

影响范围:
- 修复了微信重试时无法正确重用 future 的问题
- AI 图片生成、长文本生成等耗时操作现在可以正常工作
- 仅影响微信公众号适配器,其他平台不受影响

Fixes #1679
2026-01-02 22:16:04 +08:00
Soulter
fc42db40ce chore: bump version to 4.10.6 2026-01-02 12:14:59 +08:00
Soulter
e413a002c1 perf: list view mode toggle with localStorage support in ExtensionPage (#4288)
closes: #4253
2026-01-02 11:59:41 +08:00
tjc66666666
6437d759a3 fix: reasoning content inject for openai api (#4284) 2026-01-02 01:09:28 +08:00
Soulter
c758b2d888 feat: use shell globbing to match umop config router (#4270)
* feat: use shell globbing to match umop config router

* rf

* fix: use fnmatchcase for case-sensitive matching in UmopConfigRouter
2025-12-31 23:10:12 +08:00
Soulter
510290fe0e chore: bump version to 4.10.5 2025-12-31 17:58:28 +08:00
Soulter
c61d62edb6 fix: handle null item-meta in ConfigItemRenderer (#4269)
fixes: #4268
2025-12-31 17:55:49 +08:00
Soulter
45bce6fe76 chore: bump version to 4.10.4 2025-12-31 12:50:37 +08:00
Soulter
f156adddf8 feat: enhance configuration editor with template schema support and UI improvements (#4267)
- Added support for template schemas in the configuration editor, allowing users to define and manage additional parameters like temperature, top_p, and max_tokens.
- Improved UI components in ProviderModelsPanel and ObjectEditor for better user interaction, including new configuration buttons and enhanced input handling.
- Updated localization files to include new configuration options.
2025-12-31 12:19:29 +08:00
Soulter
b5a4b80c36 perf: Add list item add button (#4259)
fixes: #4254
2025-12-30 15:27:17 +08:00
Soulter
792fb69d6d perf: allow zero chunk overlap in recursive chunker (#4258)
* Allow zero chunk overlap

* Validate recursive chunking bounds
2025-12-30 15:23:05 +08:00
Oscar Shaw
300a73ace0 fix(#4188): terminate the same plugin when install the plugin via file (#4250)
* fix(#4188): 从文件安装插件时先终止并解绑已存在的同名插件

* feat(star): 优化从文件安装插件的处理同名冲突逻辑,增加边缘检查
2025-12-30 13:43:44 +08:00
Oscar Shaw
a5b9de3695 Update stale.yml 2025-12-30 11:10:21 +08:00
fluidcat
90142bcafe fix: ensure close aiodocker.Docker() (#4251)
* fix: ensure close aiodocker.Docker()

* fix: code formatted
2025-12-30 00:24:29 +08:00
Misaka Mikoto
79d0487c03 feat: add template_list config type to support multiple repeated core/plugin config sets (#4208)
* feat: 添加模板列表配置支持,包含验证和编辑功能

* refactor(dashboard): extract ConfigItemRenderer to eliminate code duplication

- Create ConfigItemRenderer.vue to centralize rendering logic for various config types (string, int, bool, selectors, etc.)
- Refactor TemplateListEditor.vue to use the new renderer for entry fields
- Refactor AstrBotConfig.vue and AstrBotConfigV4.vue to simplify metadata-driven rendering
- Resolve circular dependency by decoupling TemplateListEditor from the base renderer

* ruff format

* refactor: improve config validation and fix unidirection data flow

- Frontend: Fix one-way data flow in TemplateListEditor.vue by cloning entries before applying defaults and emitting updates instead of in-place modification.
- Frontend: Remove unused TemplateListEditor import in ConfigItemRenderer.vue.
- Backend: Refactor validate_config in config.py by extracting _expect_type and _validate_template_list helpers to reduce nesting and complexity.
2025-12-30 00:16:24 +08:00
akuuma
4f15102e79 perf(satori): increase websocket max message size to 10MB (#4238)
* perf(satori): increase websocket max message size to 10MB

Add max_size parameter to websocket connection to handle larger messages
and prevent connection drops when receiving large payloads from Satori platform.

* chore: ruff format

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2025-12-29 23:59:55 +08:00
Oscar Shaw
ef1feb639c fix(utils): optimize pip install output decoding for cross-platform encoding compatibility (#4249) 2025-12-29 23:54:11 +08:00
Oscar Shaw
1039a4f864 chore: update stale issue workflow to target only 'bug' labeled issues and adjust inactivity handling (#4252) 2025-12-29 23:49:40 +08:00
Soulter
66e2f49c11 perf: support extended thinking for Anthropic, DeepSeek reasoning mode, and Gemini text part thought signatures to improve multi-turn reasoning performance. (#4240)
* perf: support extended thinking for Anthropic, DeepSeek reasoning mode, and Gemini text part thought signatures to improve multi-turn reasoning performance.

* chore: remove verbose

* perf

* refactor: remove special tools handling for deepseek-reasoner model in openai source

* fix: improve error handling and logging in InternalAgentSubStage processing

* refactor: remove unused reasoning content from Gemini source processing

* refactor: enhance modality determination logic in useProviderSources

Co-authored-by: kawayiYokami <289104862@qq.com>
2025-12-29 14:22:30 +08:00
fluidcat
c5773fe63e feat: add JSON value for custom_extra_body (#4246)
* feat: add JSON value for custom_extra_body

* feat: add invalid format tip
2025-12-29 12:52:10 +08:00
NieiR
4e9ef48af2 fix: handle None values in _extract_usage to prevent TypeError (#4244)
* fix: handle None values in _extract_usage to prevent TypeError

Some LLM providers (especially API proxies) may return None for
prompt_tokens and completion_tokens in the usage response. This
causes a TypeError when attempting arithmetic operations.

Added null checks with fallback to 0 for both prompt_tokens and
completion_tokens before performing calculations.

* refactor: use explicit None check and reuse cached variable

- Use `is None` instead of `or 0` to avoid masking unexpected falsy values
- Reuse `cached` variable for `input_cached` to avoid redundant calculation

* ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-29 12:49:25 +08:00
RC-CHN
9eafd7b44a feat: add features for chunked upload and backup file management to the backup section (#4237)
* feat: 添加分片上传备份文件功能

* feat: 为上传备份文件添加异步并发以提升速度

* feat: 使用浏览器原生下载方式以显示进度条

* feat: 添加从已上传备份列表恢复的功能

* feat: 允许重命名备份文件

* feat: 在后端校验可用备份文件后在前端部分显示备份版本号,添加手动上传提示

* style: format code

* fix: 更新备份部分测试

* fix: 修复浏览器原生下载鉴权问题,通过url传参的方式完成认证

* feat(backup): 改进备份系统的分片上传和下载鉴权

- 修复浏览器原生下载鉴权问题,支持 URL 参数传递 token
- 修复上传会话过期判断,使用 last_activity 避免活跃上传被清理
- 延迟启动后台清理任务,避免 asyncio 事件循环问题
- 统一由后端计算 chunk_size 和 total_chunks,避免前后端不一致
- 更新 generate_unique_filename 文档注释与实际行为一致
- 更新测试用例以验证 origin 字段

修复问题:
- 浏览器下载时显示"需要授权"
- 大文件上传可能因会话过期失败
- __init__ 中 asyncio.create_task 可能失败

* style: format code
2025-12-29 12:30:59 +08:00
Soulter
fc61f7ad32 fix: unique session config cannot be applied in non-default astrbot config (#4232)
* fix: unique session config cannot be applied in non-default astrbot config

fixes: #4195

* perf: sesison id
2025-12-28 15:01:43 +08:00
simplify123
f51810997a fix: Xinference STT failed: INVALID (#4231)
* Update xinference_stt_provider.py

* chore: ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-28 14:42:06 +08:00
Soulter
fb4baf676f perf: add auto voice emotion for minimax tts (#4228)
* perf: add `auto` voice emotion for minimax tts

* ruff format
2025-12-28 00:34:44 +08:00
Oscar Shaw
71ad974c3c feat: two dashboard persistence optimizations (#4221)
* feat: persist console visibility state in local storage on PlatformPage

* feat: add persistence for sidebar opened items in local storage
2025-12-27 14:06:01 +08:00
Soulter
f0fff68947 fix: at sender users not working in dingtalk (#4219)
fixes: #4218
2025-12-27 11:26:39 +08:00
Soulter
3e3599835e chore: bump version to 4.10.3 2025-12-26 22:39:59 +08:00
Soulter
5255388e2d refactor: move builtin stars to astrbot package (#4209)
* refactor: move builtin stars to astrbot package

fixes: #4202

* chore: ruff format

* chore: remove print
2025-12-26 22:31:22 +08:00
Yokami
fbdd60b64c feat: add extra user content block support (#4189)
* feat: 多文本块功能

* FIX

* 传递链

* 重命名

* refactor: unify extra_user_content_parts type to ContentPart across providers and update related handling

* claude额外块支持图片模态

* 已经处理过了不用再处理

* feat: enhance image handling in extra content blocks for multiple providers

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-26 22:08:20 +08:00
Soulter
bd1b0a2836 perf: drop unnecessary none-value fields in tool call loop (#4213) 2025-12-26 21:12:34 +08:00
Soulter
19541d9d07 fix: ensure max_tokens is set and validate tool_calls type in ProviderAnthropic (#4212) 2025-12-26 21:01:05 +08:00
大饼鸡蛋
2a5d574394 fix: failed to initialize FishAudio TTS instance (#4200)
fixes: #4172

* fix: 修复 FishAudio 源的配置加载问题并增强请求鲁棒性

- Fix `KeyError: 'model'``: 适配新版配置结构。
- Add `timeout` support: 防止长文本生成时超时。
- Improve response handling: 使用更标准的 Header 检查方式。

* feat: 使用更安全的类型转换并优化错误信息打印
2025-12-26 20:50:45 +08:00
Soulter
f2924fbd1b chore: update readme 2025-12-26 18:04:56 +08:00
Gao Jinzhe
703e208947 fix: handle index out of range error when selecting provider (#4206) 2025-12-26 18:02:43 +08:00
NoctuUFO
9a5cc977c2 fix: fix log loss on SSE reconnect using Last-Event-ID (#4205)
* feat: implement last-event-id handing in log route

* perf: better log handling

* chore: ruff format

* perf: log

* Update ConsoleDisplayer.vue

* Update package.json

* Update ConsoleDisplayer.vue

* Update common.js

* chore: ruff format

* fix: ensure last_event_id is required for log replay

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-26 18:01:58 +08:00
RC-CHN
aa38fe776a feat: supports data backup (#4105)
* feat: 添加数据迁移功能

* test: 添加迁移相关测试

* feat: 备份插件及相关持久化目录

* fix: 修复版本号比较逻辑,添加相关测试

* fix: 清洗文件名,添加相关测试

* fix: 修复安全文件名测试用例断言

* refactor: 优化代码,为备份模块提取公用常量

* feat: 修改备份版本校验逻辑,允许强制小版本间导入

* fix: 修复备份创建时间读取,修复备份相关i18n

* refactor(backup): 使用 astrbot_path 统一管理备份目录路径

* fix(backup): 清理备份模块中未使用的导入

* refactor(backup): 统一备份路径与参数并移除未用附件目录

- 通过 astrbot_path 动态获取备份/知识库/数据相关路径
- 移除 exporter/importer 未使用的 attachments_dir/data_root 传参
- 更新备份路由与测试用例的构造参数

* fix(dashboard): alias mermaid to dist entry for Vite prebundle

* fix(backup): 放行start-time接口到白名单以处理备份导入后jwt token变化导致无法自动刷新webui的问题

* chore(backup): 统一配置路径以使用动态数据目录

* refactor(backup): 使用 VersionComparator 替代重复的版本比较函数

* style(backup test): format code

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-26 15:47:50 +08:00
Luna-channel
61dfb0f207 chore: remove unnecessary files and revert auto_release.yml 2025-12-25 15:04:47 +08:00
Luna-channel
6f9cb770be 修复格式问题 2025-12-25 14:40:33 +08:00
Luna-channel
f4e05e1352 2.0 2025-12-25 02:25:38 +08:00
Luna-channel
8af46ab804 稳定版 2025-12-25 01:44:24 +08:00
Luna-channel
9d32c4e720 自定义规则界面修改 2025-12-25 00:37:10 +08:00
Soulter
701399c00c docs: update readme xmas 2025-12-24 21:58:04 +08:00
Soulter
eaee98d4b8 chore: bump version to 4.10.2 2025-12-24 21:55:05 +08:00
Soulter
76c66000a7 chore: restrict psutil version <7.2.0 to avoid compatibility issues
fixes: #4176
2025-12-24 15:48:58 +08:00
Oscar Shaw
4b365143c0 feat: support for managing command aliases (#4170)
* feat(command): persist aliases on rename and apply to runtime filter

* feat(dashboard-api): support aliases in rename command endpoint

* feat(dashboard-ui): add alias editor to rename command dialog

* feat(dashboard-ui): enhance alias editor UI in rename dialog
2025-12-24 15:37:10 +08:00
Soulter
6e4e5011e2 chore: bump version to 4.10.1 2025-12-23 21:35:40 +08:00
Venus Yan
d853bfde84 perf: handle unsupported message types with logging in OneBot adapter (#4164)
* Handle unsupported message types with logging

解决else 分支中对未知消息类型毫无防御,直接索引ComponentTypes[t],导致新类型markdown类信息报错并炸掉事件管道,且对应群聊单群永久不响应插件;尝试支持markdown类型进行支持但未经过测试

* chore: ruff format

* chore: ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-23 21:31:32 +08:00
Soulter
a0e856f80f fix: provider source id contains slash will lead to 405 (#4162) 2025-12-22 20:28:20 +08:00
Oscar Shaw
8c94a0010c fix(core): improve error handling of command parser and sync (#4161) 2025-12-22 19:54:26 +08:00
Soulter
a44fdaaec0 chore: bump version to 4.10.0 2025-12-22 18:10:30 +08:00
Soulter
60105c76f5 feat: implement router loading progress indicator 2025-12-22 13:20:39 +08:00
Soulter
bcf87d3ce4 fix: update provider subtitle for clarity in English and Chinese locales
- Revised the subtitle in the provider feature localization files to provide a more detailed description of functionalities, including chat model configuration and third-party service integrations.
2025-12-22 13:13:42 +08:00
Soulter
4d7c8c8453 style: add active background color for provider source list item in dark theme 2025-12-22 12:59:55 +08:00
Soulter
a064a9115f fix: omit thinking params for gemini image generation models (#4151)
- Expanded model name checks to include specific Gemini 2.5 and 3 variants, ensuring correct configuration for thinking parameters based on the model used.
2025-12-22 00:09:30 +08:00
Soulter
6ef99e1553 feat: enhance ChatInput and ConversationSidebar dark theme 2025-12-21 21:19:54 +08:00
Soulter
c0dbe5cf65 chore: bump version to 4.10.0-alpha.2 2025-12-21 13:11:32 +08:00
Soulter
3598c51eff fix: enhance provider model menu and sidebar session selection handling (#4144)
- Updated `ProviderModelMenu.vue` to manage menu state and load provider configurations dynamically upon opening.
- Filtered provider configurations to exclude those with `enable` set to false.
- Improved session selection logic in `useSessions.ts` to ensure the currently selected session is highlighted and properly managed during navigation.
2025-12-21 13:05:15 +08:00
Soulter
b5cdb8f650 fix: improve error handling in tool execution to prevent infinite tool call loops (#4143)
* fix: improve error handling in tool execution to prevent infinite tool call loops

- Enhanced error handling in `call_local_llm_tool` to provide more informative exceptions for ValueError and TypeError, including detailed parameter information.
- Updated `ToolLoopAgentRunner` to yield appropriate messages for cases with no response or unsupported types, ensuring clearer communication to users.
- Improved logging and messaging consistency across tool execution processes.

* refactor: clean up unused router parameter in message retrieval functions

- Removed the unused `router` parameter from `getSessionMessages` and related function calls in `Chat.vue` and `useMessages.ts`.
- Commented out the `tool_calls` dictionary in `chat.py` for clarity, indicating it is not currently in use.

* fix: enhance exception handling in tool execution for clearer error reporting

- Improved exception handling in `call_local_llm_tool` by chaining exceptions for ValueError and TypeError, providing more context in error messages.
- Ensured that traceback information is preserved in raised exceptions for better debugging.
2025-12-21 12:57:54 +08:00
Yokami
fc5b520f9b perf(agent): add max step limit to prevent infinite tool call loops (#4110)
* perf(agent): add max step limit to prevent infinite tool call loops

* feat: implement max step limit handling in main agent runner

- Enhanced the agent runner to enforce a maximum step limit, logging a warning and forcing a final response when the limit is reached.
- Updated message handling to append a user prompt when the tool call limit is exceeded.
- Refactored tool response handling to yield appropriate messages based on the response type, including handling cases with no response or unsupported types.
- Improved conversation message formatting to ensure consistent output in the assistant's responses.

* chore: ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-21 12:30:43 +08:00
Soulter
904f56b32f fix: webui conversation traj data display error (#4142)
fixes: #4141
2025-12-20 23:29:40 +08:00
Soulter
2f15fd019c chore: bump version to v4.10.0-alpha.1 2025-12-20 16:35:54 +08:00
Soulter
82330b8d10 feat: add changelog functionality and dialog component (#4135)
* feat: add changelog functionality and dialog component

- Implemented new routes for fetching changelogs and available versions in StatRoute.
- Created ChangelogDialog.vue for displaying changelog content and version selection.
- Updated VerticalSidebar.vue to include a button for opening the changelog dialog.
- Enhanced localization files for English and Chinese to support new changelog features.
- Adjusted styles in VerticalHeader.vue for improved layout consistency.

* chore: ruff format
2025-12-20 16:33:12 +08:00
Soulter
3ee6af7027 feat: add route watcher for viewMode changes in VerticalHeader.vue
- Introduced a watcher to monitor changes in customizer.viewMode, automatically redirecting to the homepage when switching from 'chat' to 'bot' mode.
- Updated imports to include useRoute from vue-router for routing functionality.
- Adjusted button styles for improved layout consistency in bot mode.
2025-12-20 15:38:01 +08:00
Soulter
6e20ebe901 feat: add KaTeX and Mermaid and computation-friendly renderer support (#4118)
* feat: add KaTeX and Mermaid support for enhanced markdown rendering in MessageList.vue

closes: #3747
- Integrated @mdit/plugin-katex and katex for LaTeX rendering.
- Added markstream-vue for improved markdown rendering capabilities.
- Updated MessageList.vue to utilize MarkdownRender component for rendering markdown content.
- Enhanced UI for dark mode compatibility across various components.
- Introduced new styles for file links, reasoning blocks, and tool call cards to improve visual consistency.

* refactor: replace markdown-it with markstream-vue for improved markdown rendering

- Removed markdown-it and related configurations from ReadmeDialog.vue, VerticalHeader.vue, and ConversationPage.vue.
- Integrated markstream-vue for enhanced markdown rendering capabilities, including support for KaTeX and Mermaid.
- Updated components to utilize MarkdownRender for rendering markdown content, improving consistency and performance.

* chore: remove deprecated markdown-it and marked dependencies from pnpm-lock.yaml

- Cleaned up pnpm-lock.yaml by removing markdown-it and marked entries, streamlining the dependency list.
- This change follows the recent integration of markstream-vue for improved markdown rendering capabilities.

* chore: remove d3 dependency and update MessageList.vue for dark mode support

- Removed d3 from package.json and commented out its import in LongTermMemory.vue to clean up unused dependencies.
- Updated MessageList.vue to ensure consistent dark mode styling by passing the isDark prop to MarkdownRender components.

* feat: add loading indicator for message retrieval in Chat and MessageList components

- Introduced a loading overlay in Chat.vue and MessageList.vue to indicate when messages are being loaded.
- Added a new `isLoadingMessages` prop to manage loading state and enhance user experience during message retrieval.
- Updated styles to ensure the loading indicator is visually integrated with the existing UI.

* feat: add provider configuration dialog to chat sidebar

- Introduced a new `ProviderConfigDialog` component for managing provider settings.
- Added a menu item in the `ConversationSidebar` to open the provider configuration dialog.
- Updated English and Chinese localization files to include translations for the new provider configuration feature.

* feat: update dashboard components and styles for improved chat experience

- Replaced font in index.html to use 'Outfit' for a fresh look.
- Changed icon in ConversationSidebar.vue to 'mdi-creation' for better representation.
- Refactored MessageList.vue to streamline loading indicators and enhance styling consistency.
- Updated localization files to change 'Provider Configuration' to 'AI Configuration' for clarity.
- Introduced new styles for loading indicators and chat mode adjustments in FullLayout.vue.
- Added functionality for toggling between bot and chat modes in the header.
- Removed deprecated sidebar item for chat navigation.

* feat: xmas easter egg

* chore: remove pnpm lock file
2025-12-20 15:22:48 +08:00
Yokami
4d6150fd6d fix: handle quoted messages correctly to prevent breaking cache (#4112)
* fix: Handle quoted messages correctly as user context

This change ensures quoted messages, including text and image captions, are appended to the conversation history as a user message rather than being injected into the system prompt.

Fixes #3886

* 注入到req.prompt里
2025-12-20 11:03:27 +08:00
Soulter
544e52191b Merge pull request #4065 from AstrBotDevs/refactor/provider-source
refactor: SUPER AMAZING model provider refactor
2025-12-20 00:09:36 +08:00
Soulter
f2c2a6da4a chore: ruff format 2025-12-20 00:07:42 +08:00
Soulter
dd3df425ee feat: add warnings for missing provider IDs in manager and context
- Introduced logging warnings in ProviderManager and Context classes when a provider ID is not found, indicating potential issues due to ID modifications.
- Updated the ProviderPage.vue to advise against modifying provider IDs, highlighting possible configuration impacts.
2025-12-20 00:06:42 +08:00
Soulter
40b4a27a3d Merge remote-tracking branch 'origin/master' into refactor/provider-source 2025-12-19 15:48:42 +08:00
Soulter
9d991c7468 perf: enhance chat components with theme and fullscreen toggles (#4116)
* perf: enhance chat components with theme and fullscreen toggles

- Added theme and fullscreen toggle functionality to Chat.vue and ConversationSidebar.vue.
- Introduced a new StyledMenu component for improved dropdown menus.
- Updated MessageList.vue and ChatInput.vue for better mobile responsiveness and UI consistency.
- Enhanced language switcher integration in ConversationSidebar.vue.
- Added new settings translations in English and Chinese locales.

* fix: streamline conversation selection handling in Chat.vue

- Updated handleSelectConversation function to immediately set the current session ID and selected sessions, reducing the need for multiple clicks.
- Adjusted padding in ConversationSidebar.vue for improved layout consistency.
2025-12-19 11:18:01 +08:00
Soulter
ad6a8b5c94 Merge remote-tracking branch 'origin/master' into refactor/provider-source 2025-12-18 17:39:27 +08:00
Soulter
1b4bfcbd72 chore: ruff format 2025-12-18 17:37:12 +08:00
Soulter
9d3cc593a1 feat: supports thinking level of google gemini (#4104)
* feat: supports thinking level of google gemini

- Updated google-genai version to >=1.56.0 in pyproject.toml and requirements.txt.
- Changed model configuration from "gemini-1.5-flash" to "gemini-3-flash-preview" in default.py.
- Enhanced thinking configuration handling in gemini_source.py to support new parameters for Gemini 3 models.

* fix: standardize thinking level configuration in default.py and gemini_source.py

- Updated the thinking level values in default.py to uppercase for consistency.
- Enhanced gemini_source.py to validate the thinking level and default to "HIGH" if an invalid value is provided.
2025-12-18 17:37:11 +08:00
Soulter
f0dee35ba9 feat: enhance tool call handling and agent stats tracking and UI integration for tool calls render (#4101)
* feat: enhance tool call handling and UI integration for tool calls render

- Added support for tool call messages in the agent runner and webchat event handling.
- Implemented JSON message component for structured tool call data.
- Updated chat route to save tool call information in message history.
- Enhanced frontend to display tool call details in a collapsible format, including status and results.
- Introduced elapsed time tracking for ongoing tool calls in the chat interface.

* fix: improve message handling in agent run utility and tool loop runner

- Refactored message sending logic in `astr_agent_run_util.py` to use `msg_chain` directly for better clarity.
- Added a check in `tool_loop_agent_runner.py` to ensure `tool_call_result_blocks` is not empty before yielding the last tool call result, preventing potential errors.

* refactor: enhance message structure and UI for chat components

- Updated message handling in `MessageList.vue` to support structured message parts, including plain text, images, audio, and files.
- Improved the `Chat.vue` component styles for better visual consistency.
- Refactored message parsing logic in `useMessages.ts` to accommodate new message formats and ensure proper rendering of embedded content.
- Removed deprecated tool call handling from the message structure, streamlining the message display process.

* chore: ruff format

* feat: implement agent statistics tracking and display in chat

- Added `AgentStats` and `TokenUsage` data classes to track agent performance metrics.
- Enhanced `ToolLoopAgentRunner` to collect and update agent statistics during execution.
- Integrated agent statistics sending to webchat for real-time updates.
- Updated chat route to save and display agent statistics in message history.
- Improved frontend components to visualize agent statistics, including token usage and duration metrics.

* fix: improve message handling in Telegram event and agent run utility

- Updated message sending logic in `astr_agent_run_util.py` to send the correct message chain for tool calls.
- Enhanced `tg_event.py` to edit messages during streaming breaks, improving message management and user experience.
- Added error handling for message editing failures to ensure robustness.

* chore: ruff format
2025-12-18 17:36:45 +08:00
Soulter
4135bd84d5 refactor: update OneBot configuration and add platform logo (#4106)
- Renamed "QQ 个人号(OneBot v11)" to "OneBot v11" in the configuration.
- Added a new logo for OneBot in the dashboard assets.
- Updated platform icon retrieval logic to include the new OneBot logo.
2025-12-18 17:34:59 +08:00
Soulter
f6da614e5d fix: validation error for ToolCall.extra_content in specific upstream model providers (#4102)
* fix: validation error for ToolCall.extra_content in specific upstream model providers

* fix: handle missing extra_content gracefully in ToolCall serialization
2025-12-18 17:34:59 +08:00
Soulter
5f531c9be5 chore: ruff format 2025-12-18 17:17:17 +08:00
Soulter
94591d965b feat: supports thinking level of google gemini (#4104)
* feat: supports thinking level of google gemini

- Updated google-genai version to >=1.56.0 in pyproject.toml and requirements.txt.
- Changed model configuration from "gemini-1.5-flash" to "gemini-3-flash-preview" in default.py.
- Enhanced thinking configuration handling in gemini_source.py to support new parameters for Gemini 3 models.

* fix: standardize thinking level configuration in default.py and gemini_source.py

- Updated the thinking level values in default.py to uppercase for consistency.
- Enhanced gemini_source.py to validate the thinking level and default to "HIGH" if an invalid value is provided.
2025-12-18 17:15:01 +08:00
Soulter
8a0f865af1 feat: enhance tool call handling and agent stats tracking and UI integration for tool calls render (#4101)
* feat: enhance tool call handling and UI integration for tool calls render

- Added support for tool call messages in the agent runner and webchat event handling.
- Implemented JSON message component for structured tool call data.
- Updated chat route to save tool call information in message history.
- Enhanced frontend to display tool call details in a collapsible format, including status and results.
- Introduced elapsed time tracking for ongoing tool calls in the chat interface.

* fix: improve message handling in agent run utility and tool loop runner

- Refactored message sending logic in `astr_agent_run_util.py` to use `msg_chain` directly for better clarity.
- Added a check in `tool_loop_agent_runner.py` to ensure `tool_call_result_blocks` is not empty before yielding the last tool call result, preventing potential errors.

* refactor: enhance message structure and UI for chat components

- Updated message handling in `MessageList.vue` to support structured message parts, including plain text, images, audio, and files.
- Improved the `Chat.vue` component styles for better visual consistency.
- Refactored message parsing logic in `useMessages.ts` to accommodate new message formats and ensure proper rendering of embedded content.
- Removed deprecated tool call handling from the message structure, streamlining the message display process.

* chore: ruff format

* feat: implement agent statistics tracking and display in chat

- Added `AgentStats` and `TokenUsage` data classes to track agent performance metrics.
- Enhanced `ToolLoopAgentRunner` to collect and update agent statistics during execution.
- Integrated agent statistics sending to webchat for real-time updates.
- Updated chat route to save and display agent statistics in message history.
- Improved frontend components to visualize agent statistics, including token usage and duration metrics.

* fix: improve message handling in Telegram event and agent run utility

- Updated message sending logic in `astr_agent_run_util.py` to send the correct message chain for tool calls.
- Enhanced `tg_event.py` to edit messages during streaming breaks, improving message management and user experience.
- Added error handling for message editing failures to ensure robustness.

* chore: ruff format
2025-12-18 17:11:09 +08:00
Soulter
4aced976a8 refactor: update OneBot configuration and add platform logo (#4106)
- Renamed "QQ 个人号(OneBot v11)" to "OneBot v11" in the configuration.
- Added a new logo for OneBot in the dashboard assets.
- Updated platform icon retrieval logic to include the new OneBot logo.
2025-12-18 15:19:15 +08:00
Soulter
0299aa6e4c fix: validation error for ToolCall.extra_content in specific upstream model providers (#4102)
* fix: validation error for ToolCall.extra_content in specific upstream model providers

* fix: handle missing extra_content gracefully in ToolCall serialization
2025-12-18 11:55:49 +08:00
Soulter
e8b54a019e refactor: replace ProviderModelSelector with ProviderModelMenu for improved UI and functionality 2025-12-17 22:57:32 +08:00
Soulter
98ce796275 chore: remove copilot instruction 2025-12-17 17:21:33 +08:00
Soulter
b87dcf2275 refactor: improve provider source ID validation to prevent duplicates during configuration updates 2025-12-17 17:19:35 +08:00
Soulter
591a228431 refactor: enhance provider management with resource locking and CRUD operations 2025-12-17 17:08:52 +08:00
Soulter
f52f375154 refactor: update provider handling to use new config structure and improve template retrieval 2025-12-17 16:55:12 +08:00
Soulter
975c685a17 chore: ruff format 2025-12-17 16:32:38 +08:00
Soulter
6db80d36a8 fix: prevent platform ID modification during updates and ensure correct routing table handling 2025-12-17 16:16:50 +08:00
Soulter
4651bd2807 feat: implement provider deletion functionality and ensure unique provider IDs 2025-12-17 15:00:22 +08:00
Soulter
94ada3793e Merge remote-tracking branch 'origin/master' into refactor/provider-source 2025-12-17 13:33:23 +08:00
Soulter
fd05b0bf09 docs: update contributing guidelines to include code style and formatting instructions 2025-12-17 13:26:22 +08:00
Soulter
4d046f8490 delete: remove backup of ProviderPage.vue 2025-12-17 11:34:12 +08:00
Copilot
58e32b7b70 fix: inverted logic in segmented reply LLM-only filter (#4071)
* Initial plan

* Fix: Correct inverted logic in is_seg_reply_required for only_llm_result option

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>
2025-12-17 11:12:05 +08:00
Soulter
903dd0f9f7 feat: add manual model addition functionality and search capability in ProviderPage 2025-12-17 10:56:45 +08:00
Soulter
1acac0cac2 feat: enhance provider selection with a new drawer interface and localization updates 2025-12-17 10:39:16 +08:00
Oscar Shaw
80b89fd2ea feat: implements command management and improve webui feature structure (#3904)
move mcp management to plugin managemanet page

* feat: 新增命令配置数据库模型

* feat: 实现核心命令管理系统

* feat: 将命令管理集成到 Star 框架

* feat: 新增命令管理后台 API

* feat: 新增命令管理界面页面

* feat: 新增命令管理国际化支持

* test: 新增命令管理相关测试

* refactor(command): 移除指令重命名时的别名功能

* fix(command): 修正指令冲突检测逻辑

* fix(command): 排除已禁用指令的冲突检测

- 只有 `effective_command` 存在且 `enabled` 为 `True` 的指令才会被纳入冲突检测范围。

* feat(command): 优化指令冲突显示与提示

- 【功能】新增指令冲突警告提示,当检测到冲突时显示详细信息及解决方案。
- 【优化】调整指令列表排序逻辑,将冲突指令优先显示并分组。
- 【样式】为冲突指令行添加专属高亮样式,提升视觉识别度。
- 【国际化】更新英文和中文多语言文件,增加指令冲突警告相关的翻译文本。

* chore(command-page): 禁用命令表格部分列的排序功能

* style(command-page): 调整命令页面表格样式和图标大小

* refactor(command): 优化指令页面布局并更新冲突警告

- 【布局优化】重新组织指令管理页面布局,将筛选器移至顶部独立行
- 【信息展示】将搜索栏与总指令数、已禁用指令数合并显示,提升页面空间利用率
- 【视觉更新】更新指令冲突警告样式

* style: UI 细节

* refactor(command): 调整指令管理中的成员权限显示与筛选

  - 更新指令筛选逻辑,当选择“所有人”权限筛选时,将同时包含 `everyone` 和 `member` 权限的指令。

* feat(command-management): 新增指令层级管理与UI展示

- 【后端】
  - `CommandDescriptor` 新增 `parent_group_handler` 和 `sub_commands` 字段,支持指令层级结构定义。
  - `list_commands` 函数重构,实现指令的层级收集与构建,将子指令正确挂载到其父指令组下。
  - 新增 `_collect_all_descriptors` 和 `_find_parent_group_handler` 辅助函数,用于全面收集指令并定位父指令组。
  - `_build_descriptor` 优化指令类型判断逻辑,明确区分普通指令、指令组和子指令。
  - `_descriptor_to_dict` 递归处理子指令,确保 API 返回完整的指令层级数据。
- 【前端】
  - 指令管理页面 (`CommandPage.vue`) 增加指令类型筛选器,并支持指令组的展开/折叠功能。
  - 表格展示优化,为指令组和子指令添加不同的样式和缩进,提升层级结构的视觉可读性。
  - 指令详情对话框新增指令类型、所属指令组和子指令列表的展示。
  - 更新 `CommandItem` 接口,以适配后端提供的层级数据结构。
- 【i18n】
  - 新增指令类型(指令、指令组、子指令)的国际化文本。
  - 更新指令管理相关 UI 文本,包括表格头部、详情对话框字段和筛选器选项。

* style(command): 优化指令组子指令数量显示UI

* refactor(command): 修改指令列表排序逻辑

* style(command-page): 优化命令列表UI

* feat(command): 添加系统插件指令过滤与冲突处理

* refactor(command): 更新指令数展示逻辑

* style(command): 更新空状态描述

* feat(extension): 添加插件指令冲突检测与提示

- 在插件安装或启用后,自动检测并提示指令冲突。
- 当检测到指令冲突时,显示警告对话框,告知用户冲突数量及可能的影响。

* refactor(command): 移除指令表格内部加载指示器

* style(extension): 文案修改

* refactor(command): 模块化指令管理面板前端代码

* refactor(commandPanel): 重命名指令模块目录为 commandPanel

* style(commandPanel): 微调指令面板UI

* fix(command): 确保新命令配置的事务提交

* fix(sidebar): 补全新增侧边栏项后的侧边栏位追加逻辑

* refactor(commands): 重构/help指令以动态显示实际命令并补充部分命令描述

* style(builtin_commands): 补充命令描述

* refactor(commandPanel): 移除未使用的 filterState 常量

* perf(dashboard): 删除多余的CommandPage.vue文件(已被模块化引用)

* perf(command): 优化命令冲突计数逻辑

* perf(command): 优化指令管理辅助函数和配置绑定逻辑

* perf(db): 优化重构command相关数据库操作

* refactor(sidebar): 提取侧边栏项目解析逻辑到工具函数复用

* refactor: move mcp and command page to extension page

* refactor: remove unused imports in component panel

* fix: update terminology for handler management in extension localization

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-16 20:24:57 +08:00
Soulter
26f863ba81 Revert "fix: omit empty content field for the LLM request after tool calls ar…" (#4068)
This reverts commit f78a90218e.
2025-12-16 20:22:13 +08:00
sctop
f78a90218e fix: omit empty content field for the LLM request after tool calls are completed (#4008)
* fix: omit content field for the LLM request after tool calls are completed and content is empy string or none

* chore: ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-16 20:11:11 +08:00
Soulter
a3ecebd2aa fix: correct text accumulation logic in webchat (#4066) 2025-12-16 19:35:41 +08:00
Soulter
67c33b842d feat: add new provider icons and improve provider source handling
- Added icons for 'modelstack', 'tokenpony', and 'compshare' in providerUtils.js.
- Updated ProviderPage.vue to display the correct count of displayed provider sources.
- Enhanced the logic for displaying provider sources to include placeholders for unselected templates.
- Improved the display name for provider sources to show template keys for placeholders.
- Adjusted styles for better layout and overflow handling in provider source list and cards.
- Refactored source selection logic to handle placeholder sources correctly.
- Updated error handling in provider testing to provide clearer messages.
2025-12-16 16:11:56 +08:00
Soulter
5431c9f46e refactor: remove unused tab from AddNewProvider and disable button based on provider status in ProviderPage 2025-12-16 12:26:26 +08:00
Soulter
764b91a5f7 chore: ruff check 2025-12-16 12:21:14 +08:00
Soulter
c20c1b84bf feat: implement LLM metadata fetching and integrate into provider model selection 2025-12-16 12:19:40 +08:00
Soulter
fd66a0ac00 perf: better UI 2025-12-16 11:24:07 +08:00
Soulter
aaee283367 fix: type checking of AstrAgentContext 2025-12-16 10:09:57 +08:00
Soulter
4a5b7d1976 fix: type checking of contextwrapper 2025-12-16 09:59:56 +08:00
Sukafon
08244548ab fix: incorrect type assignment when the agent send an image (#4050) 2025-12-16 08:28:10 +08:00
dependabot[bot]
b486de6a98 chore(deps): bump actions/upload-artifact in the github-actions group (#4061)
Bumps the github-actions group with 1 update: [actions/upload-artifact](https://github.com/actions/upload-artifact).


Updates `actions/upload-artifact` from 5 to 6
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-16 08:24:03 +08:00
Soulter
e2f928a7e5 chore: bump version to 4.9.2 2025-12-15 16:58:32 +08:00
Soulter
b8e4068c75 feat: support key-value storage for plugins (#4048)
* feat: support key-value storage for plugins

* fix: remove unnecessary initialization method from Main class
2025-12-15 16:50:44 +08:00
Soulter
0916177a57 chore: bump version to 4.9.1 2025-12-15 16:07:10 +08:00
Soulter
02cd5e396b feat: add trigger probability setting for TTS and support to render slider in schema (#4047)
* feat: add trigger probability setting for TTS and support to render slider in schema

* chore: ruff format
2025-12-15 16:04:27 +08:00
Soulter
56673ad78f fix: prevent duplicate result content type after streaming finishes in RespondStage 2025-12-15 15:33:40 +08:00
Soulter
9a4d05e2b6 fix: remove unnecessary persistent attribute from ReadmeDialog and adjust dialog structure in ExtensionPage 2025-12-15 15:27:42 +08:00
Soulter
b2e9dab233 refactor: enhance layout and improve provider source management in ProviderPage 2025-12-15 15:15:17 +08:00
Soulter
45110200ea feat: update provider and provider source configuration handling 2025-12-15 12:31:29 +08:00
Soulter
c3f45449e8 docs: readme
wa ta shi wa ko sei no de su ka ra!
2025-12-15 11:47:21 +08:00
Copilot
65da469deb feat: add conversation export feature to JSONL for AI training (#4037)
* Initial plan

* Add conversation export functionality (backend and frontend)

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

* Address code review feedback: move imports, simplify logic, improve i18n

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

* Simplify frontend download logic: remove redundant Blob wrapper and complex filename parsing

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

* fix: update conversation export filename format for consistency

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-12-14 21:44:12 +08:00
Soulter
16df64c405 fix: lark domain and log_level of Lark API client (#4038)
fixes: #4035
2025-12-14 21:31:17 +08:00
i0cLiceao
6b73b19e54 fix: support using GitHub Raw content as plugin source (#3975)
* Update plugin.py

* Update plugin.py

* Update plugin.py

* Update plugin.py
2025-12-14 18:23:29 +08:00
Soulter
a70088b799 Merge remote-tracking branch 'origin/master' into refactor/provider-source 2025-12-13 23:37:23 +08:00
Soulter
e7e97730af chore: bump version to 4.9.0 2025-12-13 18:49:07 +08:00
Soulter
467ca1eb5c fix: webui log output incompletely (#4029)
* fix: webui log output incompletely

* fix: improve SSE log parsing to handle partial data chunks

* fix: enhance log handling by implementing local cache and fetching history

* fix: log time handling to use epoch time
2025-12-13 18:46:16 +08:00
Soulter
bb45d9cb54 stage 2025-12-13 17:16:07 +08:00
RC-CHN
46528391c2 feat: add pre-chunk import strategy for knowledge base (#3973)
* feat: 添加文档导入功能及相关测试

* feat: 优化文档上传功能,支持从文件名推断文件类型,并增强文档切片验证

* feat: 添加文档导入功能的无效输入测试,验证 chunks 类型和内容的错误处理

* refactor: 重构文档上传和导入任务的状态管理,添加任务初始化、结果设置和进度更新方法
2025-12-12 23:15:11 +08:00
Soulter
8a0b7717cc feat: supports webhook mode for Lark platform (#4016)
* feat: add Lark platform support with unified webhook configuration

* fix: update token verification logic in LarkWebhookServer

* feat: implement event deduplication and cleanup for Lark webhook events
2025-12-12 22:12:13 +08:00
Copilot
3b81fb4985 fix: mobile dialog close button visibility (#4010)
* Initial plan

* Fix mobile dialog close button visibility by adding max-height and scrollable content

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>
2025-12-12 16:02:24 +08:00
Soulter
c09d57a820 refactor: improve UI layout and interaction for list item management (#4002)
* refactor: improve UI layout and interaction for list item management

* feat: enhance list configuration UI with batch import functionality

* feat: add internationalization support for list configuration UI
2025-12-11 18:55:56 +08:00
Soulter
ec408a2aff fix: lark message timestamp 2025-12-11 18:20:50 +08:00
Soulter
417179a6b9 ci: add smoke test 2025-12-11 10:44:15 +08:00
Soulter
fcd29445c7 refactor: remove unused current provider initialization in StarRequestSubStage 2025-12-11 10:36:33 +08:00
BiDuang
5f535001db fix: incorrect modalities enum of gemini api provider (#3993) 2025-12-10 20:27:51 +08:00
PaloMiku
750d245b16 docs: Update README with new Zread link and badges (#3992)
ZRead 是由智谱 AI 推出的 DeepWiki 类似平替品。
2025-12-10 20:22:56 +08:00
Dt8333
f624971613 chore: fix bunches of type checking errors (#3213)
* chore(core.utils): 🚨 修正错误Lint

* chore(core.provider): 🚨 修复基类错误Lint

* chore(core.utils): 补全session_get()的重载

* chore(core.provider): 🚨 修正实现错误Lint

* chore(core.platform): 🚨 修正platform基类和webchat的错误Lint

* chore(core.platform): 修正错误实现Lint

* fix(core.provider): 修复循环调用和错误assert

* chore(core.platform): 修复部分实现Lint

* chore(core.provider): 补充Dify.text_chat_stream的参数类型

* chore(core.pipeline): 🚨 修复错误Lint

* fix(core.slack): 补充遗漏导入

* chore(core.utils): 修复错误的session_get声明

* chore(core.platform): 移除Lark adapter import中的wildcard

* chore(core.db): 修复声明和部分逻辑

* chore(core.db): 添加typings,使faiss参数能被正确识别。

* chore(core): 修复声明

* chore(core): 修改声明

* chore: 补充faiss声明

* chore(dashboard): 修改实现,减少报错

* chore(package): 修改部分声明与实现,减少报错

* chore(core): 添加Handler的overload,以去除部分assert同时通过类型检查

* chore(core.pipeline): 修改Pipeline Scheduler的execute,将判断属性改为判断类型,通过静态类型检查

* chore(core.config): 添加类型标注,通过类型检查

* chore(core.message): 为File._download_file添加检查,通过类型检查

* fix: 将断言改为条件判断以实现优雅关闭的容错性

* refactor: 移除 discord 客户端中的 assert,改用 if None 判断并抛出异常

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: DiscordPlatformAdapter 对 self.client.user 为 None 做日志并返回,移除断言

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: 增强 Lark 相关空值/异常检查并完善日志输出

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* refactor: 将断言替换为条件检查并加入日志与错误处理

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* chore: 移除LLM生成的无用注释

* refactor: 使用 File.get_file 替换下载逻辑并移除 assert,提供默认 filename

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: Slack Socket 未初始化抛出运行时异常,图片 URL 判空改为非空判断

* refactor: 将 WeChatPadProAdapter 的断言改为空值判断并添加日志

* refactor: 使用 isinstance 替代断言实现类型判断,便于静态检查

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: 去除cast,直接使用字段与字典访问,修正端口解析

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* refactor: 使用 match-case 重构 ProviderManager 加载并通过类型检查抛出 TypeError

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: group_name_display 时若 group 对象为空则记录错误并返回

* fix: 将 _get_current_persona_id 的 assert 替换成 if guard 并返回 None

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: 优化插件目录存在性检查及图片URL非空验证,更新JSON排序配置

* fix: 将 datetime_str 的 assert 替换为显式检查并抛出异常

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* refactor: 移除 cast,改为运行时检查并在找不到调度器时跳过

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* refactor: 移除 cast,改用 isinstance 检查 FaissVecDB 并警告

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: 删除 typing.cast 导入,并在获取文件绝对路径前校验 file_

* refactor: 移除 typing.cast,简化内容安全检查调用

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* refactor: 将 PlatformMetadata.id 设为必填并在注册时传入 id,移除 cast

* refactor: 移除 cast,改用 HasInitialize 与 isinstance 进行初始化

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: 为 ProviderManager.initialize 增加ID类型判断,避免 None 导致 get 失败

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* refactor: 为 OTTSProvider 与 AzureNativeProvider 引入 _client 与 client 属性改进上下文管理

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: 为 Whisper 自托管源添加模型未初始化校验并直接调用 transcribe

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* refactor: 移除未使用的 cast 导入并简化 platform_name 赋值

* refactor: 引入 cast 并对 id 使用 cast(str, ...) 提升类型安全

* fix: 将 _id_to_sid 返回改为 str,空值返回空串;对 id 与 message_id 使用 cast

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* refactor: 重构 Discord 处理逻辑:强制 类型转换、优先斜杠指令并优化提及判断

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* fix: 统一对 id 获取执行 cast,并在微信消息解析失败时抛错

* Revert "fix: 去除cast,直接使用字段与字典访问,修正端口解析"

This reverts commit 1cbfdf9d1b.

* fix: 百炼 Rerank 会话关闭时返回空结果;初始化 request.prompt 避免空值拼接

* fix: 统一处理搜索结果链接为字符串,新增 _get_url 助手并适配 Bing/Sogo

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>

* refactor: 调整 call_handler 泛型、Discord 通道注解及 FishAudioTTS API 请求类型

* refactor: 使用 col(...) 替代列引用并对结果进行 CursorResult 强转

* chore: ruff format

---------

Co-authored-by: aider (openai/gemini-3-pro-high) <aider@aider.chat>
Co-authored-by: Soulter <905617992@qq.com>
2025-12-09 14:13:47 +08:00
Soulter
aa6d07afcc refactor: move all internal commands from astrbot plugin to default_command plugin (#3960)
* refactor: move all internal commands from astrbot plugin to default_command plugin

* ruff check

* feat: add config

* ruff check
2025-12-08 22:17:32 +08:00
Soulter
2c36649874 feat: add Agent Runner test prompt dialog in ProviderPage (#3968) 2025-12-08 21:46:47 +08:00
Soulter
c95735dcc0 docs: update readme 2025-12-08 12:05:57 +08:00
Soulter
03bb278f50 chore: ruff check 2025-12-08 11:00:43 +08:00
Soulter
a5e0974da3 chore: ruff format 2025-12-08 00:36:56 +08:00
vmoranv
f0fb447fbc feat: custom plugin api source manager (#3956)
* feat: custom plugin api source manager

* fix: rename plugin source file in a safer way

* chore: turned the way of saving plugin source to backend and refacted some components

* style: clean up whitespace and improve logging message formatting

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-08 00:32:50 +08:00
Soulter
37566182b0 feat: segment reply supports segmentation words (#3959)
* feat: segment reply supports segmentation words

* chore: ruff format

* feat: enhance segmented reply processing by refining word extraction logic

* ruff format
2025-12-08 00:27:17 +08:00
Soulter
e460b411da chore: remove dev version from webui (#3951)
* chore: remove dev version

* chore: remove development version references from header localization files
2025-12-07 15:23:30 +08:00
Soulter
e14ed804da chore: bump version to 4.8.0 2025-12-05 19:09:56 +08:00
Oscar Shaw
8e4e49df20 fix: not invoke on_llm_response hook when LLM request has error (#3871)
* fix: handle on_agent_done in error responses

- Introduced an LLMResponse for error messages to be processed by agent hooks, ensuring better error reporting and handling.

* fix: improve error logging in on_agent_done hook

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2025-12-05 16:13:46 +08:00
Oscar Shaw
5d856900ef perf: some UI/UX fixes, change Console to Platform Logs (#3873)
* refactor: 统一‘平台日志’文案

* perf: 优化自动滚动开关键操作逻辑

* perf: add tooltips to save and code editor buttons
2025-12-05 16:02:20 +08:00
Soulter
380a68b96c chore: add CONTRIBUTING.md 2025-12-05 15:59:18 +08:00
易推倒白毛
8879bd7e9d fix: add supports for Whisper with QQ amr audio file
* fix: Whisper API对QQ语音amr文件的支持

* Update whisper_api_source.py

* fix: cleanup temporary files in Whisper API

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-05 15:41:37 +08:00
RC-CHN
2cce09400f feat: add Kubernetes manifests for astrbot and napcat deployment with services and persistent storage (#3901)
* feat: add Kubernetes manifests for astrbot and napcat deployment with services and persistent storage

* chore: remove 11451 port

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-04 20:36:35 +08:00
Oscar Shaw
54d26dcd38 perf: integrate Pinia store for log cache management (#3852)
* perf: integrate Pinia store for log cache management

* perf: remove unused code
2025-12-04 14:26:05 +08:00
Soulter
205024f27a fix: correct SQL query syntax in SQLiteDatabase class 2025-12-04 12:51:22 +08:00
Soulter
efde994907 chore: revise badges and language links
Updated badge links and language options in README.
2025-12-03 17:21:09 +08:00
Soulter
8ca4f9cb74 feat: update README files for multilingual support and enhanced descriptions
- Added French, Russian, and Traditional Chinese README files to support a wider audience.
- Updated English and Japanese README files with improved descriptions of AstrBot's capabilities and features.
- Enhanced community section in all README files to include QQ, Telegram, and Discord group information.
- Adjusted plugin marketplace badge and key features list for clarity and consistency across languages.
2025-12-03 17:01:56 +08:00
Soulter
54e49b997b feat: enhance platform management with status tracking and error handling
- Introduced PlatformStatus enum to manage platform states (pending, running, error, stopped).
- Added error recording and retrieval functionality in the Platform class.
- Implemented a new method in PlatformManager to gather statistics for all platforms.
- Updated the dashboard to display platform statuses and error details, including a dialog for error insights.
- Enhanced localization for runtime statuses and error dialogs in both English and Chinese.
2025-12-03 16:48:57 +08:00
Soulter
5714944eef feat: unified platform webhook url (#3889)
* feat: unified platform webhook url

* chore: ruff format

* fix: 修复 Telegram 语音使用 Whisper API 报错 (#3884)

* Update whisper_api_source.py

* chore: ruff format

---------

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

* Update astrbot/dashboard/routes/platform.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_adapter.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* chore: ruff format

* fix: update webhook dialog descriptions for clarity in English and Chinese locales

* fix: update webhook URL paths to include '/api' prefix for consistency across the application

---------

Co-authored-by: 易推倒白毛 <zhaixingbi@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-03 15:44:52 +08:00
Soulter
defc46b6c9 fix: remove unnecessary blocks in Slack reply message (#3897) 2025-12-03 13:59:41 +08:00
Soulter
4d819546b0 fix: handle message sending in QQOfficialMessageEvent class (#3894)
- Added a fallback to the `_post_send` method without parameters when the stream payload is not set, ensuring proper message handling in all scenarios.

fixes: #3893
2025-12-03 13:15:12 +08:00
易推倒白毛
8006981976 fix: 修复 Telegram 语音使用 Whisper API 报错 (#3884)
* Update whisper_api_source.py

* chore: ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-12-03 02:50:50 +08:00
Soulter
f7a716af43 refactor: message storage format of webchat, support reply and file message segment (#3845)
* refactor: message storage format of webchat

* refactor: update image and record handling in webchat event processing

* fix: thinking placeholder in webchat

* feat: supports file upload in webchat

* feat: supports to delete attachments when webchat session is deleted

* perf: improve performance of file downloading

* refactor: remove unused import in chat route

* feat: add message timestamp formatting and localization support in chat

* fix: handle missing filename in file upload for chat route

* feat: enhance file handling in chat and webchat, supporting video uploads and improved attachment management

* fix: update property name for embedded files in message handling

* fix: compute variable errors after uninstalling plugins

* feat: supported for reply message and standarlize the message param

* fix: ensure message actions are displayed for the last message in the list
2025-12-02 17:11:08 +08:00
Copilot
a708901e7f fix: fix dark mode white background in conversation preview dialog (#3881)
* Initial plan

* Fix dark mode background issue in conversation data preview

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

* style: update conversation messages container background color and add debug log for dark mode detection

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-12-02 17:03:59 +08:00
Soulter
e9be8cf69f chore: bump version to 4.7.4 2025-12-01 18:42:07 +08:00
Soulter
31d53edb9d refactor: standardize provider test method implementation
- Updated the `test` method in all provider classes to remove return values and raise exceptions for failure cases, enhancing clarity and consistency.
- Adjusted related logic in the dashboard and command routes to align with the new `test` method behavior, simplifying error handling.
2025-12-01 18:37:08 +08:00
Soulter
2ba0460f19 feat: introduce file extract capability (#3870)
* feat: introduce file extract capability

powered by MoonshotAI

* fix: correct indentation in default configuration file

* fix: add error handling for file extract application in InternalAgentSubStage

* fix: update file name handling in InternalAgentSubStage to correctly associate file names with extracted content

* feat: add condition settings for local agent runner in default configuration

* fix: enhance file naming logic in File component and update prompt handling in InternalAgentSubStage
2025-12-01 18:12:39 +08:00
雪語
0e034f0fbd fix: aiocqhttp 适配器 NapCat 文件名获取为空 (#3853)
* aiocqhttp 适配器 NapCat 文件名获取为空

修复使用 NapCat 时,文件消息的 File.name 为空的问题。原代码硬编码 name="",导致下游插件无法获取文件名和扩展名

* Enhance file name retrieval from message data

Updated file name extraction logic to check multiple fields for better accuracy.
2025-12-01 13:36:19 +08:00
Soulter
2a7d03f9e1 fix: fit language and log AI responses more clearly (#3864)
* fix: fit language and log AI responses more clearly

* chore: ruff format
2025-12-01 13:24:52 +08:00
Soulter
72fac4b9f1 feat: implement unified provider availability testing across components (#3865)
- Added a `test` method to each provider class to standardize availability checks.
- Updated the dashboard and command routes to utilize the new `test` method for provider reachability verification, simplifying the logic and improving maintainability.
- Removed redundant reachability check logic from the command handler.
2025-12-01 13:17:20 +08:00
Soulter
38281ba2cf refactor: restore reachability check configuration in default settings and localization files 2025-12-01 00:38:30 +08:00
Soulter
21aa3174f4 fix: disable reachability check in default configuration 2025-12-01 00:16:11 +08:00
邹永赫
dcda871fc0 feat: provider availability reachability improvements (#3708) 2025-12-01 01:06:10 +09:00
Soulter
c13c51f499 fix: assistant message validation error when tool_call exists but content not exists (#3862)
* fix: assistant message validation error when tool_call exists but content not exists

* fix: enhance content validation in Message model to allow None for assistant role with tool_calls
2025-11-30 23:42:37 +08:00
Dt8333
a130db5cf4 fix: 将 Graceful shutdown 的异常改为 KeyboardInterrupt (#3855) 2025-11-30 20:31:17 +08:00
邹永赫
7faeb5cea8 Merge pull request #3850 from zouyonghe/feature/plugin-upgrade-all
增加升级所有插件按钮
2025-11-30 15:12:36 +09:00
ZouYonghe
8d3ff61e0d Format plugin route with ruff 2025-11-30 11:56:24 +08:00
ZouYonghe
4c03e82570 Fix plugin update JSON parsing and concurrency handling 2025-11-30 11:50:46 +08:00
ZouYonghe
e7e8664ab4 chore: tweak update all label 2025-11-30 11:18:30 +08:00
ZouYonghe
1dd1623e7d feat: batch update plugins via new api 2025-11-30 11:11:36 +08:00
ZouYonghe
80d8161d58 feat: add update all plugins action 2025-11-30 10:40:46 +08:00
Soulter
fc80d7d681 chore: bump version to 4.7.3 2025-11-30 00:42:49 +08:00
Soulter
c2f036b27c chore: bump vertion to 4.7.2 2025-11-30 00:33:07 +08:00
Soulter
4087bbb512 perf: set content attribute optional to AssistantMessageSegment for enhanced message handling
fixes: #3843
2025-11-30 00:32:00 +08:00
Soulter
e1c728582d chore: bump version to 4.7.2 2025-11-30 00:18:23 +08:00
Oscar Shaw
93c69a639a feat: 新增群聊模式下的专用图片转述模型配置 (#3822)
* feat: add image caption provider configuration for group chat

- Introduced `image_caption_provider_id` to allow separate configuration for group chat image understanding.
- Updated metadata and hints in English and Chinese for clarity on new settings.
- Adjusted logic in long term memory to utilize the new provider ID for image captioning.

* fix: format

* Fix logic for image caption and active reply settings

* Fix indentation and formatting in long_term_memory.py

* chore: ruff format

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-11-29 23:53:32 +08:00
Soulter
a7fdc98b29 fix: third party agent runner cannot run properly when using non-default config file
fix: #3815
2025-11-29 23:45:12 +08:00
Soulter
85b7f104df fix: remove unnecessary provider check (#3846)
fixes: #3815
2025-11-29 23:15:19 +08:00
Oscar Shaw
d76d1bd7fe perf: adjust padding for PlatformPage and ProviderPage log sections (#3825)
- Added bottom margin to log card for better spacing.
2025-11-29 19:15:35 +08:00
Soulter
df4412aa80 style: adjust bot-embedded-image max-width and remove hover effect for improved layout 2025-11-29 01:31:25 +08:00
Soulter
ab2c94e19a chore: comment out error logging in provider sources to reduce verbosity 2025-11-28 19:59:33 +08:00
Oscar Shaw
37cc4e2121 perf: console tag UI improve (#3816)
- Added yarn.lock to .gitignore to prevent tracking of Yarn lock files.
- Updated ConsoleDisplayer.vue to improve chip styling
2025-11-28 17:17:11 +08:00
Soulter
60dfdd0a66 chore: update astrbot cli version 2025-11-28 16:53:20 +08:00
Soulter
bb8b2cb194 chore: bump version to 4.7.1 2025-11-28 15:13:35 +08:00
Soulter
4e29684aa3 fix: add plugin set and knowledge bases selection in custom rules page (#3813)
fixes: #3806
2025-11-28 13:29:50 +08:00
Soulter
0e17e3553d chore: bump version to 4.7.0 2025-11-27 23:50:05 +08:00
Soulter
0a55060e89 fix: session controller in webchat 2025-11-27 22:32:35 +08:00
Soulter
77859c7daa feat: enhance provider status display in ProviderPage
- Added a tooltip to show detailed provider status, including availability and error messages.
- Refactored item details template to include status chips for better visual representation.
- Removed unused status section to streamline the UI.
2025-11-27 16:39:51 +08:00
Soulter
ba39c393a0 perf: enhance provider management with reload locking and logging (#3793)
- Introduced a reload lock to prevent concurrent reloads of providers.
- Added logging to indicate when a provider is disabled and when providers are being synchronized with the configuration.
- Refactored the reload method to improve clarity and maintainability.


Co-authored-by: anka <1350989414@qq.com>
2025-11-27 16:25:31 +08:00
Soulter
6a50d316d9 fix: mcp server cannot reload successfully after updating mcp server config (#3797)
fixes: #3780
2025-11-27 16:22:26 +08:00
Soulter
88c1d77f0b perf: add at message to group chat history (#3796)
* feat: enhance long-term memory message formatting

- Added support for 'At' message components in long-term memory, allowing for better representation of mentions in messages.

* chore: ruff check
2025-11-27 15:59:07 +08:00
Dt8333
758ce40cc1 chore: fix test (#3787) 2025-11-27 14:02:42 +08:00
Soulter
3e7bb80492 chore: ruff format 2025-11-27 14:01:25 +08:00
Soulter
75e95aa9ca fix: update session management icon in sidebar
- Changed the icon for the session management sidebar item from 'mdi-account-group' to 'mdi-pencil-ruler' for better representation.
2025-11-27 14:00:05 +08:00
Soulter
a389842e25 feat: update session management UI with information button and layout adjustments
- Added an information button linking to custom rules documentation.
- Adjusted layout for improved spacing and readability in the session management page.
- Minor refactoring of the data table component for better alignment.
2025-11-27 13:58:37 +08:00
Soulter
0f6a3c3f5a refactor: session management custom rules (#3792)
* refactor: umo custom rules

* feat(i18n): update session management translations and improve provider configuration handling

- Updated English and Chinese translations for session management, including "Unified Message Origin" and "Follow Config".
- Enhanced provider configuration options to include "Follow Config" as a selectable item.
- Removed unused clear buttons and refactored provider configuration saving logic to handle updates and deletions more efficiently.
2025-11-27 13:30:43 +08:00
Soulter
133f27422d feat: implement i18n of astrbot config (#3772)
* feat: implement i18n of astrbot config

* feat(config): update configuration metadata with i18n details and future deprecation notes
2025-11-26 16:40:58 +08:00
RC-CHN
abc6deb244 feat: add plugin logo placeholder (#3784) 2025-11-26 16:22:11 +08:00
teapot1de
06869b4597 docs: clarify segmented_reply words_count_threshold hint (#3779)
Update the configuration hint for `words_count_threshold` to explicitly state that it acts as a maximum limit for segmentation, preventing user confusion about it being a minimum trigger.
2025-11-26 16:15:09 +08:00
dependabot[bot]
d32cea9870 chore(deps): bump actions/checkout in the github-actions group (#3775)
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 5 to 6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-26 16:13:42 +08:00
Soulter
4b68100f16 feat(chat): add standalone chat component and integrate with config page for testing configurations (#3767)
* feat(chat): add standalone chat component and integrate with config page for testing configurations

* feat(chat): add error handling for message sending and session creation
2025-11-24 22:06:02 +08:00
Soulter
5c5515d462 fix: segmented reply regex error handling (#3771)
* fix: segmented reply regex error handling

closes: #3761

* fix: improve regex handling for segmented replies to support multiline input

* fix: update regex handling in ResultDecorateStage to use findall for segmented replies

* fix: update error logging message for segmented reply regex handling
2025-11-24 22:00:59 +08:00
Soulter
3932b8f982 Merge pull request #3760 from AstrBotDevs/feat/agent-runner
refactor: transfer dify, coze and alibaba dashscope from chat provider to agent runner
2025-11-24 15:33:20 +08:00
Soulter
82488ca900 feat(api): enhance file upload method to support mime type and file name 2025-11-24 15:30:49 +08:00
Soulter
29d9b9b2d6 feat(config): add condition for display_reasoning_text based on agent_runner_type 2025-11-24 15:10:17 +08:00
Soulter
02215e9b7b feat(config): update hint for agent_runner execution method to clarify third-party integration 2025-11-24 15:07:33 +08:00
Soulter
7160b7a18b fix: dify workflow streaming mode 2025-11-24 15:04:15 +08:00
Soulter
ea8dac837a feat(config): enhance hint for agent_runner execution method in configuration 2025-11-24 14:42:36 +08:00
Soulter
e2a7a028bd feat(migration): enhance migration process with error handling and agent runner config updates 2025-11-24 14:37:25 +08:00
Soulter
70db8d264b fix(config): disable auto_save_history option in configuration 2025-11-24 14:25:14 +08:00
Soulter
0518e6d487 feat(config): add hint for agent_runner execution method in configuration 2025-11-24 14:23:53 +08:00
Soulter
39eb367866 perf: improve file structure
- Implemented CozeAPIClient for file upload, image download, chat messaging, and context management.
- Developed DashscopeAgentRunner for handling requests to the Dashscope API with streaming support.
- Created DifyAgentRunner to manage interactions with the Dify API, including file uploads and workflow execution.
- Introduced DifyAPIClient for making asynchronous requests to the Dify API.
- Updated third-party agent imports to reflect new module structure.
2025-11-24 14:00:16 +08:00
Soulter
f1d51a22ad feat(dashscope_agent_runner): refactor request payload construction and enhance streaming response handling 2025-11-24 13:21:34 +08:00
Soulter
77fb554e8f feat(dashscope_agent_runner): implement streaming response handling and request payload construction 2025-11-24 13:09:57 +08:00
Soulter
91f8a0ae09 fix(provider_manager): use get method for provider_type check in load_provider 2025-11-24 10:57:13 +08:00
Soulter
370cda7cf0 feat(dify_api_client): add docstring for file_upload method 2025-11-24 10:53:50 +08:00
Soulter
66b3eed273 fix: correct typo in agent state transition log message 2025-11-24 00:03:22 +08:00
Soulter
99b061a143 fix: make session properties required in Session interface 2025-11-23 23:25:29 +08:00
Soulter
5f3c7ed673 feat(conversation): update agent runner type configuration path to provider_settings 2025-11-23 23:05:36 +08:00
Soulter
a6dc458212 feat(third-party-agent): implement streaming response handling and enhance agent execution flow 2025-11-23 23:03:56 +08:00
Soulter
520f521887 feat(provider): enhance agent runner provider selection with subtype filtering 2025-11-23 22:23:23 +08:00
Soulter
01427d9969 feat(config): add hint for non-built-in agent execution model configuration 2025-11-23 22:13:52 +08:00
Soulter
34c03ce983 Merge remote-tracking branch 'origin/master' into feat/agent-runner 2025-11-23 22:06:52 +08:00
Soulter
95e9da42d6 fix(webchat): webchat session cannot be deleted (#3759) 2025-11-23 22:03:07 +08:00
Soulter
1338cab61b feat: add configuration selector for session management and enhance session handling in chat components 2025-11-23 21:53:56 +08:00
Soulter
7ba98c1e91 feat: enhance provider display with grouped categorization and improved filtering 2025-11-23 21:06:16 +08:00
Soulter
9a5f507cbe feat: enable agent runner providers in configuration 2025-11-23 20:58:18 +08:00
Soulter
d560671d1f feat: agent runner config migration 2025-11-23 20:54:19 +08:00
Soulter
82c9cf4db6 chore: remove legacy coze and dashscope provider 2025-11-23 20:18:51 +08:00
Soulter
910ec6c695 feat: implement third party agent sub stage and refactor provider management
- Added `ThirdPartyAgentSubStage` to handle interactions with third-party agent runners (Dify, Coze, Dashscope).
- Refactored `star_request.py` to ensure consistent return types in the `process` method.
- Updated `stage.py` to initialize and utilize the new `AgentRequestSubStage`.
- Modified `ProviderManager` to skip loading agent runner providers.
- Removed `Dify` source implementation as it is now handled by the new agent runner structure.
- Enhanced `DifyAPIClient` to support file uploads via both file path and file data.
- Cleaned up shared preferences handling to simplify session preference retrieval.
- Updated dashboard configuration to reflect changes in agent runner provider selection.
- Refactored conversation commands to accommodate the new agent runner structure and remove direct dependencies on Dify.
- Adjusted main application logic to ensure compatibility with the new conversation management approach.
2025-11-23 20:18:51 +08:00
Soulter
766d6f2bec fix(conversation): update session configuration retrieval to use unified message origin 2025-11-23 20:18:51 +08:00
Soulter
9f39140987 fix(conversation): update session configuration retrieval to use unified message origin 2025-11-23 19:59:21 +08:00
Soulter
89716ef4da Merge remote-tracking branch 'origin/master' into feat/agent-runner 2025-11-23 14:48:08 +08:00
Soulter
3c4ea5a339 chore: bump version to 4.6.1 2025-11-23 13:58:53 +08:00
Soulter
601846a8c1 docs: refine readme 2025-11-22 18:57:08 +08:00
Soulter
85d66c1056 fix(migration): update migration_done key for webchat session tracking (#3746) 2025-11-22 18:51:00 +08:00
Dt8333
b89d3f663c fix(core.db): 修复升级后webchat未正确迁移的问题 (#3745)
不是所有人都叫Astrbot

#3722
2025-11-22 18:37:39 +08:00
Soulter
0260d430d1 Merge pull request #3706 from piexian/master 2025-11-22 01:11:35 +08:00
piexian
2e608cdc09 refactor(bailian_rerank): 修复误删除并优化top_n参数处理
- 移除不合理的知识库配置读取逻辑
- 添加os模块导入(用于读取环境变量)
- 抽取辅助函数:_build_payload()、_parse_results()、_log_usage()
- 添加自定义异常类:BailianRerankError、BailianAPIError、BailianNetworkError
- 使用.get()安全访问API响应字段,避免KeyError
- 使用raise ... from e保持异常链
2025-11-21 05:34:18 +08:00
piexian
234ce93dc1 refactor(bailian_rerank): 优化代码质量和错误处理
- 移除未使用的 os 导入
- 简化 API Key 验证逻辑
- 优化 top_n 参数处理,优先使用传入值
- 改进错误处理,使用 RuntimeError 替代通用 Exception
- 添加异常链保持原始错误上下文
2025-11-21 04:07:45 +08:00
Soulter
4e2154feb7 fix(ci): repository name must be lowercase 2025-11-20 23:46:34 +08:00
Soulter
604958898c chore: bump version to 4.6.0 2025-11-20 23:41:20 +08:00
Soulter
a093f5ad0a fix(dependencies): specify upper version limit for google-genai 2025-11-20 23:32:05 +08:00
Soulter
a7e9a7f30c fix(gemini): ensure extra_content is not empty before processing 2025-11-20 23:30:19 +08:00
Soulter
5d1e9de096 Merge pull request #3678 from AstrBotDevs/refactor/webchat-session
refactor: Implement WebChat session management and migration
2025-11-20 17:23:10 +08:00
Soulter
89da4eb747 Merge branch 'master' into refactor/webchat-session 2025-11-20 17:21:48 +08:00
Soulter
8899a1dee1 feat(chat): refactor chat component structure and add new features (#3701)
- Introduced `ConversationSidebar.vue` for improved conversation management and sidebar functionality.
- Enhanced `MessageList.vue` to handle loading states and improved message rendering.
- Created new composables: `useConversations`, `useMessages`, `useMediaHandling`, `useRecording` for better code organization and reusability.
- Added loading indicators and improved user experience during message processing.
- Ensured backward compatibility and maintained existing functionalities.
2025-11-20 17:19:45 +08:00
Soulter
384a687ec3 delete: remove useConversations composable 2025-11-20 17:15:47 +08:00
Soulter
70cfdd2f8b feat(chat): refactor chat component structure and add new features (#3701)
- Introduced `ConversationSidebar.vue` for improved conversation management and sidebar functionality.
- Enhanced `MessageList.vue` to handle loading states and improved message rendering.
- Created new composables: `useConversations`, `useMessages`, `useMediaHandling`, `useRecording` for better code organization and reusability.
- Added loading indicators and improved user experience during message processing.
- Ensured backward compatibility and maintained existing functionalities.
2025-11-20 17:15:04 +08:00
Soulter
bdbd2f009a delete: useConversations 2025-11-20 17:11:01 +08:00
Soulter
164e0d26e0 feat(chat): refactor chat component structure and add new features (#3701)
- Introduced `ConversationSidebar.vue` for improved conversation management and sidebar functionality.
- Enhanced `MessageList.vue` to handle loading states and improved message rendering.
- Created new composables: `useConversations`, `useMessages`, `useMediaHandling`, `useRecording` for better code organization and reusability.
- Added loading indicators and improved user experience during message processing.
- Ensured backward compatibility and maintained existing functionalities.
2025-11-20 17:10:36 +08:00
Soulter
cb087b5ff9 refactor: update timestamp handling in session management and chat components 2025-11-20 17:02:01 +08:00
Soulter
1d3928d145 refactor(sqlite): remove auto-generation of session_id in insert method 2025-11-20 16:33:57 +08:00
Soulter
6dc3d161e7 feat(chat): refactor chat component structure and add new features (#3701)
- Introduced `ConversationSidebar.vue` for improved conversation management and sidebar functionality.
- Enhanced `MessageList.vue` to handle loading states and improved message rendering.
- Created new composables: `useConversations`, `useMessages`, `useMediaHandling`, `useRecording` for better code organization and reusability.
- Added loading indicators and improved user experience during message processing.
- Ensured backward compatibility and maintained existing functionalities.
2025-11-20 16:30:05 +08:00
Soulter
e9805ba205 fix: anyio.ClosedResourceError when calling mcp tools (#3700)
* fix: anyio.ClosedResourceError when calling mcp tools

added reconnect mechanism

fixes: 3676

* fix(mcp_client): implement thread-safe reconnection using asyncio.Lock
2025-11-20 16:24:02 +08:00
Dt8333
d5280dcd88 fix(core.platform): 修复启用多个企业微信智能机器人适配器时消息混乱的问题 (#3693)
* fix(core.platform): 修复启用多个企业微信智能机器人适配器时消息混乱的问题

移除了全局的消息队列,改为每个适配器处理自己的队列。修改相关方法适应该更改。

#3673

* chore: apply suggestions from code review

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

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-11-20 16:24:02 +08:00
Dt8333
67a9663eff fix(dashboard.i18n): complete the missing i18n keys(#3699)
#3679
2025-11-20 16:24:02 +08:00
Soulter
77dd89b8eb feat: add supports for gemini-3 series thought signature (#3698)
* feat: add supports for gemini-3 series thought signature

* feat: refactor tools_call_extra_content to use a dictionary for better structure
2025-11-20 16:24:02 +08:00
Soulter
8e511bf14b fix: build docker ci failed 2025-11-20 16:24:02 +08:00
Soulter
164a4226ea feat(chat): refactor chat component structure and add new features (#3701)
- Introduced `ConversationSidebar.vue` for improved conversation management and sidebar functionality.
- Enhanced `MessageList.vue` to handle loading states and improved message rendering.
- Created new composables: `useConversations`, `useMessages`, `useMediaHandling`, `useRecording` for better code organization and reusability.
- Added loading indicators and improved user experience during message processing.
- Ensured backward compatibility and maintained existing functionalities.
2025-11-20 16:07:09 +08:00
Soulter
6d6fefc435 fix: anyio.ClosedResourceError when calling mcp tools (#3700)
* fix: anyio.ClosedResourceError when calling mcp tools

added reconnect mechanism

fixes: 3676

* fix(mcp_client): implement thread-safe reconnection using asyncio.Lock
2025-11-20 16:01:22 +08:00
Soulter
aa59532287 refactor: implement migration for WebChat sessions by creating PlatformSession records from platform_message_history 2025-11-20 15:58:27 +08:00
piexian
2ada1deb9a 修复文档返回读取问题 2025-11-20 08:31:50 +08:00
piexian
788ceb9721 添加阿里百炼重排序模型 2025-11-20 08:05:42 +08:00
Dt8333
8488c9aeab fix(core.platform): 修复启用多个企业微信智能机器人适配器时消息混乱的问题 (#3693)
* fix(core.platform): 修复启用多个企业微信智能机器人适配器时消息混乱的问题

移除了全局的消息队列,改为每个适配器处理自己的队列。修改相关方法适应该更改。

#3673

* chore: apply suggestions from code review

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

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-11-19 21:44:38 +08:00
Dt8333
676f9fd4ff fix(dashboard.i18n): complete the missing i18n keys(#3699)
#3679
2025-11-19 21:36:34 +08:00
Soulter
1935ce4700 refactor: update session handling by replacing conversation_id with session_id in chat routes and components 2025-11-19 19:54:29 +08:00
Soulter
e760956353 refactor: enhance PlatformSession migration by adding display_name from Conversations and improve session item styling 2025-11-19 19:41:57 +08:00
Soulter
be3e5f3f8b refactor: update message history deletion logic to remove newer records based on offset 2025-11-19 19:41:25 +08:00
Soulter
cdf617feac refactor: optimize WebChat session migration by batch inserting records 2025-11-19 19:16:15 +08:00
Soulter
afb56cf707 feat: add supports for gemini-3 series thought signature (#3698)
* feat: add supports for gemini-3 series thought signature

* feat: refactor tools_call_extra_content to use a dictionary for better structure
2025-11-19 18:54:56 +08:00
Soulter
cd2556ab94 fix: build docker ci failed 2025-11-19 15:40:41 +08:00
Soulter
cf4a5d9ea4 refactor: change to platform session 2025-11-18 22:37:55 +08:00
Soulter
0747099cac fix: restore migration check for version 4.7 2025-11-18 22:07:43 +08:00
Soulter
323ec29b02 refactor: Implement WebChat session management and migration from version 4.6 to 4.7
- Added WebChatSession model for managing user sessions.
- Introduced methods for creating, retrieving, updating, and deleting WebChat sessions in the database.
- Updated core lifecycle to include migration from version 4.6 to 4.7, creating WebChat sessions from existing platform message history.
- Refactored chat routes to support new session-based architecture, replacing conversation-related endpoints with session endpoints.
- Updated frontend components to handle sessions instead of conversations, including session creation and management.
2025-11-18 22:04:26 +08:00
magisk317
ae81d70685 ci(docker-build): build nightly image everyday (#3120)
* ci: build test image on master pushes

* ci: split workflows for master test and release builds

* test ci

* test ci

* Update docker-image.yml

* test ci

Updated README to enhance deployment instructions.

* Make GHCR publishing optional in Docker workflow

* chore: Update DockerHub password secret in workflow

* Update .github/workflows/docker-image.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* chore: rename job to build nightly image in workflow

* feat: schedule the nightly build at 0:00 am everyday, if have new commits

* fix: update build-nightly-image job to trigger only on schedule events

* Update fetch-depth and enable fetch-tag in workflows

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-11-18 10:47:58 +08:00
RC-CHN
270c89c12f feat: Add URL document parser for knowledge base (#3622)
* feat: 添加从 URL 上传文档的功能,支持进度回调和错误处理

* feat: 添加从 URL 上传文档的前端

* chore: 添加 URL 上传功能的警告提示,确保用户配置正确

* feat: 添加内容清洗功能,支持从 URL 上传文档时的清洗设置和服务提供商选择

* feat: 更新内容清洗系统提示,增强信息提取规则;添加 URL 上传功能的测试版标识

* style: format code

* perf: 优化上传设置,增强 URL 上传时的禁用逻辑和清洗提供商验证

* refactor:使用自带chunking模块

* refactor: 提取prompt到单独文件

* feat: 添加 Tavily API Key 配置对话框,增强网页搜索功能的配置体验

* fix: update URL hint and warning messages for clarity in knowledge base upload settings

* fix: 修复设置tavily_key的热重载问题

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-11-17 19:05:14 +08:00
Soulter
c7a58252fe feat: supports knowledge base agentic search (#3667)
* feat: supports knowledge base agentic search

* fix: correct formatting of system prompt in knowledge base results
2025-11-17 17:29:18 +08:00
Soulter
47ad8c86e5 docs: update translations of README 2025-11-17 12:50:01 +08:00
Soulter
937e879e5e chore: revise the issue template
Updated the bug report template to include English translations for all fields and improved clarity.
2025-11-17 11:35:24 +08:00
Soulter
1ecf26eead chore: revice pr template
Removed unnecessary comments and streamlined the pull request template.
2025-11-17 11:27:48 +08:00
Soulter
adbb84530a chore: bump version to 4.5.8 2025-11-17 09:58:02 +08:00
piexian
6cf169f4f2 fix: ImageURLPart typo (#3665)
* 修复新版本更新对不上格式的问题

entities.py生成的格式:{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}
ImageURLPart期望的格式:{"type": "image_url", "image_url": "data:image/jpeg;base64,..."}

* Revert "修复新版本更新对不上格式的问题"

This reverts commit 28b4791391.

* fix(core.agent): 修复ImageURLPart的声明,修复pydantic校验失败的问题。

---------

Co-authored-by: piexian <piexian@users.noreply.github.com>
Co-authored-by: Dt8333 <lb0016@foxmail.com>
2025-11-17 09:52:31 +08:00
Soulter
5ab9ea12c0 chore: bump verstion to 4.5.7 2025-11-16 14:01:25 +08:00
Soulter
fd9cb703db refactor: update ToolSet initialization to use Pydantic Field and clean up deprecated methods in Context 2025-11-16 12:13:11 +08:00
Soulter
388c1ab16d fix: ensure parameter properties are correctly handled in spec_to_func 2025-11-16 11:50:58 +08:00
Soulter
f867c2a271 feat: enhance parameter type handling in LLM tool registration with JSON schema support (#3655)
* feat: enhance parameter type handling in LLM tool registration with JSON schema support

* refactor: remove debug print statement from FunctionToolManager
2025-11-16 00:55:40 +08:00
Soulter
605bb2cb90 refactor: disable debug logging for chunk delta in OpenAI provider 2025-11-15 22:29:06 +08:00
Soulter
5ea15dde5a feat: enhance LLM handsoff tool execution with system prompt and run hooks 2025-11-15 22:26:13 +08:00
Soulter
3ca545c4c7 Merge pull request #3636 from AstrBotDevs/feat/context-llm-capability
refactor: better invoke the LLM / Agent capabilities
2025-11-15 21:41:42 +08:00
Soulter
e200835074 refactor: remove unused Message import and context_model initialization in LLMRequestSubStage 2025-11-15 21:36:54 +08:00
Soulter
3a90348353 Merge branch 'master' into feat/context-llm-capability 2025-11-15 21:34:54 +08:00
Soulter
5a11d8f0ee refactor: LLM response handling with reasoning content (#3632)
* refactor: LLM response handling with reasoning content

- Added a `show_reasoning` parameter to `run_agent` to control the display of reasoning content.
- Updated `LLMResponse` to include a `reasoning_content` field for storing reasoning text.
- Modified `WebChatMessageEvent` to handle and send reasoning content in streaming responses.
- Implemented reasoning extraction in various provider sources (e.g., OpenAI, Gemini).
- Updated the chat interface to display reasoning content in a collapsible format.
- Removed the deprecated `thinking_filter` package and its associated logic.
- Updated localization files to include new reasoning-related strings.

* feat: add Groq chat completion provider and associated configurations

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

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

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-11-15 21:31:03 +08:00
Soulter
824af5eeea fix: Provider.meta() error (#3647)
fixes: #3643
2025-11-15 21:30:05 +08:00
Dt8333
08ec787491 fix(core.platform): make DingTalk user-ID compliant with UMO (#3634) 2025-11-15 21:30:05 +08:00
Soulter
b062e83d54 refactor: remove redundant session lock management from message sending logic in RespondStage (#3645)
fixes: #3644

Co-authored-by: Dt8333 <lb0016@foxmail.com>
2025-11-15 21:30:05 +08:00
Soulter
17422ba9c3 feat: introduce messages field in agent RunContext 2025-11-15 21:15:20 +08:00
Soulter
6849af2bad refactor: LLM response handling with reasoning content (#3632)
* refactor: LLM response handling with reasoning content

- Added a `show_reasoning` parameter to `run_agent` to control the display of reasoning content.
- Updated `LLMResponse` to include a `reasoning_content` field for storing reasoning text.
- Modified `WebChatMessageEvent` to handle and send reasoning content in streaming responses.
- Implemented reasoning extraction in various provider sources (e.g., OpenAI, Gemini).
- Updated the chat interface to display reasoning content in a collapsible format.
- Removed the deprecated `thinking_filter` package and its associated logic.
- Updated localization files to include new reasoning-related strings.

* feat: add Groq chat completion provider and associated configurations

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

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

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-11-15 18:59:17 +08:00
Soulter
09c3da64f9 fix: Provider.meta() error (#3647)
fixes: #3643
2025-11-15 18:01:51 +08:00
Dt8333
2c8470e8ac fix(core.platform): make DingTalk user-ID compliant with UMO (#3634) 2025-11-15 17:31:03 +08:00
Soulter
c4ea3db73d refactor: remove redundant session lock management from message sending logic in RespondStage (#3645)
fixes: #3644

Co-authored-by: Dt8333 <lb0016@foxmail.com>
2025-11-15 16:39:49 +08:00
Soulter
89e79863f6 fix: ensure image_urls and system_prompt default to empty values in ProviderRequest 2025-11-14 22:45:55 +08:00
Soulter
d19945009f refactor: decople the agent impl part and introduce some helper context method to call llm 2025-11-14 19:17:24 +08:00
Soulter
c77256ee0e feat: add id field to ProviderMetaData and update provider manager to set provider ID 2025-11-14 12:35:30 +08:00
Soulter
7d823af627 refactor: update provider metadata handling and enhance ProviderMetaData structure 2025-11-13 19:53:23 +08:00
Soulter
3957861878 refactor: streamline llm processing logic (#3607)
* refactor: streamline llm processing logic

* perf: merge-nested-ifs

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

* fix: ruff format

* refactor: remove unnecessary debug logs in FunctionToolExecutor and LLMRequestSubStage

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-11-13 10:08:57 +08:00
Dt8333
6ac43c600e perf: improve streaming fallback strategy for streaming-unsupported platform (#3547)
* feat: 修改tool_loop_agent_runner,新增stream_to_general属性。

Co-authored-by: aider (openai/gemini-2.5-flash-preview) <aider@aider.chat>

* refactor: 优化text_chat_stream,直接yield完整信息

Co-authored-by: aider (openai/gemini-2.5-flash-preview) <aider@aider.chat>

* feat(core):  添加streaming_fallback选项,允许进行流式请求和非流式输出

添加了streaming_fallback配置,默认为false。在PlatformMetadata中新增字段用于标识是否支持真流式输出。在LLMRequest中添加判断是否启用Fallback。

#3431 #2793 #3014

* refactor(core): 将stream_to_general移出toolLoopAgentRunner

* refactor(core.platform): 修改metadata中的属性名称

* fix: update streaming provider settings descriptions and add conditions

* fix: update streaming configuration to use unsupported_streaming_strategy and adjust related logic

* fix: remove support_streaming_message flag from WecomAIBotAdapter registration

* fix: update hint for non-streaming platform handling in configuration

* fix(core.pipeline): Update astrbot/core/pipeline/process_stage/method/llm_request.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(core.pipeline): Update astrbot/core/pipeline/process_stage/method/llm_request.py

---------

Co-authored-by: aider (openai/gemini-2.5-flash-preview) <aider@aider.chat>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-12 18:01:20 +08:00
RC-CHN
27af9ebb6b feat: changelog display improvement
* feat: 添加旧版本changelog的modal

* style: 调整发布说明对话框的样式,移除背景颜色
2025-11-12 14:54:03 +08:00
Soulter
b360c8446e feat: add default model selection chip in provider model selector 2025-11-10 13:04:28 +08:00
Soulter
6d00717655 feat: add streaming support with toggle in chat interface and adjust layout for mobile 2025-11-09 21:57:30 +08:00
Soulter
bb5f06498e perf: refine login page 2025-11-09 20:57:45 +08:00
Dt8333
aca5743ab6 feat: 为部分适配器添加缺失的 send_streaming 方法 (#3545)
为Wechatpadpro和discord添加缺失的方法。
2025-11-09 16:00:24 +08:00
Soulter
6903032f7e fix: improve knowledge base chip display with truncation and styling (#3582)
fixes: #3546
2025-11-09 15:30:41 +08:00
nazo
1ce0ff87bd feat: supports to add custom headers for openai providers (#3581)
* feat: OPENAI系支持自定义添加请求头

* chore: add custom headers and extra body to config for zhipu

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
2025-11-09 15:12:52 +08:00
Soulter
e39d6bae0b fix: update JSON submission link in plugin publish template 2025-11-09 15:06:40 +08:00
Raven95676
8028e9e9a6 chore: bump version to 4.5.6 2025-11-07 16:20:19 +08:00
Raven95676
817f20ea01 fix: pyproject 2025-11-07 16:18:42 +08:00
Raven95676
ad5579a2f4 chore: bump version to 4.5.5 2025-11-07 15:52:58 +08:00
Raven95676
81a689a79b fix: typo 2025-11-07 15:41:14 +08:00
Raven95676
1893dd8336 fix: dockefile 2025-11-07 15:41:03 +08:00
Soulter
021ca8175b chore: bump version to 4.5.4 2025-11-07 14:28:51 +08:00
Soulter
39d6207fe1 chore: remove dynamic version 2025-11-07 14:26:56 +08:00
Soulter
23ce687229 chore: fix dockerfile 2025-11-07 14:23:49 +08:00
鸦羽
3715312fd2 fix: update project description to English (#3516) 2025-11-07 01:13:32 +08:00
Soulter
8196922cac docs: simplify README 2025-11-06 15:22:43 +08:00
Soulter
8089ad91da perf: improve extension market ui 2025-11-06 13:57:46 +08:00
Soulter
2930cc3fd8 chore: bump version to 4.5.3 2025-11-05 21:21:14 +08:00
Soulter
0e841a8b25 fix: correct tools dictionary comprehension in get_tool_list method 2025-11-05 21:19:10 +08:00
Soulter
67fa1611cc chore: bump version to 4.5.2 2025-11-05 19:02:51 +08:00
Soulter
91136bb9f7 fix: llm tool register error (#3493) 2025-11-05 14:27:37 +08:00
Copilot
7c050d1adc feat: add customizable sidebar module ordering (#3307)
* Initial plan

* Add sidebar customization feature with drag-and-drop support

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

* Add dist/ to .gitignore to exclude build artifacts

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

* Fix memory leak and improve code quality per code review

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

* Fix i18n key format: use dot notation instead of colon notation

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

* Fix drag-and-drop to empty list issue

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>
2025-11-04 23:59:45 +08:00
Misaka Mikoto
a0690a6afc feat: support options to delete plugins config and data (#3280)
* - 为插件管理页面中,删除插件提供一致的二次确认(原本只有卡片视图有二次确认)
- 二次确认时可选删除插件配置和持久化数据
- 添加对应的i18n支持

* ruff

* 移除未使用的
const $confirm = inject('$confirm');
2025-11-04 11:48:48 +08:00
Dt8333
c51609b261 fix: typing error (#3267)
* fix: 修复一些小错误。

修复aiocqhttp和slack中部分逻辑缺失的await。修复discord中错误的异常捕获类型。

* fix(core.platform): 修复discord适配器中错误的message_chain赋值

* fix(aiocqhttp): 更新convert_message方法的返回类型为AstrBotMessage | None

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-11-03 23:38:52 +08:00
Soulter
72148f66eb chore: nodejs in Dockerfile 2025-11-03 13:19:51 +08:00
Copilot
a04993a2bb Replace insecure random with secrets module in cryptographic contexts (#3248)
* Initial plan

* Security fixes: Replace insecure random with secrets module and improve SSL context

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

* Address code review feedback: fix POST method and add named constants

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

* Improve documentation for random number generation constants

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

* Update astrbot/core/utils/io.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/platform/sources/wecom_ai_bot/WXBizJsonMsgCrypt.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update tests/test_security_fixes.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/utils/io.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/utils/io.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix: Handle path parameter in SSL fallback for download_image_by_url

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>
Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-03 02:43:00 +08:00
LIghtJUNction
74f845b06d Chore: Dockerfile (#3266)
* fix: Dockerfile

python main.py 改为uv run main.py

* fix(dockerfile): 减少重复安装

* fix: 修复一些细节问题

* fix(.dockerignore): 需要git文件夹以获取astrbot版本(带git commit hash后缀)

* fix(.dockerignore): uv run之前会uv sync
2025-11-03 02:41:40 +08:00
Soulter
50144ddcae refactor: revise LLM message schema and fix the reload logic when using dataclass-based LLM Tool registration (#3234)
* refactor: llm message schema

* feat: implement MCPTool and local LLM tools with enhanced context handling

* refactor: reorganize imports and enhance docstrings for clarity

* refactor: enhance ContentPart validation and add message pair handling in ConversationManager

* chore: ruff format

* refactor: remove debug print statement from payloads in ProviderOpenAIOfficial

* Update astrbot/core/agent/tool.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/agent/message.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/agent/message.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/agent/tool.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/pipeline/process_stage/method/llm_request.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/agent/message.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* refactor: enhance documentation and import mcp in tool.py; update call method return type

* fix: 修复以数据类的方式注册 tool 时的插件重载机制问题

* refactor: change role attributes to use Literal types for message segments

* fix: add support for 'decorator_handler' method in call_local_llm_tool

* fix: handle None prompt in text_chat method and ensure context is properly formatted

---------

Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-02 18:12:20 +08:00
Copilot
94bf3b8195 Fix incorrect type annotations and errors (#3250)
* Initial plan

* Fix type annotation errors in cmd_conf, cmd_init, and version_comparator

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

* Changes before error encountered

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

* Fix more type annotation errors: change `= None` to `| None = None`

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

* Fix final batch of type annotation errors

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>
Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
2025-11-02 17:02:56 +08:00
Copilot
e190bbeeed Optimize string concatenation in loops: replace += with list.join() (#3246)
* Initial plan

* Fix string concatenation performance issues in loops

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

* Address code review feedback: Fix plugin list logic and add comment

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

* Improve comment clarity for at_parts accumulation

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>
2025-11-02 13:00:59 +08:00
Copilot
92abc43c9d Fix mutable default arguments in constructors and methods (#3247)
* Initial plan

* Fix mutable default arguments in constructors and methods

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>
2025-11-02 12:57:37 +08:00
Copilot
c8e34ff26f [WIP] Translate mixed English comments to Chinese (#3256)
* Initial plan

* Changes before error encountered

Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>
2025-11-02 12:52:46 +08:00
Soulter
630df3e76e refactor: reorganize ComponentType definitions and remove unused classes 2025-11-01 23:18:40 +08:00
Raven95676
bdbf382201 chore: remove astrbot.lock 2025-11-01 17:43:54 +08:00
Raven95676
00eefc82db chore(.gitignore): update ignore rule 2025-11-01 17:41:02 +08:00
LIghtJUNction
dc97080837 Update .gitignore 2025-11-01 17:37:57 +08:00
LIghtJUNction
0b7fc29ac4 style: add ruff lint module of isort and pyupgrade, and some ruff check fix (#3214)
Co-authored-by: Dt8333 <25431943+Dt8333@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-11-01 13:26:19 +08:00
Soulter
ff998fdd8d chore: bump version to 4.5.1 2025-10-31 23:55:40 +08:00
LIghtJUNction
d7461ed54c fix(helper.py): 修复了迁移逻辑,现在不再误判 (#3215)
* fix(helper.py): 修复了迁移逻辑,现在不再误判

* fix(helper.py): 没有data_v3 dir
2025-10-31 23:37:37 +08:00
Soulter
3ce577acf9 docs: enhance bug report template with clarity on details
Updated bug report template to emphasize the need for detailed logs and information.
2025-10-31 23:18:15 +08:00
Chris
50b1dccff3 feat: support xAI Grok Live Search config (#3203)
* Add xai_native_search configuration option

* Implement xAI compatibility and search injection

Add support for xAI integration with search parameters injection.

* Refactor xAI handling in openai_source.py

Removed the _is_xai method and updated xAI search injection logic.

* Fix formatting of condition in default.py

* Fix formatting in openai_source.py
2025-10-31 21:48:45 +08:00
Dt8333
c33e7e30d4 chore(requirements): Sync dependencies from pyproject to requirements.txt (#3208)
* chore(requirements): 将pyproject中的dependency同步到requirements.txt

* chore(requirements): 补全遗漏dependency
2025-10-31 15:27:16 +08:00
RC-CHN
bc7f01ba36 feat: add Xinference STT provider (#3197)
* feat: add Xinference STT provider

* chore:update comment in xinference_stt_provider

* style: ruff format xinference_stt_provider

* chore: remove unused import of base64 in xinference_stt_provider

* fix: enhance model initialization check in get_text method

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-10-31 01:49:35 +08:00
再吃颗电池吧
2ce653caad perf: modify the at logic in the DingTalk adapter (#3186)
* feat 初次提交

* fix: Modify the At logic in the DingTalk adapter.

* del uv.lock

* 添加at_users为空判断

* 优化钉钉at的处理逻辑,不用重复判断机器人是否is_in_at_list

* fix: refine handling of mentioned users in group messages

---------

Co-authored-by: linyiming <linyiming@example.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-10-30 14:15:01 +08:00
Soulter
0d850d7b22 fix: refine docstring for add_llm_tools method in Context class 2025-10-29 20:16:27 +08:00
Soulter
a2be155b8e feat: add method to register LLM tools in Context class 2025-10-29 20:13:15 +08:00
Soulter
68aa107689 docs: update readme 2025-10-29 13:58:58 +08:00
Soulter
23096ed3a5 perf: update extension card page style, add config and view-docs button 2025-10-29 00:38:04 +08:00
RC-CHN
90a65c35c1 feat: add Xinference rerank provider (#3162)
* feat:add Xinference rerank provider

* feat:add default rerank_api_key option for Xinference provider

* style: format code

* fix: refactor XinferenceRerankProvider initialization for better error handling

* fix: update XinferenceRerankProvider to use async client methods for initialization and reranking

* feat: add launch_model_if_not_running option to XinferenceRerankProvider for better control over model initialization

* chore: remove unused asyncio import from xinference_rerank_source.py
2025-10-28 18:23:55 +08:00
a490077
3d88827a95 fix: qq_official_webhook is_sandbox field error (#3167)
* QQ官方机器人增加沙箱模式选项,让本地部署能跳过IP白名单验证

* chore: ruff format

* 修复沙盒配置为字符串判断

* 由于配置类型为字符串,修复为字符串判断

* chore: ruff format

* fix: update is_sandbox configuration to use boolean type

---------

Co-authored-by: 郭鹏 <gp@pp052.top>
Co-authored-by: Soulter <905617992@qq.com>
Co-authored-by: Dt8333 <lb0016@foxmail.com>
2025-10-28 10:15:46 +08:00
Futureppo
40a0a8df5a perf: 优化 /model 切换模型成功的提示 (#3161) 2025-10-28 09:05:42 +08:00
dependabot[bot]
20f7129c0b chore(deps): bump actions/upload-artifact in the github-actions group (#3178)
Bumps the github-actions group with 1 update: [actions/upload-artifact](https://github.com/actions/upload-artifact).


Updates `actions/upload-artifact` from 4 to 5
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-28 08:53:28 +08:00
Soulter
0e962e95dd docs: update plugin information template in YAML 2025-10-27 14:26:59 +08:00
Soulter
07ba9c772c chore: bump version to 4.5.0 2025-10-26 21:40:11 +08:00
Soulter
0622d88b22 fix: revert 3106 (#3153)
* fix: revert 3106

Co-authored-by: Dt8333 <25431943+Dt8333@users.noreply.github.com>
Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
Co-authored-by: exynos <110159911+xiaoxi68@users.noreply.github.com>

* Update astrbot/dashboard/routes/update.py

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

* fix: remove unnecessary version file handling in download_dashboard function

* fix: revert

---------

Co-authored-by: Dt8333 <25431943+Dt8333@users.noreply.github.com>
Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
Co-authored-by: exynos <110159911+xiaoxi68@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-10-26 21:26:48 +08:00
Soulter
594f0fed55 style: adjust padding for card text in ExtensionPage for improved layout 2025-10-26 21:19:07 +08:00
Soulter
04b0d9b88d Merge pull request #3155 from AstrBotDevs/feat/plugin-display-name-and-logo
feat: add support for plugin display name and logo, and some extension card style fix
2025-10-26 20:54:24 +08:00
Soulter
1f2af8ef94 Update dashboard/src/components/shared/ExtensionCard.vue
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-10-26 20:52:37 +08:00
Soulter
598ea2d857 refactor: update ExtensionCard styling and improve layout for better responsiveness 2025-10-26 20:49:27 +08:00
Soulter
6dd9bbb516 feat: enhance plugin metadata with display name and logo support 2025-10-26 20:30:54 +08:00
Soulter
3cd0b47dc6 feat: add GitHub link button to ExtensionCard for extensions with a repository 2025-10-26 19:41:00 +08:00
Soulter
65c71b5f20 refactor: remove Google search engine integration from main module and dependencies (#3154) 2025-10-26 18:54:01 +08:00
exynos
1152b11202 feat(thinking_filter): 适配第三方 Gemini 思考片段过滤 (#3139)
* feat(thinking_filter): 适配第三方 Gemini 思考片段过滤

* feat(thinking_filter): Gemini 思考过滤、序列化回退与空白清理重构

* 使用 ruff 格式化并修复导入空行
2025-10-26 18:43:58 +08:00
Soulter
51246ea31b fix: apply configuration option to enable/disable WebUI in AstrBotDashboard (#3152) 2025-10-26 17:29:04 +08:00
Soulter
7e5592dd32 fix: comment out existing configuration preview section in AddNewPlatform component 2025-10-26 17:07:04 +08:00
Soulter
c6b28caebf Merge pull request #3151 from AstrBotDevs/feat/platform-abconf-interaction
feat: enhance AddNewPlatform and ConfigPage components with improved configuration management and UI interactions
2025-10-26 17:04:34 +08:00
Soulter
ca002f6fff feat: enhance AddNewPlatform dialog with scroll functionality and toggle for configuration section 2025-10-26 17:03:07 +08:00
Soulter
14ec392091 fix: update message styling in AddNewPlatform component for better visibility 2025-10-26 17:00:36 +08:00
Soulter
5e2eb91ac0 feat: enhance AddNewPlatform and ConfigPage components with improved configuration management and UI interactions 2025-10-26 16:57:01 +08:00
Soulter
c1626613ce fix: update repository references from Soulter/AstrBot to AstrBotDevs/AstrBot across documentation and codebase (#3150)
* fix: update repository references from Soulter/AstrBot to AstrBotDevs/AstrBot across documentation and codebase

- Updated README_ja.md to reflect new GitHub repository links.
- Modified AstrBotUpdator to download from the new repository.
- Changed download URLs in io.py for dashboard releases.
- Updated changelogs to point to the new issue links.
- Adjusted Docker compose file to reference the new repository.
- Updated Vue components in the dashboard to link to the new repository.
- Changed main.py to provide the correct download instructions for the new repository.

* fix: improve error handling for configId selection in AddNewPlatform component

* Update astrbot/core/utils/io.py

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

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-10-26 16:17:24 +08:00
LIghtJUNction
42042d9e73 Merge branch 'master' of https://github.com/AstrBotDevs/AstrBot 2025-10-26 15:41:36 +08:00
LIghtJUNction
22c3b53ab8 fix(io.py): path改回传入文件地址,而不是传入文件夹地址 2025-10-26 15:41:20 +08:00
Soulter
090c32c90e feat: enhance AddNewPlatform dialog with data preparation on enter and improve code formatting 2025-10-26 15:40:15 +08:00
LIghtJUNction
4f4a9b9e55 fix(io.py): download_dashboard如果发现没有dist/assets/version文件,下载完毕自动写入(以防万一) 2025-10-26 15:35:25 +08:00
Soulter
6c7d7c9015 Merge pull request #3147 from AstrBotDevs/feat/kb-markitdown
feat: refactor knowledge base parsers and add MarkitdownParser for docx, xls, xlsx support
2025-10-26 13:18:52 +08:00
Soulter
562e62a8c0 feat: add new dependencies for PDF processing, file handling, and text ranking 2025-10-26 13:02:32 +08:00
Soulter
0823f7aa48 在检查字面量集合的成员资格时使用 set
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-10-25 22:04:17 +08:00
Soulter
eb201c0420 feat: refactor knowledge base parsers and add MarkitdownParser for docx, xls, xlsx support 2025-10-25 22:00:54 +08:00
Soulter
6cfed9a39d Merge pull request #3143 from lxfight/feature/knowledge-base 2025-10-25 18:19:15 +08:00
Soulter
33618c4a6b feat: add dynamic embedding dimension retrieval for providers and enhance error handling 2025-10-25 16:39:11 +08:00
LI SONGSONG 🍂
ace0a7c219 docs: update link and description 2025-10-25 16:07:27 +08:00
Soulter
f7d018cf94 feat: add pre-checks for embedding and rerank providers in KnowledgeBaseRoute 2025-10-25 15:22:35 +08:00
Soulter
8ae2a556e4 feat: remove tips from knowledge base creation form and add persistent hints for field modifications 2025-10-25 15:06:07 +08:00
lxfight
4188deb386 fix: 简化日志错误信息格式 2025-10-25 14:13:23 +08:00
lxfight
82cf4ed909 fix: 使用ruff格式化文件代码 2025-10-25 14:10:26 +08:00
lxfight
88fc437abc feat: 优化知识库选择界面,添加自定义滚动条样式 2025-10-25 13:59:09 +08:00
lxfight
57f868cab1 Merge branch 'feature/knowledge-base' of https://github.com/lxfight/AstrBot into feature/knowledge-base 2025-10-25 13:53:03 +08:00
lxfight
6cb5527894 feat: 添加会话知识库配置的 API 接口,支持获取、设置和删除会话配置,优化知识库选择界面 2025-10-25 13:52:57 +08:00
Soulter
016783a1e5 feat: implement RecursiveCharacterChunker and update KnowledgeBaseManager to use it 2025-10-25 13:46:06 +08:00
lxfight
594ccff9c8 fix: 添加数据库连接检查和知识库终止功能,增强错误处理和清理逻辑,修复知识库无法删除的问题 2025-10-25 11:56:37 +08:00
Soulter
30792f0584 Merge pull request #114 from lxfight/lwl-dev/knowledge-base
refactor: 知识库优化
2025-10-25 00:42:16 +08:00
Soulter
8f021eb35a feat: refactor document storage to use SQLModel and enhance database operations 2025-10-24 23:17:37 +08:00
Soulter
1969abc340 feat: add route for legacy knowledge base and update UI with banner suggestion 2025-10-24 22:01:55 +08:00
Soulter
b1b53ab983 Merge remote-tracking branch 'origin/master' into lwl-dev/knowledge-base 2025-10-24 21:48:47 +08:00
Soulter
9b5af23982 feat: remove beta label from knowledge base navigation and adjust margin in KBList component 2025-10-24 21:46:53 +08:00
Soulter
4cedc6d3c8 feat: add t-SNE visualization for FAISS index and enhance knowledge base retrieval with debug mode 2025-10-24 21:22:46 +08:00
Soulter
4e9cce76da feat: add timing logs for dense and sparse retrieval processes and adjust top K results in sparse retriever 2025-10-24 17:51:30 +08:00
Soulter
9b004f3d2f feat: update document retrieval to include limit and offset parameters 2025-10-24 17:38:22 +08:00
Soulter
9430e3090d feat: add progress callback for document upload and enhance upload progress tracking 2025-10-24 17:13:44 +08:00
Soulter
ba44f9117b feat: enhance document upload process with batch settings and improved chunk handling 2025-10-24 16:37:37 +08:00
Soulter
eb56710a72 feat: add chunk size, overlap, and top K parameters to knowledge base response 2025-10-24 15:10:47 +08:00
Soulter
38e3f27899 feat: update knowledge base retrieval configuration and UI adjustments 2025-10-24 15:06:07 +08:00
Soulter
3c58d96db5 feat: add configuration for final knowledge base retrieval count and update related components 2025-10-24 14:45:07 +08:00
Soulter
a6be0cc135 feat: refresh knowledge base and document after uploading a document 2025-10-24 14:28:27 +08:00
Soulter
a53510bc41 refactor: comment out file path handling in KBHelper and search input in DocumentDetail 2025-10-24 14:27:01 +08:00
Soulter
1fd482e899 feat: update chunk deletion to include document ID and refresh metadata 2025-10-24 14:18:32 +08:00
Soulter
2f130ba009 feat: delete chunk and delete document 2025-10-24 13:59:17 +08:00
Soulter
e6d9db9395 feat: disable embedding provider selection in settings tab 2025-10-24 12:53:59 +08:00
Soulter
e0ac743cdb perf: remove rerank functionality from settings tab and related form data 2025-10-24 12:13:51 +08:00
Soulter
b0d3fc11f0 feat: remove sessions tab and related components from knowledge base detail view 2025-10-24 00:48:17 +08:00
Soulter
7e0a50fbf2 feat: enhance knowledge base retrieval with chunk metadata and pagination support; remove unused chunk model 2025-10-24 00:44:40 +08:00
Soulter
59df244173 improve 2025-10-23 21:20:41 +08:00
Soulter
deb31a02cf docs: Update badge links in README.md 2025-10-23 09:53:54 +08:00
Soulter
e3aa1315ae stage 2025-10-23 00:31:15 +08:00
Soulter
65bc5efa19 feat: 集成知识库管理器,优化知识库上下文注入流程,移除冗余代码 2025-10-22 21:59:00 +08:00
Dt8333
abc4bc24b4 fix(dashboard): webchat input textarea is disabled when session controller is active
Removed the disable attribute of Input in isConvRunning. Added an activeSSE counter to correctly determine the current session state and prevent new input from causing interface display errors during session_waiter execution. Set isStreaming after streaming input ends to restore the text box.

#3037 #2892
2025-10-22 20:32:40 +08:00
Soulter
5df3f06f83 fix: persona information is not appearing in the PersonaForm when editing 2025-10-22 17:09:21 +08:00
Soulter
0e1de82bd7 fix: correct indentation in pre-commit config for pyupgrade hook 2025-10-22 17:08:54 +08:00
Soulter
f31e41b3f1 docs: update readme 2025-10-22 13:10:44 +08:00
Soulter
61a68477d0 stage 2025-10-21 14:19:38 +08:00
LIghtJUNction
fe8d2718c4 新增pyupgrade钩子
代码风格统一化
2025-10-21 11:17:20 +08:00
Soulter
8afefada0a fix: image_caption btn 2025-10-21 11:07:39 +08:00
LIghtJUNction
745e1c37c0 Add ruff-check hook to pre-commit config
跟随官方推荐
2025-10-21 11:07:00 +08:00
LIghtJUNction
fdb5988cec 更新 .pre-commit-config.yaml 2025-10-21 11:02:30 +08:00
Soulter
36ffcf3cc3 fix: typing error 2025-10-21 10:56:44 +08:00
Soulter
e74f626383 stage 2025-10-21 09:55:14 +08:00
Soulter
ef99f64291 feat(config): 添加 agent 运行器类型及相关配置支持 2025-10-21 00:47:04 +08:00
Soulter
a0f8f3ae32 style: ruff format 2025-10-21 00:21:42 +08:00
Soulter
130f52f315 chore(monaco-editor): bump monaco-editor version to 0.54.0 2025-10-21 00:18:29 +08:00
lxfight
a05868cc45 feat: 更新知识库管理器以支持重排序模型提供商,调整相关组件的默认配置和提示信息 2025-10-20 22:38:06 +08:00
lxfight
2fc77aed15 feat: 添加知识库检索功能,支持根据知识库 ID 列出相关会话;更新相关界面和国际化文本 2025-10-20 22:23:35 +08:00
lxfight
c56edb4da6 feat: 添加知识库配置功能,支持会话管理中的知识库选择与设置 2025-10-20 21:46:39 +08:00
Soulter
6672190760 feat: add star count display and fetch functionality in sidebar 2025-10-20 18:19:21 +08:00
exynos
f122b17097 fix(update): 取消 WebUI 与核心版本对比,消除“webui有新版本!”的误报 (#3106)
* fix(update): 取消 WebUI 与核心版本对比,消除“webui有新版本!”的误报

不再比较 dv 与核心版本

* fix(update): 保留dv逻辑,新增installed标识以避免误报

新增安装状态布尔值,保留“dv 是否存在”的信息

* Fix dashboard version update check logic

---------

Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
2025-10-20 16:15:42 +08:00
Soulter
2c5f68e696 refactor: 重构创建平台时的流程及一些 UI 优化 (#3102)
* refactor: 支持在平台直接选择配置文件

* add webchat

* feat: 支持新建平台时现场预览、创建和编辑配置文件

* fix: update configuration file descriptions and visibility based on updating mode

* perf: use incremental decoder

* perf: update descriptions

* fix: UI update issues in config file dialog

* fix: update UI elements for better readability and organization

* feat: enhance sidebar navigation with group feature and dynamic resizing

Co-authored-by:  IGCrystal <3811541171@qq.com>

* refactor: persona selector

* perf: 修改部分默认行为

* fix: adjust ExtensionCard layout and improve responsiveness

* refactor: 配置文件绑定消息平台重构为消息平台绑定配文件

* style: add custom styling for v-select selection text

* fix: correct subtitle text in provider.json

* refactor: update conversation management terminology and improve session ID handling

* refactor: add Conversation ID localization and update table header reference

* Update astrbot/core/db/migration/migra_45_to_46.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* style: format logger warning for better readability

* refactor: comment out WebChat configuration for future reference

---------

Co-authored-by: IGCrystal <3811541171@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-20 12:01:06 +08:00
MoonShadow1976
e1ca645a32 feat: 增强工具调用参数处理机制 (#3036)
* feat: 增强工具调用参数处理机制

在工具调用时添加参数过滤功能,只传递函数实际需要的参数
解决问题:https://github.com/AstrBotDevs/AstrBot/issues/2988

* feat: 利用现有工具定义信息处理非期望的参数

不使用`inspect`库,利用现有工具定义信息处理非期望的参数

* ruff format for code

合并结果:
移除了多余参数避免报错,代码执行器可以正常工作。
2025-10-20 02:51:16 +08:00
lxfight
333bf56ddc feat:知识库卡片渲染统计信息。 2025-10-19 22:40:01 +08:00
lxfight
b240594859 feat:添加Beta 版本的知识库管理器前端页面;添加i18n相关文件内容。 2025-10-19 21:55:21 +08:00
lxfight
beccae933f fix:修复KBSessionConfig的导入问题 2025-10-19 21:36:01 +08:00
lxfight
e6aa1d2c54 feat:删除v2版本的知识库前端代码;删除i18n相关文件 2025-10-19 21:16:00 +08:00
magisk317
5e808bab65 fix(platform): prevent 'NoneType' object is not iterable in _outline_chain and set_result (#3103)
Guard against cases where message chain is None during pipeline execution. This change enhances error-resilience for logging and processing message chains.

- Updated AstrMessageEvent._outline_chain to return an empty string when input chain is None
- Updated AstrMessageEvent.set_result to ensure result.chain is always at least an empty list

This prevents TypeError when result.chain or chain is unexpectedly None, improving pipeline stability when handling external plugins or corner cases.

Co-authored-by: engine-labs-app[bot] <140088366+engine-labs-app[bot]@users.noreply.github.com>
Co-authored-by: cto-new[bot] <140088366+cto-new[bot]@users.noreply.github.com>
2025-10-19 20:16:14 +08:00
Dt8333
361d78247b fix(core): 修复人格预设对话的重复注入 (#3088)
备份Context避免供应商适配器移除Context内字段导致将预设会话存入历史。深拷贝人格预设会话防止运行时被意外修改。

#3063
2025-10-19 20:13:57 +08:00
a490077
3550103e45 feat: QQ 官方机器人增加沙盒模式选项,让本地部署能跳过 IP 白名单验证 (#3087)
* QQ官方机器人增加沙箱模式选项,让本地部署能跳过IP白名单验证

* chore: ruff format

---------

Co-authored-by: 郭鹏 <gp@pp052.top>
Co-authored-by: Soulter <905617992@qq.com>
2025-10-19 20:09:08 +08:00
PaloMiku
8b0d4d4de4 feat: 优化 Misskey 适配器的通知和聊天消息处理,改进 @用户提及逻辑 (#3075) 2025-10-19 20:05:55 +08:00
shangxue
dc71c04b67 feat(satori): 添加对合并转发消息功能的支持 (#3050)
* Update satori_event.py

* Update satori_event.py

* Update satori_event.py

* Update satori_adapter.py

* style: format code for better readability in satori_adapter.py and satori_event.py

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-10-19 20:05:03 +08:00
lxfight
a0254ed817 refactor: 优化知识库管理器和数据库操作的代码格式 2025-10-19 19:36:26 +08:00
lxfight
2563ecf3c5 feat: 实现知识库前端组件和路由
- 实现知识库 V2 主页面和 4 个子面板组件
- 文档管理面板:支持上传、删除、查看文档分块
- 检索测试面板:支持测试知识库检索效果
- 全局设置面板:配置嵌入模型、重排序、检索参数
- 会话配置面板:管理会话与知识库的绑定关系
- 重构 Alkaid 路由为嵌套结构,添加知识库 V2 路由
- 在翻译系统中注册知识库 V2 多语言支持
- 默认进入 Alkaid 时跳转到原生知识库页面
2025-10-19 18:43:58 +08:00
lxfight
c04738d9fe feat: 实现知识库前端界面(英文国际化)
- 添加知识库 V2 完整英文翻译文件
- 包括:主页、文档管理、检索测试、全局设置、会话配置
- 在 Alkaid 导航中添加 "Native Knowledge Base" 入口
- 区分 "Native Knowledge Base" 和 "Knowledge Base (Plugin)"
2025-10-19 18:43:35 +08:00
lxfight
1266b4d086 feat: 实现知识库前端界面(中文国际化)
- 添加知识库 V2 完整中文翻译文件
- 包括:主页、文档管理、检索测试、全局设置、会话配置
- 在 Alkaid 导航中添加"原生知识库"入口
- 区分"原生知识库"和"知识库(插件)"两个入口
2025-10-19 18:42:43 +08:00
lxfight
99cf0a1522 feat: 添加知识库 Dashboard API 路由
- 实现知识库管理 API(创建、删除、列表、更新)
- 实现文档管理 API(上传、删除、列表、分块信息)
- 实现知识库检索测试 API(支持调试和验证)
- 实现会话配置 API(绑定/解绑知识库、配置检索参数)
- 实现全局配置 API(启用/禁用、模型选择、检索参数)
- 在 Dashboard 服务器中注册知识库路由
2025-10-19 18:41:54 +08:00
lxfight
98a75e923d feat: 集成知识库到核心生命周期和消息流水线
- 在 AstrBotCoreLifecycle 中初始化知识库管理器
- 将知识库注入器添加到消息处理上下文
- 在消息流水线中添加 KBEnhanceStage(知识库增强阶段)
- 实现会话删除时的知识库配置级联清理机制
- 添加会话管理器的回调注册机制,支持零侵入扩展
2025-10-19 18:41:34 +08:00
lxfight
ad96d676e6 feat: 实现知识库核心后端模块
- 实现完整的知识库数据模型(知识库、文档、文档块、会话配置)
- 实现基于 SQLite 的向量数据库存储和检索
- 实现文档解析器(PDF、TXT)和固定大小分块器
- 实现混合检索系统(密集向量检索 + BM25 稀疏检索 + RRF 融合)
- 实现知识库生命周期管理和消息注入器
- 支持会话级别的知识库配置和关联
2025-10-19 18:40:55 +08:00
lxfight
79333bbc35 feat: 添加知识库核心依赖和配置
- 添加 pypdf、aiofiles、rank-bm25 依赖包支持文档解析和检索
- 在 default.py 中添加知识库完整配置项
- 配置包括嵌入模型、重排序、存储路径、分块策略、检索参数等
- 默认禁用知识库功能,需用户主动启用
2025-10-19 18:39:10 +08:00
Soulter
5c5b0f4fde fix: 修复未安装知识库插件时的错误引导 2025-10-18 10:36:11 +08:00
Dt8333
ed6cdfedbb fix: 修复 dashboard 的部分编译错误 (#3041)
* chore(dashboard): adding missing dependency

* fix(dashboard): 修复vertical-header中 $router 类型错误
2025-10-16 10:32:08 +08:00
PaloMiku
23f13ef05f feat:Misskey 适配器支持文件上传、投票内容感知功能和重构部分代码 (#2986)
* feat: 为 Misskey 适配器修正一些问题,添加投票信息读取支持

* feat: 增强 Misskey 平台适配器,添加随机重连延迟和通道重新订阅功能

* feat: 添加文件上传功能并优化消息发送接口,支持同时发送文件和文本

* feat: 增强文件上传功能,支持 MIME 类型检测和外部 URL 回退

* feat: 增加 Misskey 文件上传功能开关,支持配置文件上传启用与并发限制

* feat: 添加 Misskey 文件上传目标文件夹配置,支持将文件上传到指定文件夹

* feat: 优化 Misskey 平台适配器,增强文件上传和消息发送功能,支持更多可选字段

* feat: 代码优化结构与功能

* feat(misskey): 增强消息发送逻辑和工具函数

- 重构了 `misskey_event.py` 中的 `send` 方法,使用新的适配器方法 `send_by_session`,以改进消息处理(包括文件上传)。
- 添加了详细的日志记录,以提高消息发送过程的可追溯性。
- 在 `misskey_utils.py` 中引入了 `FileIDExtractor` 和 `MessagePayloadBuilder` 类,以简化文件 ID 提取和消息载荷构建。
- 在 `misskey_utils.py` 中实现了 MIME 类型检测和文件扩展名解析,以支持多种文件上传。
- 增强了 `resolve_component_url_or_path`,以更好地处理不同类型的组件上传文件。
- 在 `upload_local_with_retries` 中添加了重试逻辑,以优雅地处理不允许的文件类型。

* feat(misskey): 限制文件上传并发数,优化消息处理逻辑

* feat(misskey): ruff formatted

* feat: 大幅优化 misskey 文件上传逻辑,简化上传流程并增强可见性解析

* feat(misskey): 移除 Url上传方式,精简日志

* fix(misskey): 修复错把URL文件当本地文件上传的问题,明确处理 URL 和本地文件的方式

* fix(misskey): 修复 session_id 解析逻辑,确保与 user_cache 键格式匹配

* perf: streaming the file with a file object in FormData to reduce peak memory usage.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* style: format debug log message for local file upload in MisskeyAPI

* refactor: remove unnecessary thread executor for reading file bytes in MisskeyAPI

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-10-16 10:27:04 +08:00
Soulter
f9c59d9706 docs: fix typo 2025-10-16 09:17:09 +08:00
Soulter
e1cec42227 chore: add Node.js setup step in CI workflow 2025-10-15 23:32:53 +08:00
Soulter
8d79c50d53 chore: update CI workflow to use pnpm for package management 2025-10-15 23:12:38 +08:00
Soulter
d77830b97f feat: add markdown-it type definitions as a dev dependency 2025-10-15 23:01:38 +08:00
Soulter
394540f689 docs: Update support status for various platforms 2025-10-15 18:48:25 +08:00
Soulter
7d776e0ce2 chore: bump version to 4.3.5 2025-10-15 12:19:26 +08:00
Soulter
17df1692b9 fix: 修复 /alter_cmd reset scene <num> xxx 不可用的问题 2025-10-15 12:16:13 +08:00
Soulter
9ab652641d feat: 支持配置工具调用超时时间并适配 ModelScope 的 MCP Server 配置 (#3039)
* feat: 支持配置工具调用超时时间并适配 ModelScope 的 MCP Server 配置。

closes: #2939

* fix: Remove unnecessary blank lines in _quick_test_mcp_connection function
2025-10-15 12:06:57 +08:00
shangxue
9119f7166f feat: satori 适配器支持 video、reply 消息类型 (#3035)
* Update satori_event.py

* style: format

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-10-15 10:45:35 +08:00
Soulter
da7d9d8eb9 feat: Add tutorial link for wecom_ai_bot platform 2025-10-15 10:42:31 +08:00
Soulter
80fccc90b7 feat: 支持接入企业微信智能机器人平台 (#3034)
* stage

* stage

* feat: 支持图片收发

* feat: add support for wecom_ai_bot in getPlatformIcon function
2025-10-14 23:20:56 +08:00
Soulter
dcebc70f1a chore: Add new auto-assign users to configuration 2025-10-14 12:16:22 +08:00
dependabot[bot]
259e7bc322 chore(deps): bump github/codeql-action in the github-actions group (#3032)
Bumps the github-actions group with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3 to 4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-14 09:35:57 +08:00
Soulter
37bdb6c6f6 feat: 内置网页搜索功能支持接入百度 AI 搜索 (#3031)
* feat: 内置网页搜索功能支持接入百度 AI 搜索

* fix: 修正配置文件中的拼写错误,更新为正确的键名

* Fix Baidu AI Search initialization logic
2025-10-14 09:35:34 +08:00
Soulter
dc71afdd3f docs: Revise README for clarity and updated support info
Updated README.md to improve clarity and fix formatting issues. Removed outdated developer group information and added support details for new platforms and services.
2025-10-14 09:13:54 +08:00
Soulter
44638108d0 docs: readme 2025-10-14 08:53:23 +08:00
RC-CHN
93fcac498c feat: 添加并优化服务提供商独立测试功能 (#3024)
* feat: 添加并优化服务提供商独立测试功能

* feat: add small size to action buttons in ItemCard and ProviderPage for better UI consistency

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-10-13 13:03:20 +08:00
Soulter
79e2743aac chore: bump version to 4.3.3 2025-10-12 11:42:18 +08:00
anka
5e9c7cdd91 fix: 当没有填写 api key 时,设置为空字符串 (#2834)
* fix: 修复空key导致的无法创建Provider对象的问题

* style: format code

* Update astrbot/core/provider/provider.py

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

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-10-12 10:50:01 +08:00
Dt8333
6f73e5087d feat(core): 在新对话中重用先前的对话人格设置 (#3005)
* feat(core): reuse persona conf in new conversation

#2985

* refactor(core): simplify persona retrieval logic

* style: code format

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-10-12 10:42:35 +08:00
Yaron
8c120b020e fix: 修复阿里云百炼平台 TTS 下接入 CosyVoice V2, Qwen TTS 生成报错的问题 (#2964)
* fix: 修复了CosyVoice V2,Qwen TTS生成报错的问题。Fixed compatability problems with CosyVoice V2, Qwen TTS.

* fix: 将urlopen的同步请求替换为aiohttp的异步请求以下载音频

* fix: cozyvoice 报错显示

* fix: 添加阿里云百炼 TTS API Key 获取提示信息

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-10-12 01:03:06 +08:00
Dt8333
12fc6f9d38 fix(LTM): fix LTM not removed when removing conversation (#3002)
#2983
2025-10-12 00:16:42 +08:00
Dt8333
a6e8483b4c fix: 修复session-management中人格错误的显示为默认人格的问题 (#3000)
* fix: 修复session-management中人格错误的显示为默认人格的问题

#2985

* refactor: 使用命名表达式简化赋值和条件

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

* style: format edited code with ruff

format code edited by sourcery-ai

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-10-12 00:12:04 +08:00
Soulter
7191d28ada fix: 启动了 TTS 但未配置 TTS 模型时,At 和 Reply 发送人无效
fixes: #2996
2025-10-10 12:11:03 +08:00
Soulter
e6b5e3d282 feat: tokenpony provider 2025-10-09 16:00:31 +08:00
ctrlkk
1413d6b5fe fix: 让事件钩子被暂停时跳出循环,而不是继续执行 (#2989) 2025-10-09 15:01:45 +08:00
ctrlkk
dcd8a1094c feat: 优化 SQLite 参数配置,对话和会话管理增加输入防抖机制 (#2969)
* feat: 优化 SQLite 数据库初始化设置并增强会话搜索功能,会话管理增加输入防抖

* fix: adjust SQLite cache and mmap size

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-10-06 17:13:53 +08:00
Futureppo
e64b31b9ba fix: Correct default modalities for DeepSeek provider (#2963)
* 更新 package.json

* 更新 ExtensionPage.vue

* fix(provider): Correct default modalities for DeepSeek provider
2025-10-06 16:30:05 +08:00
Dt8333
080f347511 feat: clean browser cache after update (#2958)
* feat: clean browser cache after update

* fix: move const to module

* fix: remove self prefix (a stupid mistake)
2025-10-06 16:29:18 +08:00
Dt8333
eaaff4298d fix(Python-Interpreter): fix incorrect file read method (#2970)
fix getting file by property(Sync) in an async handler

#2960
2025-10-06 16:12:05 +08:00
Soulter
dd5a02e8ef chore: bump version to 4.3.2 2025-10-05 01:01:13 +08:00
Soulter
3211ec57ee fix: handle Google search initialization and errors gracefully 2025-10-05 00:55:47 +08:00
Soulter
6796afdaee fix: googlesearch 2025-10-05 00:54:24 +08:00
Soulter
cc6fe57773 fix: on_tool_end无法获得工具返回的结果 (#2956)
fixes: #2940
2025-10-05 00:37:51 +08:00
Soulter
1dfc831938 fix: 修复 reset 没有清除群聊上下文感知数据的问题 (#2954) 2025-10-05 00:05:42 +08:00
Futureppo
cafeda4abf feat: 为插件市场的搜索增加拼音与首字母搜索功能 (#2936)
* 更新 package.json

* 更新 ExtensionPage.vue
2025-10-03 09:42:57 +08:00
Soulter
d951b99718 fix: 发送阶段将 Plain 为空的消息段移除 2025-10-03 00:45:07 +08:00
Soulter
0ad87209e5 chore: bump version to 4.3.1 2025-10-02 17:25:09 +08:00
Soulter
1b50c5404d fix: enhance knowledge base plugin status check to handle empty data response 2025-10-02 17:25:00 +08:00
Soulter
3007f67cab fix: update Dockerfile to remove npm installation and streamline package setup
closes: #2284
2025-10-02 16:59:11 +08:00
Soulter
ee08659f01 chore: bump version to 4.3.0 2025-10-02 16:37:54 +08:00
Soulter
baf5ad0fab fix: 修复接入智谱提供商后,工具调用无限循环的问题,并停止支持 glm-4v-flash (#2931)
fixes: #2912
2025-10-02 16:03:24 +08:00
kterna
8bdd748aec feat: 支持注册消息平台适配器的 logo (#2109)
* feat: 添加平台适配器 logo 支持

* 优化平台logo注册逻辑,增加缓存机制并支持并行处理

* 去除判断绝对路径

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-10-02 14:36:15 +08:00
Soulter
cef0c22f52 feat: update prompt prefix handling to support placeholder replacement 2025-10-02 14:20:52 +08:00
Soulter
13d3fc5cfe fix: fix type checking error and op, deop, wl, dwl command 2025-10-02 00:18:12 +08:00
Soulter
b91141e2be fix: add plugin activation check and corresponding messages in Knowledge Base 2025-10-01 22:14:03 +08:00
Soulter
f8a4b54165 fix: 修复插件指令注解为联合类型时处理异常的问题 (#2925)
* fix: 修复插件指令注解为联合类型时处理异常的问题

* fix: 修复参数类型检查以支持 typing.Union

* Update astrbot/core/star/filter/command.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update astrbot/core/star/filter/command.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: 修复参数类型检查以支持 typing.Union 的处理逻辑

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-01 21:46:49 +08:00
Soulter
afe007ca0b refactor: 优化 packages/astrbot 内置插件的代码结构以提高可维护性和可读性 (#2924)
* refactor: code structure for improved readability and maintainability

* style: ruff format

* Update packages/astrbot/commands/provider.py

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

* Update packages/astrbot/commands/persona.py

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

* Update packages/astrbot/commands/llm.py

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

* Update packages/astrbot/commands/conversation.py

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

* fix: improve error handling message formatting in key switching

* fix: update LLM command to use safe get for provider settings

* feat: implement ProcessLLMRequest class for handling LLM requests and persona injection

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-10-01 21:29:15 +08:00
Soulter
8a9a044f95 fix: 修复注册指令组指令时的 Pyright 类型检查提示 (#2923) 2025-10-01 20:03:04 +08:00
u0_ani-nya.com
5eaf03e227 perf: 对于 Telegram 群聊,将回复机器人的消息视为唤醒机器人 (#2926)
* reply as at for tg

Add handling for bot replies in group messages.

* style: type checking and ruff format

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-10-01 19:04:37 +08:00
Seayon
a8437d9331 feat: 支持在 Telegram 和飞书下请求 LLM 前预表态功能 (#2737)
*  feat(platform): 为 Telegram 和飞书添加消息表情回应功能

支持在收到命令时自动添加表情回应,提升用户交互体验
新增平台特异配置项,允许自定义启用状态和表情列表

* Update astrbot/core/platform/astr_message_event.py

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

* style: ruff format

* fix: 优化平台特异配置的预回应表情处理逻辑

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-09-30 17:29:34 +08:00
晴空
e0392fa98b fix: 用 mi-googlesearch-python 库代替失效的 googlesearch-python 库 (#2909)
* googlesearch-python库失效,用mi-googlesearch-python库平替,恢复谷歌搜索

* Update googlesearch-python dependency version
2025-09-29 12:54:16 +08:00
ctrlkk
68ff8951de feat: 添加分页和搜索功能以获取会话列表,优化前端与后端的数据交互 (#2906)
* feat: 添加分页和搜索功能以获取会话列表,优化前端与后端的数据交互

* fix: 修复会话计数显示,使用总项数替代会话数组长度

* fix: 将参数类型和名称与实现内容匹配。

* perf: convert for loop into list comprehension

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

* fix: type checking error

* fix: 优化 persona_id 的获取逻辑

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-09-28 23:25:30 +08:00
KroMiose
9c6b31e71c Update README.md (#2904) 2025-09-28 14:50:02 +08:00
Soulter
50f74f5ba2 fix: 修复"开启 TTS 时同时输出语音和文字内容"功能不可用的问题 (#2900)
fixes: #2844
2025-09-28 10:48:57 +08:00
Soulter
b9de2aef60 chore: bump version to 4.2.1 2025-09-27 23:36:25 +08:00
Soulter
7a47598538 fix: 修复指令无法使用的问题
fixes: #2897
2025-09-27 23:35:35 +08:00
Soulter
3c8c28ebd5 chore: bump version to 4.2.0 2025-09-27 20:45:50 +08:00
Soulter
524285f767 feat: add cancel button with localized text to AddNewPlatform and update close button in AddNewProvider
fixes: #2889
2025-09-27 20:41:45 +08:00
Soulter
c2a34475f1 feat: 支持删除指定会话以及部分会话管理优化 (#2895)
* feat: add toast notification system with snackbar component

* feat: add session deletion functionality

* feat: support batch operations for updating session persona, provider, LLM, and TTS statuses

fix: #2263

* feat: 修复对话状态关闭,删除对话管理库会导致对话无法恢复

fixes: #2309
2025-09-27 20:36:30 +08:00
Soulter
a69195a02b fix: webchat streaming queue interrupted after user closing tab (#2892)
* feat: add toast notification system with snackbar component

* feat: enhance chat functionality with conversation running state and notifications

* fix: update bot message avatar rendering during streaming

* feat: implement conversation tracking context manager for webchat

* fix: update conversation tracking to remove conversation ID on exit
2025-09-27 17:57:12 +08:00
RC-CHN
19d7438499 fix: unit tests (#2760)
* fix:修复了main和plugin_manager部分单元测试

* fix: 修复了dashboard部分测试

* remove: 删除暂无用的配置测试脚本

* perf:拆分插件增查删改为独立的单元测试

* refactor: 重构插件管理器测试,使用临时环境隔离测试实例

* test: 增加对仪表板文件检查的单元测试,涵盖不同情况

* style: format code

* remove: 删除未使用的导入语句

* delete: remove unused test file for pipeline

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-09-27 14:43:04 +08:00
anka
ccb380ce06 feat: 支持接入 Coze (#2858)
* feat: 适配 coze 供应商
1. 支持文件上传
2. 支持多模态
3. 支持流式传输
4. 支持 API 端的上下文保存历史记录
5. 支持类似 dify 的 forget 接口

* style: format code

* fix: type checking error

* fix: 修复:
1. 使用coze api端的上下文时, 现在不会重复传递上下文
2. 使用 AstrBot 的上下文时, 正确处理其中的图片信息
3. 上传图片时, 提供一个非持久化的缓存避免重复上传(在解析上下文并将文件转化为file_id传递给coze api时, 如果没有缓存会导致很多的网络资源浪费)
4. 修复reset等指令不能正确重置上下文的问题

* fix: 移除某些地方多余的针对 dify 的断言, 以兼容 Coze

* style: 修改配置项显示/webchat平台对于非预期的类型的处理

* fix: 让conversation_id放到请求中正确的位置

* refactor: extract coze api client

* refactor: improve image processing logic in ProviderCoze

* chore: remove file ext guessing

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-09-27 14:23:29 +08:00
Ding Jiatong
a35c439bbd fix: 使用增量解码器修复 Dify 流式返回结果偶现的解码错误 (#2888)
* fix: 修复linux下utf-8解码错误的问题

* feat: use incremental decoder

* fix: add type hint for response parameter in _stream_sse and refactor file upload method

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-09-26 23:04:58 +08:00
Soulter
09d1f96603 fix: 修复 /alter_cmd 指令无法控制指令组、子指令组和子指令组下子指令的问题 (#2873)
* fix: revert changes in command_group.py at 782c036 to fix command group permission check

* fix: 不传递 GroupCommand handler

* perf: alter_cmd 指令支持对子指令、指令组进行配置

* chore: remove test commands and subcommands from test_group

* chore: add cache for complete command names list in CommandFilter and CommandGroupFilter

---------

Co-authored-by: Dt8333 <25431943+Dt8333@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-09-26 14:16:50 +08:00
鸦羽
26aa18d980 Merge pull request #2881 from Raven95676/fix/2879
fix: add missing id field
2025-09-26 11:31:28 +08:00
Raven95676
d10b542797 chore: format 2025-09-26 11:05:32 +08:00
Raven95676
ce4e4fb8dd fix: add missing id field 2025-09-26 10:59:11 +08:00
Soulter
8f4a31cf8c chore: bump version to 4.1.7 2025-09-23 22:16:36 +08:00
Soulter
23549f13d6 Feature: 支持批量删除对话历史 (#2859)
* feat: 支持批量删除对话

closes: #2784

* feat: 添加加载状态禁用功能,优化用户交互体验
2025-09-23 22:10:56 +08:00
Soulter
869d11f9a6 perf: 优化验证配置时的性能,移除配置隐式类型转换
fixes: #2646
2025-09-23 21:04:14 +08:00
Soulter
02e73b82ee fix: 修复无法打开更新对话框的问题 2025-09-23 20:29:10 +08:00
Soulter
f85f87f545 feat: WebChat 支持手动填写模型名
closes: #2830
2025-09-23 15:32:54 +08:00
Soulter
1fff5713f3 refactor: 解耦 PlatformPage 和 ProviderPage 的部分组件 2025-09-23 15:32:54 +08:00
Soulter
8453ec36f0 docs: Revise links for documentation and blog in README
Updated links in the README for documentation and blog.
2025-09-23 14:12:05 +08:00
Soulter
d5b3ce8424 fix: update download_dashboard to log specific dashboard release URLs 2025-09-23 13:10:33 +08:00
Soulter
80cbbfa5ca chore: bump version to 4.1.6 2025-09-23 13:02:06 +08:00
Soulter
9177bb660f fix: improve error handling in run_agent for streaming responses 2025-09-23 10:34:24 +08:00
Soulter
a3df39a01a perf: unified button styles
closes: #2748
2025-09-23 10:27:52 +08:00
Soulter
25dce05cbb refactor: improve webchat UI (#2853) 2025-09-23 10:19:26 +08:00
Soulter
1542ea3e03 fix: context.get_provider_by_id issue 2025-09-22 17:22:50 +08:00
Soulter
6084abbcfe feat: add user_id search capability in get_filtered_conversations 2025-09-21 22:45:55 +08:00
Soulter
ed19b63914 chore: bump version to v4.1.5 2025-09-21 21:47:14 +08:00
Soulter
4efeb85296 chore: remove uv.lock file 2025-09-21 21:47:06 +08:00
shangxue
fc76665615 feat: Satori适配器引用消息无法正确识别 (#2686)
* Update PlatformPage.vue

* Update PlatformPage.vue

* Update PlatformPage.vue

* Update satori_adapter.py

* Update satori_event.py

* Update default.py

* Update satori_adapter.py

* Update satori_adapter.py

* style: format code

---------

Co-authored-by: Soulter <905617992@qq.com>
2025-09-21 21:45:35 +08:00
Soulter
3a044bb71a fix: 修复 Telegram 下流式传输时,第一次输出的内容会被覆盖掉的问题 (#2838)
fixes: #2481
2025-09-21 21:24:47 +08:00
Soulter
cddd606562 perf: 优化 ExtensionPage 2025-09-21 21:10:03 +08:00
Soulter
7a5bc51c11 fix: 识别引用消息的图片时优先使用默认图片转述提供商 (#2836)
* fix: 识别引用消息的图片时优先使用默认图片转述提供商

closes: #2821

* fix: 添加日志记录以处理未找到图片标题提供者的情况

* style: format code
2025-09-21 20:55:32 +08:00
Soulter
9f939b4b6f fix: 修复对话管理页面的关键词搜索功能失效的问题并优化一些 UI 样式 (#2837)
* fix: 修复对话管理页面的关键词搜索功能失效的问题并优化一些 UI 样式

fixes: #2782

* style: format code

* fix: remove debug print statements from conversation retrieval methods
2025-09-21 20:55:15 +08:00
Soulter
80a86f5b1b fix: 修复 astrbot.core.star 等包下的 type checking error (#2787)
* fix: 修复 astrbot.core.star 等包下的 type checking error

* refactor: improve type checking and annotations

* chore: ruff format
2025-09-21 18:10:04 +08:00
yitaikarma
a0ce1855ab fix: 优化统计页内存占用和消息数据趋势的样式 (#2826)
* fix: 调整统计页内存占用和消息趋势分析的布局,优化响应式显示

* fix: 隐藏增长率为零时的趋势图标
2025-09-21 17:06:47 +08:00
anka
a4b43b884a fix: 修复aiocqhttp适配器at会获取群昵称而消息不会获取的逻辑不一致 (#2769)
* fix: 修复at会获取群昵称而消息不会获取的逻辑不一致

* style: format code
2025-09-19 13:04:51 +08:00
PaloMiku
824c0f6667 feat: 新增 Misskey 平台适配器 (#2774)
* feat: add Misskey platform adapter

* fix: 修复 Misskey 配置项的大小写问题

* feat: 添加消息链序列化功能和可见性解析逻辑

* chore: 删除损坏的 Misskey 平台适配器工具函数文件

* docs: 更新 Misskey 消息适配器设置描述信息

* feat: Misskey 单用户连续上下文对话支持

* feat: 为 Astrbot 添加 Misskey 平台适配器的 ID 配置

* feat: 重构 Misskey 平台适配器,提取通用工具函数并优化消息处理逻辑

* refactor: 清理 Misskey 平台适配器和 API 代码,移除冗余注释

* fix: 修复了使用中和使用者反馈的多个问题

* fix: 修改提及格式,确保提及在新行开始,提升帖子美观和易读性。

* feat: 添加默认可见性和本地仅限设置,优化 Misskey 平台适配器的配置

* fix: 更新 Misskey 平台适配器配置,使用前缀以防止和其他适配器未来可能的冲突问题

* chore: rename 'misskey' to 'Misskey' in config

* feat: Misskey 适配器添加聊天消息响应功能,重构接收和发送逻辑为 Websockets 处理

* fix: 增强 Misskey WebSocket 消息日志输出

* refactor: 优化 Misskey 适配器的消息处理和日志输出

* fix: 增强 Misskey WebSocket 重连接逻辑

* feat: 增强 Misskey 适配器的消息处理,支持房间消息和相关功能,重构通用函数,清理代码重复冗余

* fix: 不屏蔽唤醒前缀对默认 LLM 的唤醒

* fix: 透传所有的群聊消息事件

* fix: 修复 message_type

* perf: 实现 send_streaming 以支援流式请求

* docs(README): update README.md

* fix: super().send(message) 被忽略

* fix: 修正 session 结构

: 作为分隔符可能会导致 umo 组装出现问题

---------

Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
2025-09-18 23:34:41 +08:00
Soulter
a030fe8491 feat: add audioop-lts dependencies (#2809)
pydub needs audioop as a requirement but this builtin package has been removed in 3.13
2025-09-18 23:32:04 +08:00
Soulter
3a9429e8ef fix: on_tool_end hook unavailable 2025-09-17 15:48:57 +08:00
anka
c4eb1ab748 chore: bump version to 4.1.4 2025-09-16 20:09:11 +08:00
anka
29ed19d600 Merge pull request #2783 from AstrBotDevs/revert-2778-fix-handler-type
Revert "fix: parameter type/default handling in CommandFilter"
2025-09-16 20:01:23 +08:00
anka
0cc65513a5 Revert "fix: parameter type/default handling in CommandFilter" 2025-09-16 20:01:05 +08:00
1754 changed files with 362304 additions and 39382 deletions

View File

@@ -1,9 +1,9 @@
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# github acions
# github actions
.git
.github/
.*ignore
.git/
# User-specific stuff
.idea/
# Byte-compiled / optimized / DLL files
@@ -15,10 +15,12 @@ env/
venv*/
ENV/
.conda/
README*.md
dashboard/
!astrbot/dashboard/
!astrbot/dashboard/dist/
!astrbot/dashboard/dist/**
data/
changelogs/
tests/
.ruff_cache/
.astrbot
.astrbot
astrbot.lock

184
.env.example Normal file
View File

@@ -0,0 +1,184 @@
# ==========================================
# AstrBot Instance Configuration: ${INSTANCE_NAME}
# AstrBot 实例配置文件:${INSTANCE_NAME}
# ==========================================
# 将此文件复制为 .env 并根据需要修改。
# Copy this file to .env and modify as needed.
# 注意:在此处设置的变量将覆盖默认配置。
# Note: Variables set here override application defaults.
# ------------------------------------------
# 实例标识 / Instance Identity
# ------------------------------------------
# 实例名称(用于日志和服务名)
# Instance name (used in logs/service names)
INSTANCE_NAME="${INSTANCE_NAME}"
# ------------------------------------------
# 核心配置 / Core Configuration
# ------------------------------------------
# AstrBot 根目录路径
# AstrBot root directory path
# 默认 Default: 当前工作目录,桌面客户端为 ~/.astrbot服务器为 /var/lib/astrbot/<instance>/
# 示例 Example: /var/lib/astrbot/mybot
ASTRBOT_ROOT="${ASTRBOT_ROOT}"
# 日志等级
# Log level
# 可选值 Values: DEBUG, INFO, WARNING, ERROR, CRITICAL
# 默认 Default: INFO
# ASTRBOT_LOG_LEVEL=INFO
# 启用插件热重载(开发时有用)
# Enable plugin hot reload (useful for development)
# 可选值 Values: 0 (禁用 disabled), 1 (启用 enabled)
# 默认 Default: 0
# ASTRBOT_RELOAD=0
# 禁用匿名使用统计
# Disable anonymous usage statistics
# 可选值 Values: 0 (启用统计 enabled), 1 (禁用统计 disabled)
# 默认 Default: 0
ASTRBOT_DISABLE_METRICS=0
# 覆盖 Python 可执行文件路径(用于本地代码执行功能)
# Override Python executable path (for local code execution)
# 示例 Example: /usr/bin/python3, /home/user/.pyenv/shims/python
# PYTHON=/usr/bin/python3
# 启用演示模式(可能限制部分功能)
# Enable demo mode (may restrict certain features)
# 可选值 Values: True, False
# 默认 Default: False
# DEMO_MODE=False
# 启用测试模式(影响日志和部分行为)
# Enable testing mode (affects logging and behavior)
# 可选值 Values: True, False
# 默认 Default: False
# TESTING=False
# 标记:是否通过桌面客户端执行(主要用于内部)
# Flag: running via desktop client (internal use)
# 可选值 Values: 0, 1
# ASTRBOT_DESKTOP_CLIENT=0
# 标记:是否通过 systemd 服务执行
# Flag: running via systemd service
# 可选值 Values: 0, 1
ASTRBOT_SYSTEMD=1
# ------------------------------------------
# 管理面板配置 / Dashboard Configuration
# ------------------------------------------
# 启用或禁用 WebUI 管理面板
# Enable or disable WebUI dashboard
# 可选值 Values: True, False
# 默认 Default: True
ASTRBOT_DASHBOARD_ENABLE=True
# 允许跨域请求的来源域名(多个用逗号分隔,允许所有则用 *
# Allowed CORS origins for WebUI dashboard (comma-separated, or * for all)
# 示例 Example: https://dash.astrbot.men
# 默认 Default: *
# ASTRBOT_CORS_ALLOW_ORIGIN="*"
# ------------------------------------------
# 国际化配置 / Internationalization Configuration
# ------------------------------------------
# CLI 界面语言
# CLI interface language
# 可选值 Values: zh (中文), en (英文)
# 默认 Default: zh (跟随系统 locale / follows system locale)
# ASTRBOT_CLI_LANG=zh
# ------------------------------------------
# 网络配置 / Network Configuration
# ------------------------------------------
# API 绑定主机
# API bind host
# 示例 Example: 0.0.0.0 (所有接口 all interfaces), 127.0.0.1 (仅本地 localhost only)
ASTRBOT_HOST="${ASTRBOT_HOST}"
# API 绑定端口
# API bind port
# 示例 Example: 3000, 6185, 8080
ASTRBOT_PORT="${ASTRBOT_PORT}"
# 是否为 API 启用 SSL/TLS
# Enable SSL/TLS for API
# 可选值 Values: true, false
# 默认 Default: false
ASTRBOT_SSL_ENABLE=false
# SSL 证书路径PEM 格式)
# SSL certificate path (PEM format)
# 示例 Example: /etc/astrbot/certs/myinstance/fullchain.pem
ASTRBOT_SSL_CERT=""
# SSL 私钥路径PEM 格式)
# SSL private key path (PEM format)
# 示例 Example: /etc/astrbot/certs/myinstance/privkey.pem
ASTRBOT_SSL_KEY=""
# SSL CA 证书链路径(可选,用于客户端验证)
# SSL CA certificates bundle (optional, for client verification)
# 示例 Example: /etc/ssl/certs/ca-certificates.crt
ASTRBOT_SSL_CA_CERTS=""
# ------------------------------------------
# 代理配置 / Proxy Configuration
# ------------------------------------------
# HTTP 代理地址
# HTTP proxy URL
# 示例 Example: http://127.0.0.1:7890, socks5://127.0.0.1:1080
# http_proxy=
# HTTPS 代理地址
# HTTPS proxy URL
# 示例 Example: http://127.0.0.1:7890, socks5://127.0.0.1:1080
# https_proxy=
# 不走代理的主机列表(逗号分隔)
# Hosts to bypass proxy (comma-separated)
# 示例 Example: localhost,127.0.0.1,192.168.0.0/16,.local
# no_proxy=localhost,127.0.0.1
# ------------------------------------------
# 第三方集成 / Third-party Integrations
# ------------------------------------------
# 阿里云 DashScope API 密钥(用于 Rerank 服务)
# Alibaba DashScope API Key (for Rerank service)
# 获取地址 Get from: https://dashscope.console.aliyun.com/
# 示例 Example: sk-xxxxxxxxxxxx
# DASHSCOPE_API_KEY=
# Coze 集成
# Coze integration
# 获取地址 Get from: https://www.coze.com/
# COZE_API_KEY=
# COZE_BOT_ID=
# 计算机控制相关的数据目录(用于截图/文件存储)
# Computer control data directory (for screenshots/file storage)
# 示例 Example: /var/lib/astrbot/bay_data
# BAY_DATA_DIR=
# ------------------------------------------
# 平台特定配置 / Platform-specific Configuration
# ------------------------------------------
# QQ 官方机器人测试模式开关
# QQ official bot test mode
# 可选值 Values: on, off
# 默认 Default: off
# TEST_MODE=off
# End of template / 模板结束

2
.envrc Normal file
View File

@@ -0,0 +1,2 @@
git pull
git status

View File

@@ -16,7 +16,7 @@ body:
请将插件信息填写到下方的 JSON 代码块中。其中 `tags`(插件标签)和 `social_link`(社交链接)选填。
不熟悉 JSON 现在可以从 [这里](https://plugins.astrbot.app/#/submit) 获取你的 JSON 啦!获取到了记得复制粘贴过来哦!
不熟悉 JSON ?可以从 [此站](https://plugins.astrbot.app) 右下角提交。
- type: textarea
id: plugin-info
@@ -26,12 +26,13 @@ body:
value: |
```json
{
"name": "插件名",
"desc": "插件介绍",
"name": "插件名,请以 astrbot_plugin_ 开头",
"display_name": "用于展示的插件名,方便人类阅读",
"desc": "插件的简短介绍",
"author": "作者名",
"repo": "插件仓库链接",
"tags": [],
"social_link": ""
"social_link": "",
}
```
validations:

View File

@@ -1,46 +1,44 @@
name: '🐛 报告 Bug'
name: '🐛 Report Bug / 报告 Bug'
title: '[Bug]'
description: 提交报告帮助我们改进。
description: Submit bug report to help us improve. / 提交报告帮助我们改进。
labels: [ 'bug' ]
body:
- type: markdown
attributes:
value: |
感谢您抽出时间报告问题!请准确解释您的问题。如果可能,请提供一个可复现的片段(这有助于更快地解决问题)。
Thank you for taking the time to report this issue! Please describe your problem accurately. If possible, please provide a reproducible snippet (this will help resolve the issue more quickly). Please note that issues that are not detailed or have no logs will be closed immediately. Thank you for your understanding. / 感谢您抽出时间报告问题!请准确解释您的问题。如果可能,请提供一个可复现的片段(这有助于更快地解决问题)。请注意,不详细 / 没有日志的 issue 会被直接关闭,谢谢理解。
- type: textarea
attributes:
label: 发生了什么
description: 描述你遇到的异常
label: What happened / 发生了什么
description: Description
placeholder: >
一个清晰且具体的描述这个异常是什么
Please provide a clear and specific description of what this exception is. Please note that issues that are not detailed or have no logs will be closed immediately. Thank you for your understanding. / 一个清晰且具体的描述这个异常是什么。请注意,不详细 / 没有日志的 issue 会被直接关闭,谢谢理解
validations:
required: true
- type: textarea
attributes:
label: 如何复现?
label: Reproduce / 如何复现?
description: >
复现该问题的步骤
The steps to reproduce the issue. / 复现该问题的步骤
placeholder: >
: 1. 打开 '...'
Example: 1. Open '...'
validations:
required: true
- type: textarea
attributes:
label: AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器
description: >
请提供您的 AstrBot 版本和部署方式。
label: AstrBot version, deployment method (e.g., Windows Docker Desktop deployment), provider used, and messaging platform used. / AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器
placeholder: >
如: 3.1.8 Docker, 3.1.7 Windows启动器
Example: 4.5.7 Docker, 3.1.7 Windows Launcher
validations:
required: true
- type: dropdown
attributes:
label: 操作系统
label: OS
description: |
你在哪个操作系统上遇到了这个问题?
On which operating system did you encounter this problem? / 你在哪个操作系统上遇到了这个问题?
multiple: false
options:
- 'Windows'
@@ -53,30 +51,30 @@ body:
- type: textarea
attributes:
label: 报错日志
label: Logs / 报错日志
description: >
如报错日志、截图等。请提供完整的 Debug 级别的日志,不要介意它很长!
Please provide complete Debug-level logs, such as error logs and screenshots. Don't worry if they're long! Please note that issues with insufficient details or no logs will be closed immediately. Thank you for your understanding. / 如报错日志、截图等。请提供完整的 Debug 级别的日志,不要介意它很长!请注意,不详细 / 没有日志的 issue 会被直接关闭,谢谢理解。
placeholder: >
请提供完整的报错日志或截图。
Please provide a complete error log or screenshot. / 请提供完整的报错日志或截图。
validations:
required: true
- type: checkboxes
attributes:
label: 你愿意提交 PR 吗?
label: Are you willing to submit a PR? / 你愿意提交 PR 吗?
description: >
这不是必需的,但我们很乐意在贡献过程中为您提供指导特别是如果你已经很好地理解了如何实现修复。
This is not required, but we would be happy to provide guidance during the contribution process, especially if you already have a good understanding of how to implement the fix. / 这不是必需的,但我们很乐意在贡献过程中为您提供指导特别是如果你已经很好地理解了如何实现修复。
options:
- label: 是的,我愿意提交 PR!
- label: Yes!
- type: checkboxes
attributes:
label: Code of Conduct
options:
- label: >
我已阅读并同意遵守该项目的 [行为准则](https://docs.github.com/zh/site-policy/github-terms/github-community-code-of-conduct)。
I have read and agree to abide by the project's [Code of Conduct](https://docs.github.com/zh/site-policy/github-terms/github-community-code-of-conduct)。
required: true
- type: markdown
attributes:
value: "感谢您填写我们的表单!"
value: "Thank you for filling out our form! / 感谢您填写我们的表单!"

View File

@@ -1,42 +1,40 @@
name: '🎉 功能建议'
name: '🎉 Feature Request / 功能建议'
title: "[Feature]"
description: 提交建议帮助我们改进。
description: Submit a suggestion to help us improve. / 提交建议帮助我们改进。
labels: [ "enhancement" ]
body:
- type: markdown
attributes:
value: |
感谢您抽出时间提出新功能建议,请准确解释您的想法。
Thank you for taking the time to suggest a new feature! Please explain your idea clearly and accurately. / 感谢您抽出时间提出新功能建议,请准确解释您的想法。
- type: textarea
attributes:
label: 描述
description: 简短描述您的功能建议
label: Description / 描述
description: Please describe the feature you want to be added in detail. / 请详细描述您希望添加的功能。
- type: textarea
attributes:
label: 使用场景
description: 你想要发生什么?
placeholder: >
一个清晰且具体的描述这个功能的使用场景。
label: Use Case / 使用场景
description: Please describe the use case for this feature. / 请描述这个功能的使用场景。
- type: checkboxes
attributes:
label: 愿意提交PR吗?
label: Willing to Submit PR? / 是否愿意提交PR
description: >
这不是必的,但我们欢迎您的贡献。
This is not required, but if you are willing to submit a PR to implement this feature, it would be greatly appreciated! / 这不是必的,但如果您愿意提交 PR 来实现这个功能,我们将不胜感激!
options:
- label: 是的, 我愿意提交PR!
- label: Yes, I am willing to submit a PR. / 是的,我愿意提交 PR
- type: checkboxes
attributes:
label: Code of Conduct
options:
- label: >
我已阅读并同意遵守该项目的 [行为准则](https://docs.github.com/zh/site-policy/github-terms/github-community-code-of-conduct)
I have read and agree to abide by the project's [Code of Conduct](https://docs.github.com/zh/site-policy/github-terms/github-community-code-of-conduct). /
required: true
- type: markdown
attributes:
value: "感谢您填写我们的表单!"
value: "Thank you for filling out our form!"

View File

@@ -1,46 +1,34 @@
<!-- 如果有的话,请指定此 PR 旨在解决的 ISSUE 编号。 -->
<!-- If applicable, please specify the ISSUE number this PR aims to resolve. -->
fixes #XYZ
---
### Motivation / 动机
<!--请描述此项更改的动机:它解决了什么问题?(例如:修复了 XX 错误,添加了 YY 功能)-->
<!--Please describe the motivation for this change: What problem does it solve? (e.g., Fixes XX bug, adds YY feature)-->
<!--Please describe the motivation for this change: What problem does it solve? (e.g., Fixes XX issue, adds YY feature)-->
<!--请描述此项更改的动机:它解决了什么问题?(例如:修复了 XX issue添加了 YY 功能)-->
### Modifications / 改动点
<!--请总结你的改动:哪些核心文件被修改了?实现了什么功能?-->
<!--Please summarize your changes: What core files were modified? What functionality was implemented?-->
<!--请总结你的改动:哪些核心文件被修改了?实现了什么功能?-->
### Verification Steps / 验证步骤
<!--请为审查者 (Reviewer) 提供清晰、可复现的验证步骤例如1. 导航到... 2. 点击...)。-->
<!--Please provide clear and reproducible verification steps for the Reviewer (e.g., 1. Navigate to... 2. Click...).-->
- [x] This is NOT a breaking change. / 这不是一个破坏性变更。
<!-- If your changes is a breaking change, please uncheck the checkbox above -->
### Screenshots or Test Results / 运行截图或测试结果
<!--请粘贴截图、GIF 或测试日志,作为执行“验证步骤”的证据,证明此改动有效。-->
<!--Please paste screenshots, GIFs, or test logs here as evidence of executing the "Verification Steps" to prove this change is effective.-->
### Compatibility & Breaking Changes / 兼容性与破坏性变更
<!--请说明此变更的兼容性:哪些是破坏性变更?哪些地方做了向后兼容处理?是否提供了数据迁移方法?-->
<!--Please explain the compatibility of this change: What are the breaking changes? What backward-compatible measures were taken? Are data migration paths provided?-->
- [ ] 这是一个破坏性变更 (Breaking Change)。/ This is a breaking change.
- [ ] 这不是一个破坏性变更。/ This is NOT a breaking change.
<!--请粘贴截图、GIF 或测试日志,作为执行“验证步骤”的证据,证明此改动有效。-->
---
### Checklist / 检查清单
<!--如果分支被合并,您的代码将服务于数万名用户!在提交前,请核查一下几点内容。-->
<!--If merged, your code will serve tens of thousands of users! Please double-check the following items before submitting.-->
<!--如果分支被合并,您的代码将服务于数万名用户!在提交前,请核查一下几点内容。-->
- [ ] 😊 如果 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.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 in `requirements.txt` and `pyproject.toml`.
- [ ] 😮 我的更改没有引入恶意代码。/ My changes do not introduce malicious code.
- [ ] 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
/ 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。
- [ ] 👀 My changes have been well-tested, **and "Verification Steps" and "Screenshots" have been provided above**.
/ 我的更改经过了良好的测试,**并已在上方提供了“验证步骤”和“运行截图”**。
- [ ] 🤓 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`.
/ 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 `requirements.txt``pyproject.toml` 文件相应位置。
- [ ] 😮 My changes do not introduce malicious code.
/ 我的更改没有引入恶意代码。

View File

@@ -11,6 +11,8 @@ reviewers:
- Larch-C
- anka-afk
- advent259141
- Fridemn
- LIghtJUNction
# - zouyonghe
# A number of reviewers added to the pull request

View File

@@ -15,7 +15,6 @@ Always reference these instructions first and fallback to search or bash command
### Running the Application
- Run main application: `uv run main.py` -- starts in ~3 seconds
- Application creates WebUI on http://localhost:6185 (default credentials: `astrbot`/`astrbot`)
- Application loads plugins automatically from `packages/` and `data/plugins/` directories
### Dashboard Build (Vue.js/Node.js)
- **Prerequisites**: Node.js 20+ and npm 10+ required
@@ -35,7 +34,7 @@ Always reference these instructions first and fallback to search or bash command
- **ALWAYS** run `uv run ruff check .` and `uv run ruff format .` before committing changes
### Plugin Development
- Plugins load from `packages/` (built-in) and `data/plugins/` (user-installed)
- Plugins load from `astrbot/builtin_stars/` (built-in) and `data/plugins/` (user-installed)
- Plugin system supports function tools and message handlers
- Key plugins: python_interpreter, web_searcher, astrbot, reminder, session_controller

View File

@@ -1,92 +0,0 @@
on:
push:
tags:
- 'v*'
workflow_dispatch:
name: Auto Release
jobs:
build-and-publish-to-github-release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Dashboard Build
run: |
cd dashboard
npm install
npm run build
echo "COMMIT_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
echo ${{ github.ref_name }} > dist/assets/version
zip -r dist.zip dist
- name: Upload to Cloudflare R2
env:
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
R2_BUCKET_NAME: "astrbot"
R2_OBJECT_NAME: "astrbot-webui-latest.zip"
VERSION_TAG: ${{ github.ref_name }}
run: |
echo "Installing rclone..."
curl https://rclone.org/install.sh | sudo bash
echo "Configuring rclone remote..."
mkdir -p ~/.config/rclone
cat <<EOF > ~/.config/rclone/rclone.conf
[r2]
type = s3
provider = Cloudflare
access_key_id = $R2_ACCESS_KEY_ID
secret_access_key = $R2_SECRET_ACCESS_KEY
endpoint = https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com
EOF
echo "Uploading dist.zip to R2 bucket: $R2_BUCKET_NAME/$R2_OBJECT_NAME"
mv dashboard/dist.zip dashboard/$R2_OBJECT_NAME
rclone copy dashboard/$R2_OBJECT_NAME r2:$R2_BUCKET_NAME --progress
mv dashboard/$R2_OBJECT_NAME dashboard/astrbot-webui-${VERSION_TAG}.zip
rclone copy dashboard/astrbot-webui-${VERSION_TAG}.zip r2:$R2_BUCKET_NAME --progress
mv dashboard/astrbot-webui-${VERSION_TAG}.zip dashboard/dist.zip
- name: Fetch Changelog
run: |
echo "changelog=changelogs/${{github.ref_name}}.md" >> "$GITHUB_ENV"
- name: Create GitHub Release
uses: ncipollo/release-action@v1
with:
bodyFile: ${{ env.changelog }}
artifacts: "dashboard/dist.zip"
build-and-publish-to-pypi:
# 构建并发布到 PyPI
runs-on: ubuntu-latest
needs: build-and-publish-to-github-release
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.10'
- name: Install uv
run: |
python -m pip install uv
- name: Build package
run: |
uv build
- name: Publish to PyPI
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
run: |
uv publish

49
.github/workflows/build-docs.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: Build and Deploy AstrBot Docs
on:
push:
tags:
- 'v*'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest # 运行环境
steps:
- name: checkout
uses: actions/checkout@v7
- name: Setup pnpm
uses: pnpm/action-setup@v6.0.9
with:
version: 10.28.2
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "24.13.0"
cache: "pnpm"
cache-dependency-path: docs/pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
working-directory: './docs'
- name: Build docs
run: pnpm run docs:build
working-directory: './docs'
- name: scp
uses: appleboy/scp-action@v1.0.0
with:
host: ${{ secrets.HOST_NEKO }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORDNEKO }}
source: 'docs/.vitepress/dist/*'
target: '/tmp/'
- name: script
uses: appleboy/ssh-action@v1.2.5
with:
host: ${{ secrets.HOST_NEKO }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORDNEKO }}
script: |
mkdir -p /root/docker_data/caddy/caddy_data/static_site/abv4/
rm -rf /root/docker_data/caddy/caddy_data/static_site/abv4/*
mv /tmp/docs/.vitepress/dist/* /root/docker_data/caddy/caddy_data/static_site/abv4/
rm -rf /tmp/docs/

View File

@@ -12,12 +12,12 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.10'
python-version: '3.12'
- name: Install UV
run: pip install uv

View File

@@ -56,11 +56,11 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v7
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -88,6 +88,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v7
with:
fetch-depth: 0
@@ -37,9 +37,10 @@ jobs:
mkdir -p data/temp
export TESTING=true
export ZHIPU_API_KEY=${{ secrets.OPENAI_API_KEY }}
pytest --cov=. -v -o log_cli=true -o log_level=DEBUG
pytest --cov=astrbot -v -o log_cli=true -o log_level=DEBUG
- name: Upload results to Codecov
uses: codecov/codecov-action@v5
if: github.repository == 'AstrBotDevs/AstrBot'
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -8,16 +8,30 @@ on:
jobs:
build:
if: github.repository == 'AstrBotDevs/AstrBot'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v7
- name: npm install, build
- name: Setup pnpm
uses: pnpm/action-setup@v6.0.9
with:
version: 10.28.2
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '24.13.0'
cache: "pnpm"
cache-dependency-path: dashboard/pnpm-lock.yaml
- name: Install and Build
working-directory: dashboard
run: |
cd dashboard
npm install
npm run build
pnpm install --frozen-lockfile
pnpm lint:check
pnpm run build
- name: Inject Commit SHA
id: get_sha
@@ -29,7 +43,7 @@ jobs:
zip -r dist.zip dist
- name: Archive production artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: dist-without-markdown
path: |
@@ -38,11 +52,11 @@ jobs:
- name: Create GitHub Release
if: github.event_name == 'push'
uses: ncipollo/release-action@v1
uses: ncipollo/release-action@v1.21.0
with:
tag: release-${{ github.sha }}
owner: AstrBotDevs
repo: astrbot-release-harbour
body: "Automated release from commit ${{ github.sha }}"
token: ${{ secrets.ASTRBOT_HARBOUR_TOKEN }}
artifacts: "dashboard/dist.zip"
artifacts: "dashboard/dist.zip"

View File

@@ -3,18 +3,132 @@ name: Docker Image CI/CD
on:
push:
tags:
- 'v*'
- "v*"
schedule:
# Run at 00:00 UTC every day
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
publish-docker:
build-nightly-image:
if: github.repository == 'AstrBotDevs/AstrBot' && github.event_name == 'schedule'
runs-on: ubuntu-latest
env:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
GHCR_OWNER: astrbotdevs
HAS_GHCR_TOKEN: ${{ secrets.GHCR_GITHUB_TOKEN != '' }}
steps:
- name: Pull The Codes
uses: actions/checkout@v5
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0 # Must be 0 so we can fetch tags
fetch-depth: 1
fetch-tag: true
- name: Check for new commits today
if: github.event_name == 'schedule'
id: check-commits
run: |
# Get commits from the last 24 hours
commits=$(git log --since="24 hours ago" --oneline)
if [ -z "$commits" ]; then
echo "No commits in the last 24 hours, skipping build"
echo "has_commits=false" >> $GITHUB_OUTPUT
else
echo "Found commits in the last 24 hours:"
echo "$commits"
echo "has_commits=true" >> $GITHUB_OUTPUT
fi
- name: Exit if no commits
if: github.event_name == 'schedule' && steps.check-commits.outputs.has_commits == 'false'
run: exit 0
- name: Build Dashboard
run: |
dashboard_version=$(python3 - <<'PY'
import tomllib
with open("pyproject.toml", "rb") as f:
print("v" + tomllib.load(f)["project"]["version"])
PY
)
cd dashboard
npm install
npm run build
mkdir -p dist/assets
echo "$dashboard_version" > dist/assets/version
cd ..
mkdir -p astrbot/dashboard
rm -rf astrbot/dashboard/dist
cp -r dashboard/dist astrbot/dashboard/dist
- name: Determine test image tags
id: test-meta
run: |
short_sha=$(echo "${GITHUB_SHA}" | cut -c1-12)
build_date=$(date +%Y%m%d)
echo "short_sha=$short_sha" >> $GITHUB_OUTPUT
echo "build_date=$build_date" >> $GITHUB_OUTPUT
- name: Set QEMU
uses: docker/setup-qemu-action@v4.1.0
- name: Set Docker Buildx
uses: docker/setup-buildx-action@v4.1.0
- name: Log in to DockerHub
uses: docker/login-action@v4.2.0
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
- name: Login to GitHub Container Registry
if: env.HAS_GHCR_TOKEN == 'true'
uses: docker/login-action@v4.2.0
with:
registry: ghcr.io
username: ${{ env.GHCR_OWNER }}
password: ${{ secrets.GHCR_GITHUB_TOKEN }}
- name: Build nightly image tags list
id: test-tags
run: |
TAGS="${{ env.DOCKER_HUB_USERNAME }}/astrbot:nightly-latest
${{ env.DOCKER_HUB_USERNAME }}/astrbot:nightly-${{ steps.test-meta.outputs.build_date }}-${{ steps.test-meta.outputs.short_sha }}"
if [ "${{ env.HAS_GHCR_TOKEN }}" = "true" ]; then
TAGS="$TAGS
ghcr.io/${{ env.GHCR_OWNER }}/astrbot:nightly-latest
ghcr.io/${{ env.GHCR_OWNER }}/astrbot:nightly-${{ steps.test-meta.outputs.build_date }}-${{ steps.test-meta.outputs.short_sha }}"
fi
echo "tags<<EOF" >> $GITHUB_OUTPUT
echo "$TAGS" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Build and Push Nightly Image
uses: docker/build-push-action@v7.2.0
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.test-tags.outputs.tags }}
- name: Post build notifications
run: echo "Test Docker image has been built and pushed successfully"
build-release-image:
if: github.repository == 'AstrBotDevs/AstrBot' && (github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')))
runs-on: ubuntu-latest
env:
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
GHCR_OWNER: astrbotdevs
HAS_GHCR_TOKEN: ${{ secrets.GHCR_GITHUB_TOKEN != '' }}
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 1
fetch-tag: true
- name: Get latest tag (only on manual trigger)
id: get-latest-tag
@@ -27,21 +141,22 @@ jobs:
if: github.event_name == 'workflow_dispatch'
run: git checkout ${{ steps.get-latest-tag.outputs.latest_tag }}
- name: Check if version is pre-release
id: check-prerelease
- name: Compute release metadata
id: release-meta
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
version="${{ steps.get-latest-tag.outputs.latest_tag }}"
else
version="${{ github.ref_name }}"
version="${GITHUB_REF#refs/tags/}"
fi
if [[ "$version" == *"beta"* ]] || [[ "$version" == *"alpha"* ]]; then
echo "is_prerelease=true" >> $GITHUB_OUTPUT
echo "Version $version is a pre-release, will not push latest tag"
echo "Version $version marked as pre-release"
else
echo "is_prerelease=false" >> $GITHUB_OUTPUT
echo "Version $version is a stable release, will push latest tag"
echo "Version $version marked as stable"
fi
echo "version=$version" >> $GITHUB_OUTPUT
- name: Build Dashboard
run: |
@@ -49,41 +164,43 @@ jobs:
npm install
npm run build
mkdir -p dist/assets
echo $(git rev-parse HEAD) > dist/assets/version
echo "${{ steps.release-meta.outputs.version }}" > dist/assets/version
cd ..
mkdir -p data
cp -r dashboard/dist data/
mkdir -p astrbot/dashboard
rm -rf astrbot/dashboard/dist
cp -r dashboard/dist astrbot/dashboard/dist
- name: Set QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4.1.0
- name: Set Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4.1.0
- name: Log in to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v4.2.0
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
if: env.HAS_GHCR_TOKEN == 'true'
uses: docker/login-action@v4.2.0
with:
registry: ghcr.io
username: Soulter
username: ${{ env.GHCR_OWNER }}
password: ${{ secrets.GHCR_GITHUB_TOKEN }}
- name: Build and Push Docker to DockerHub and Github GHCR
uses: docker/build-push-action@v6
- name: Build and Push Release Image
uses: docker/build-push-action@v7.2.0
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ steps.check-prerelease.outputs.is_prerelease == 'false' && format('{0}/astrbot:latest', secrets.DOCKER_HUB_USERNAME) || '' }}
${{ secrets.DOCKER_HUB_USERNAME }}/astrbot:${{ github.event_name == 'workflow_dispatch' && steps.get-latest-tag.outputs.latest_tag || github.ref_name }}
${{ steps.check-prerelease.outputs.is_prerelease == 'false' && 'ghcr.io/soulter/astrbot:latest' || '' }}
ghcr.io/soulter/astrbot:${{ github.event_name == 'workflow_dispatch' && steps.get-latest-tag.outputs.latest_tag || github.ref_name }}
${{ steps.release-meta.outputs.is_prerelease == 'false' && format('{0}/astrbot:latest', env.DOCKER_HUB_USERNAME) || '' }}
${{ steps.release-meta.outputs.is_prerelease == 'false' && env.HAS_GHCR_TOKEN == 'true' && format('ghcr.io/{0}/astrbot:latest', env.GHCR_OWNER) || '' }}
${{ format('{0}/astrbot:{1}', env.DOCKER_HUB_USERNAME, steps.release-meta.outputs.version) }}
${{ env.HAS_GHCR_TOKEN == 'true' && format('ghcr.io/{0}/astrbot:{1}', env.GHCR_OWNER, steps.release-meta.outputs.version) || '' }}
- name: Post build notifications
run: echo "Docker image has been built and pushed successfully"
run: echo "Release Docker image has been built and pushed successfully"

264
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,264 @@
name: Release AstrBot
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
ref:
description: "Git ref to build (branch/tag/SHA)"
required: false
default: "master"
tag:
description: "Release tag to publish assets to (for example: v4.14.6)"
required: false
permissions:
contents: write
jobs:
build-dashboard:
name: Build Dashboard
if: github.repository == 'AstrBotDevs/AstrBot'
runs-on: ubuntu-24.04
env:
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 0
ref: ${{ inputs.ref || github.ref }}
- name: Resolve tag
id: tag
shell: bash
run: |
if [ "${{ github.event_name }}" = "push" ]; then
tag="${GITHUB_REF_NAME}"
elif [ -n "${{ inputs.tag }}" ]; then
tag="${{ inputs.tag }}"
else
tag="$(git describe --tags --abbrev=0)"
fi
if [ -z "$tag" ]; then
echo "Failed to resolve tag." >&2
exit 1
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"
- name: Setup pnpm
uses: pnpm/action-setup@v6.0.9
with:
version: 10.28.2
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "24.13.0"
cache: "pnpm"
cache-dependency-path: dashboard/pnpm-lock.yaml
- name: Build dashboard dist
shell: bash
working-directory: dashboard
run: |
pnpm install --frozen-lockfile
pnpm run build
echo "${{ steps.tag.outputs.tag }}" > dist/assets/version
zip -r "AstrBot-${{ steps.tag.outputs.tag }}-dashboard.zip" dist
- name: Build core package
shell: bash
run: |
git archive \
--format=zip \
--prefix="AstrBot-${{ steps.tag.outputs.tag }}/" \
--output="AstrBot-${{ steps.tag.outputs.tag }}-core.zip" \
HEAD
- name: Upload dashboard artifact
uses: actions/upload-artifact@v7
with:
name: Dashboard-${{ steps.tag.outputs.tag }}
if-no-files-found: error
path: dashboard/AstrBot-${{ steps.tag.outputs.tag }}-dashboard.zip
- name: Upload release packages to Cloudflare R2
if: ${{ env.R2_ACCOUNT_ID != '' && env.R2_ACCESS_KEY_ID != '' && env.R2_SECRET_ACCESS_KEY != '' }}
env:
R2_BUCKET_NAME: "astrbot"
DASHBOARD_LATEST_OBJECT_NAME: "astrbot-webui-latest.zip"
CORE_LATEST_OBJECT_NAME: "astrbot-core-latest.zip"
VERSION_TAG: ${{ steps.tag.outputs.tag }}
shell: bash
run: |
curl https://rclone.org/install.sh | sudo bash
mkdir -p ~/.config/rclone
cat <<EOF > ~/.config/rclone/rclone.conf
[r2]
type = s3
provider = Cloudflare
access_key_id = $R2_ACCESS_KEY_ID
secret_access_key = $R2_SECRET_ACCESS_KEY
endpoint = https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com
EOF
cp "dashboard/AstrBot-${VERSION_TAG}-dashboard.zip" "dashboard/${DASHBOARD_LATEST_OBJECT_NAME}"
rclone copy "dashboard/${DASHBOARD_LATEST_OBJECT_NAME}" "r2:${R2_BUCKET_NAME}" --progress
cp "dashboard/AstrBot-${VERSION_TAG}-dashboard.zip" "dashboard/astrbot-webui-${VERSION_TAG}.zip"
rclone copy "dashboard/astrbot-webui-${VERSION_TAG}.zip" "r2:${R2_BUCKET_NAME}" --progress
cp "AstrBot-${VERSION_TAG}-core.zip" "${CORE_LATEST_OBJECT_NAME}"
rclone copy "${CORE_LATEST_OBJECT_NAME}" "r2:${R2_BUCKET_NAME}" --progress
cp "AstrBot-${VERSION_TAG}-core.zip" "astrbot-core-${VERSION_TAG}.zip"
rclone copy "astrbot-core-${VERSION_TAG}.zip" "r2:${R2_BUCKET_NAME}" --progress
rclone copyto "AstrBot-${VERSION_TAG}-core.zip" "r2:${R2_BUCKET_NAME}/astrbot-core/${VERSION_TAG}/source.zip" --progress
rclone copyto "AstrBot-${VERSION_TAG}-core.zip" "r2:${R2_BUCKET_NAME}/download/astrbot-core/${VERSION_TAG}/source.zip" --progress
publish-release:
name: Publish GitHub Release
if: github.repository == 'AstrBotDevs/AstrBot'
runs-on: ubuntu-24.04
needs:
- build-dashboard
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 0
ref: ${{ inputs.ref || github.ref }}
- name: Resolve tag
id: tag
shell: bash
run: |
if [ "${{ github.event_name }}" = "push" ]; then
tag="${GITHUB_REF_NAME}"
elif [ -n "${{ inputs.tag }}" ]; then
tag="${{ inputs.tag }}"
else
tag="$(git describe --tags --abbrev=0)"
fi
if [ -z "$tag" ]; then
echo "Failed to resolve tag." >&2
exit 1
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"
- name: Download dashboard artifact
uses: actions/download-artifact@v8
with:
name: Dashboard-${{ steps.tag.outputs.tag }}
path: release-assets
- name: Resolve release notes
id: notes
shell: bash
run: |
note_file="changelogs/${{ steps.tag.outputs.tag }}.md"
if [ ! -f "$note_file" ]; then
note_file="$(mktemp)"
echo "Release ${{ steps.tag.outputs.tag }}" > "$note_file"
fi
echo "file=$note_file" >> "$GITHUB_OUTPUT"
- name: Ensure release exists
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
tag="${{ steps.tag.outputs.tag }}"
if ! gh release view "$tag" >/dev/null 2>&1; then
gh release create "$tag" --title "$tag" --notes-file "${{ steps.notes.outputs.file }}"
fi
- name: Remove stale assets from release
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
tag="${{ steps.tag.outputs.tag }}"
while IFS= read -r asset; do
case "$asset" in
*.AppImage|*.dmg|*.zip|*.exe|*.blockmap)
gh release delete-asset "$tag" "$asset" -y || true
;;
esac
done < <(gh release view "$tag" --json assets --jq '.assets[].name')
- name: Upload assets to release
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
tag="${{ steps.tag.outputs.tag }}"
gh release upload "$tag" release-assets/* --clobber
publish-pypi:
name: Publish PyPI
if: github.repository == 'AstrBotDevs/AstrBot'
runs-on: ubuntu-24.04
needs:
- publish-release
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 0
ref: ${{ inputs.ref || github.ref }}
- name: Resolve tag
id: tag
shell: bash
run: |
if [ "${{ github.event_name }}" = "push" ]; then
tag="${GITHUB_REF_NAME}"
elif [ -n "${{ inputs.tag }}" ]; then
tag="${{ inputs.tag }}"
else
tag="$(git describe --tags --abbrev=0)"
fi
if [ -z "$tag" ]; then
echo "Failed to resolve tag." >&2
exit 1
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"
- name: Download dashboard artifact
uses: actions/download-artifact@v8
with:
name: Dashboard-${{ steps.tag.outputs.tag }}
path: dashboard-artifact
- name: Unpack dashboard dist into package tree
shell: bash
run: |
mkdir -p astrbot/dashboard/dist
unzip -q "dashboard-artifact/AstrBot-${{ steps.tag.outputs.tag }}-dashboard.zip" -d dashboard-artifact/unpacked
cp -r dashboard-artifact/unpacked/dist/. astrbot/dashboard/dist/
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.10"
- name: Install uv
shell: bash
run: python -m pip install uv
- name: Build package
shell: bash
# Dashboard assets are already in astrbot/dashboard/dist/;
# ASTRBOT_BUILD_DASHBOARD is intentionally unset so the hatch hook skips npm.
run: uv build
- name: Publish to PyPI
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
shell: bash
run: uv publish

61
.github/workflows/smoke_test.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
name: Smoke Test
on:
push:
branches:
- master
paths-ignore:
- "README*.md"
- "changelogs/**"
- "dashboard/**"
pull_request:
workflow_dispatch:
jobs:
smoke-test:
name: Run smoke tests
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install UV package manager
run: |
pip install uv
- name: Install dependencies
run: |
uv sync
timeout-minutes: 15
- name: Run smoke tests
run: |
uv run main.py &
# uv tool install -e . --force
# astrbot init -y
# astrbot run --backend-only &
APP_PID=$!
echo "Waiting for application to start..."
for i in {1..60}; do
if curl -f http://localhost:6185 > /dev/null 2>&1; then
echo "Application started successfully!"
kill $APP_PID
exit 0
fi
sleep 1
done
echo "Application failed to start within 30 seconds"
kill $APP_PID 2>/dev/null || true
exit 1
timeout-minutes: 2

View File

@@ -1,27 +1,65 @@
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
# 本工作流用于标记并关闭长期不活跃的 Issue。
# 目前仅针对带 `bug` 标签的 Issue 生效,不会处理 PR。
#
# You can adjust the behavior by modifying this file.
# For more information, see:
# https://github.com/actions/stale
name: Mark stale issues and pull requests
# 文档: https://github.com/actions/stale
name: Mark stale bug issues
on:
schedule:
- cron: '21 23 * * *'
# 每天 UTC 08:30 执行 (北京时间 16:30)
- cron: '30 8 * * *'
workflow_dispatch:
inputs:
dry-run:
description: '仅预览, 不实际执行 (Dry run mode)'
required: false
default: true
type: boolean
jobs:
stale:
if: github.repository == 'AstrBotDevs/AstrBot'
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Stale issue message'
stale-pr-message: 'Stale pull request message'
stale-issue-label: 'no-issue-activity'
stale-pr-label: 'no-pr-activity'
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
operations-per-run: 200
# 只处理带 bug 标签的 Issue
any-of-labels: 'bug'
# 不处理 PR
days-before-pr-stale: -1
days-before-pr-close: -1
# 不活跃判定与关闭策略: 先标记 stale, 再延迟关闭
days-before-issue-stale: 60
days-before-issue-close: 30
stale-issue-label: 'stale'
stale-issue-message: |
This issue has been automatically marked as **stale** because it has not had any activity.
It will be closed in a certain period of time if no further activity occurs.
If this issue is still relevant, please leave a comment.
---
该 Issue 已较长时间无活动, 已被标记为 `stale`。
如无后续活动, 将在一段时间后自动关闭。
如仍需跟进, 请回复评论。
close-issue-message: |
This issue has been automatically closed due to inactivity.
If the problem still exists, feel free to reopen or create a new issue with updated information.
---
该 Issue 因长期无活动已自动关闭。
如问题仍存在, 欢迎补充复现信息并重新打开或新建 Issue。
remove-stale-when-updated: true
debug-only: ${{ github.event_name == 'workflow_dispatch' && inputs.dry-run }}

69
.github/workflows/sync-wiki.yml vendored Normal file
View File

@@ -0,0 +1,69 @@
name: Sync AstrBot Docs to GitHub Wiki
on:
workflow_dispatch:
push:
branches:
- master
paths:
- '.github/workflows/sync-wiki.yml'
- 'docs/scripts/sync_docs_to_wiki.py'
- 'docs/tests/test_sync_docs_to_wiki.py'
- 'docs/zh/**'
- 'docs/en/**'
concurrency:
group: sync-wiki-${{ github.ref }}
cancel-in-progress: true
jobs:
sync:
if: github.repository == 'AstrBotDevs/AstrBot'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Validate manual ref
if: github.event_name == 'workflow_dispatch' && github.ref != 'refs/heads/master'
run: |
echo "This workflow only publishes from refs/heads/master. Re-run it from the master branch."
exit 1
- name: Check out docs repository
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Run sync unit tests
working-directory: docs
run: python -m unittest discover -s tests -p 'test_sync_docs_to_wiki.py' -v
- name: Validate internal doc links
run: python docs/scripts/sync_docs_to_wiki.py --source-root docs --check-links-only
- name: Clone AstrBot wiki
env:
WIKI_TOKEN: ${{ secrets.ASTRBOT_WIKI_TOKEN }}
run: |
test -n "$WIKI_TOKEN"
git clone "https://x-access-token:${WIKI_TOKEN}@github.com/AstrBotDevs/AstrBot.wiki.git" wiki
- name: Generate wiki pages
run: python docs/scripts/sync_docs_to_wiki.py --source-root docs --wiki-root wiki
- name: Commit and push wiki changes
working-directory: wiki
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add .
if git diff --cached --quiet; then
echo "No wiki changes to push"
exit 0
fi
git commit -m "docs: sync wiki from AstrBot-1/docs"
git push

37
.github/workflows/unit_tests.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: Unit Tests
on:
push:
branches:
- master
paths-ignore:
- 'README*.md'
- 'changelogs/**'
- 'dashboard/**'
pull_request:
workflow_dispatch:
jobs:
unit-tests:
name: Run pytest suite
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Install uv
run: |
python -m pip install --upgrade pip
python -m pip install uv
- name: Run tests
run: |
chmod +x scripts/run_pytests_ci.sh
bash ./scripts/run_pytests_ci.sh ./tests

106
.gitignore vendored
View File

@@ -1,33 +1,95 @@
# Python related
__pycache__
botpy.log
.vscode
.venv*
.idea
data_v2.db
data_v3.db
configs/session
configs/config.yaml
**/.DS_Store
temp
cmd_config.json
data
cookies.json
logs/
addons/plugins
.conda/
uv.lock
.coverage
# IDE and editors
.vscode
.idea
# Logs and temporary files
botpy.log
logs/
temp
cookies.json
# Data files
data_v2.db
data_v3.db
data
configs/session
configs/config.yaml
cmd_config.json
# Plugins
addons/plugins
astrbot/builtin_stars/python_interpreter/workplace
tests/astrbot_plugin_openai
chroma
# Dashboard
dashboard/node_modules/
dashboard/dist/
.DS_Store
.pnpm-store/
package-lock.json
package.json
yarn.lock
# Bundled dashboard dist (generated by hatch_build.py during pip wheel build)
astrbot/dashboard/dist/
# Operating System
**/.DS_Store
.DS_Store
# AstrBot specific
.astrbot
astrbot.lock
# Other
chroma
venv/*
packages/python_interpreter/workplace
.venv/*
.conda/
.idea
pytest.ini
.astrbot
IFLOW.md
CLAUDE.md
# genie_tts data
CharacterModels/
GenieData/
.agent/
.codex/
.claude/
.opencode/
.kilocode/
.serena
.worktrees/
.astrbot_sdk_testing/
.env
dashboard/warker.js
dashboard/bun.lock
.pua/
# Rust build artifacts
rust/target/
# Build outputs
dist/
*.whl
# 拓展模块
*.so
*.dll
# MDI font subset (generated by dashboard/scripts/subset-mdi-font.mjs)
dashboard/src/assets/mdi-subset/*.woff
dashboard/src/assets/mdi-subset/*.woff2
.planning
*cache
node_modules
*pinokio*
dashboard/pnpm-lock.yaml
.obsidian
dashboard/.codex
.codex
.zed/settings.json

View File

@@ -7,7 +7,19 @@ ci:
autoupdate_commit_msg: ":balloon: pre-commit autoupdate"
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.2
# Ruff version.
rev: v0.15.7
hooks:
- id: ruff
# Run the linter.
- id: ruff-check
types_or: [python, pyi]
args: [--fix]
# Run the formatter.
- id: ruff-format
types_or: [python, pyi]
- repo: https://github.com/asottile/pyupgrade
rev: v3.21.2
hooks:
- id: pyupgrade
args: [--py312-plus]

View File

@@ -1 +1 @@
3.10
3.12

257
AGENTS.md Normal file
View File

@@ -0,0 +1,257 @@
## Setup commands
### Core
```
uv tool install -e . --force
astrbot init
astrbot run # start the bot
astrbot run --backend-only # start the backend only
```
Exposed an API server on `http://localhost:6185` by default.
### Dashboard(WebUI)
```
cd dashboard
bun install # First time only.
bun dev
```
Runs on `http://localhost:3000` by default.
## Pre-commit setup
AstrBot uses [pre-commit](https://pre-commit.com/) hooks to automatically format and lint Python code before each commit. The hooks run `ruff check`, `ruff format`, and `pyupgrade` (see [`.pre-commit-config.yaml`](.pre-commit-config.yaml) for details).
To set it up:
```bash
pip install pre-commit
pre-commit install
```
After installation, the hooks will run automatically on `git commit`. You can also run them manually at any time:
```bash
ruff format .
ruff check .
```
> **Note:** If you use VSCode, install the `Ruff` extension for real-time formatting and linting in the editor.
## Dev environment tips
- **Main entry**: `astrbot/__main__.py` or via CLI `astrbot run`
- **CLI commands**: `astrbot/cli/commands/`
- **Core modules**: `astrbot/core/`
- **Platform adapters**: `astrbot/core/platform/sources/`
- **Star plugins**: `astrbot/builtin_stars/`
- **Dashboard**: `dashboard/` (Vue.js frontend)
## File Organization
```
astrbot/
├── __main__.py # Main entry point
├── __init__.py # Package init, exports
├── cli/ # CLI commands
│ └── commands/ # Individual command modules
├── core/ # Core functionality
│ ├── agent/ # Agent execution
│ ├── platform/ # Platform adapters
│ ├── pipeline/ # Message processing
│ ├── star/ # Plugin system
│ └── config/ # Configuration
├── builtin_stars/ # Built-in plugins
├── dashboard/ # Vue.js frontend
└── utils/ # Utilities
```
## Architecture
### Core Components
- `astrbot/core/` - Core bot functionality
- `astrbot/core/platform/` - Platform adapter system
- `astrbot/core/agent/` - Agent execution logic
- `astrbot/core/star/` - Plugin/Star handler system
- `astrbot/core/pipeline/` - Message processing pipeline
- `astrbot/cli/` - Command-line interface
### Important Utilities
```python
from astrbot.core.utils.astrbot_path import (
get_astrbot_root, # AstrBot root directory
get_astrbot_data_path, # Data directory
get_astrbot_config_path, # Config directory
get_astrbot_plugin_path, # Plugin directory
get_astrbot_temp_path, # Temp directory
get_astrbot_skills_path, # Skills directory
)
```
### Platform Adapters
Platform adapters are in `astrbot/core/platform/sources/`:
- Each adapter extends base platform classes
- Use `@register_platform_adapter` decorator
- Events flow through `commit_event()` to message queue
### Star (Plugin) System
Stars are plugins in `astrbot/builtin_stars/`:
- Extend `Star` base class
- Use decorators for command handlers: `@star.on_command`, `@star.on_message`, etc.
- Access via `context` object
## Code Style
1. **Type hints required** - Use Python 3.12+ syntax:
- `list[str]` not `List[str]`
- `int | None` not `Optional[int]`
- Avoid `Any` when possible. Use proper `TypedDict`, `dataclass`, or `Protocol` instead.
- When encountering dict access issues (e.g., `msg.get("key")` where type inference is wrong), define a `TypedDict` with `total=False` to explicitly declare allowed keys.
Good example:
```python
class MessageComponent(TypedDict, total=False):
type: str
text: str
path: str
```
Bad example (avoid):
```python
msg: Any = something
msg = cast(dict, msg)
```
2. **Path handling** - Always use `pathlib.Path`:
```python
from pathlib import Path
# Use astrbot.core.utils.path_utils for data/temp directories
from astrbot.core.utils.path_utils import get_astrbot_data_path
```
3. **Formatting** - Run before committing:
```bash
ruff format .
ruff check .
```
4. **Comments** - Use English for all comments and docstrings
5. **Imports** - Use absolute imports via `astrbot.` prefix
### Environment Variables
When adding new environment variables:
1. Use `ASTRBOT_` prefix: `ASTRBOT_ENABLE_FEATURE`
2. Add to `.env.example` with description
3. Update `astrbot/cli/commands/cmd_run.py`:
- Add to module docstring under "Environment Variables Used in Project"
- Add to `keys_to_print` list for debug output
## Testing
1. Tests go in `tests/` directory
2. Use `pytest` with `pytest-asyncio`
3. Run: `uv sync --group dev && uv run pytest --cov=astrbot tests/`
4. Test files: `test_*.py` or `*_test.py`
### Code Quality Scoring Test
The project enforces a **code quality score** via `tests/test_code_quality_typing.py`. All agents must treat this as a hard constraint when modifying code.
**Run the test:**
```bash
uv run pytest tests/test_code_quality_typing.py -v
```
**Scoring rules (target: 100/100, threshold for PASS: 80/100):**
| Pattern | Cost |
|---------|------|
| `cast(Any, ...)` | -1 pt each |
| `# type: ignore` | -0.5 pt each |
| **BAD** `# type: ignore[...]` (unresolved-import, class-alias, no-name-module, attr-defined, etc.) | **-3 pt each** |
| `bare except:` (no exception type) | -0.5 pt each |
| Duplicate code block (5+ identical lines, ≥2 occurrences) | -2 pt each |
**Why bad type: ignore is heavily penalized:**
- `# type: ignore[unresolved-import]` — hides missing module/stub issues
- `# type: ignore[class-alias]` — hides improper type alias patterns
- `# type: ignore[attr-defined]` — hides missing attribute errors
- These are **workarounds, not fixes** — they paper over real type errors
**Scoring formula:**
```
score = max(0, 100 - cast_any - type_ignore*0.5 - bad_type_ignore*3 - bare_except*0.5 - dup_blocks*2)
```
**Agent rules when modifying code:**
1. **Do not add** `# type: ignore[unresolved-import]` or `# type: ignore[class-alias]` — fix the underlying issue instead
2. **Do not use** `cast(Any, ...)` to suppress type errors — use proper type annotations
3. **Do not add** bare `except:` clauses — use `except SomeSpecificException:`
4. **Do not copy-paste** 5+ line blocks — extract to a shared helper function
5. Before committing, run the scoring test and ensure score ≥ 80
## Git Conventions
### Commit Messages
Use conventional commits:
```
feat: add new feature
fix: resolve bug
docs: update documentation
refactor: restructure code
test: add tests
chore: maintenance tasks
```
### PR Guidelines
1. Title: conventional commit format
2. Description: English
3. Target branch: `dev`
4. Keep changes focused and atomic
## Project-Specific Guidelines
1. **No report files** - Do not add `xxx_SUMMARY.md` or similar
2. **Componentization** - Maintain clean code, avoid duplication in WebUI
3. **Backward compatibility** - When deprecating, add warnings
4. **CLI help** - Run `astrbot help --all` to see all commands
5. When modifying frontend/dashboard code, use the project's custom request module `@/utils/request` for HTTP calls
6. For fetch or SSE URLs, use `resolveApiUrl('/api/your-path')` so the configured `VITE_API_BASE` and dev proxy rules are respected
7. Do not import the plain `axios` package directly in dashboard source files
## Common Tasks
### Adding a new platform adapter
1. Create adapter in `astrbot/core/platform/sources/`
2. Extend `Platform` base class
3. Use `@register_platform_adapter` decorator
4. Implement required methods: `run()`, `convert_message()`, `meta()`
### Adding a new command
1. Add to appropriate module in `cli/commands/`
2. Register with `@click.command()`
3. Update `astrbot/cli/__main__.py` to add command
### Adding a new Star handler
1. Create in `astrbot/builtin_stars/` or as plugin
2. Extend `Star` class
3. Use decorators: `@star.on_command()`, `@star.on_schedule()`, etc.
## Release versions
1. Replace current version name to specific version name.
2. Write changelog in `changelogs/`, you can refer to the full commit messages between the latest tag to the latest commit.
3. Make and push a commit into master branch with message format like: `chore: bump version to 4.25.0`
4. Create a tag and push the tag. For example: `git tag v4.25.0 && git push origin v4.25.0`

142
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,142 @@
# CONTRIBUTING
## 贡献指南
首先,感谢您花时间做出贡献!❤️
所有类型的贡献都受到鼓励和重视。有关不同的帮助方式和处理方式的详细信息,请参阅[目录](#目录)。在做出贡献之前,请确保阅读相关部分。这将使我们维护人员的工作变得更加容易,并为所有参与者带来顺畅的体验。社区期待您的贡献。🎉
### 目录
- [报告问题](#报告问题)
- [提交代码更改](#提交代码更改)
### 报告问题
如果您在使用 AstrBot 时遇到任何问题,请按照以下步骤报告:
1. **检查现有问题**:在提交新问题之前,请先检查 [Issues](https://github.com/AstrBotDevs/AstrBot/issues) 中是否已经存在类似的问题。
2. **创建新问题**:如果没有类似的问题,请创建一个新问题。请确保提供以下信息:
- 问题的简要描述
- 重现问题的步骤
- 预期结果和实际结果
- 相关日志或错误消息
### 提交代码更改
#### 分支命名
我们使用 `fix/` 前缀来修复错误,使用 `feat/` 前缀来添加新功能。对于 `fix/` 分支,请使用简短的描述,或者直接使用 Issue 编号。例如:`fix/1234` 或者 `fix/1234-login-typo`。对于 `feat/` 分支,请使用简短的描述,例如:`feat/add-user-profile`
#### PR 描述
- 请使用英文描述您的 PR。
- 标题请使用 `fix: `, `feat: `, `docs: `, `style: `, `refactor: `, `test: `, `chore: ` 等语义化前缀,并简要描述更改内容。如:`fix: correct login page typo`
#### 代码规范
##### Core
我们使用 Ruff 作为代码格式化和静态分析工具。在提交代码之前,请运行以下命令以确保代码符合规范:
```bash
ruff format .
ruff check .
```
如果您使用 VSCode可以安装 `Ruff` 插件。
##### PR 功能完整性验证(推荐)
如果您希望在本地做一套接近 CI 的完整验证,可使用:
```bash
make pr-test-neo
```
该命令会执行:
- `uv sync --group dev`
- `ruff format --check .``ruff check .`
- Neo 相关关键测试
- `main.py` 启动 smoke test检测 `http://localhost:6185`
需要全量验证时可使用:
```bash
make pr-test-full
```
如果只想快速重复执行(跳过依赖同步和 dashboard 构建):
```bash
make pr-test-full-fast
```
## Contributing Guide
First off, thanks for taking the time to contribute! ❤️
All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉
### Table of Contents
- [Reporting Issues](#reporting-issues)
- [Pull Requests](#pull-requests)
### Reporting Issues
If you encounter any issues while using AstrBot, please follow these steps to report them:
1. **Check Existing Issues**: Before submitting a new issue, please check if a similar issue already exists in the [Issues](https://github.com/AstrBotDevs/AstrBot/issues) section of the repository.
2. **Create a New Issue**: If no similar issue exists, please create a new issue. Make sure to provide the following information:
- A brief description of the issue
- Steps to reproduce the issue
- Expected and actual results
- Relevant logs or error messages
### Pull Requests
#### Branch Naming
We use the `fix/` prefix for bug fixes and the `feat/` prefix for new features. For `fix/` branches, please use a short description or directly use the Issue number, e.g., `fix/1234` or `fix/1234-login-typo`. For `feat/` branches, please use a short description, e.g., `feat/add-user-profile`.
#### PR Description
- Please use English to describe your PR.
- Use semantic prefixes like `fix: `, `feat: `, `docs: `, `style: `, `refactor: `, `test: `, `chore: ` in the title, followed by a brief description of the changes, e.g., `fix: correct login page typo`.
#### Code Style
##### Core
We use Ruff as our code formatter and static analysis tool. Before submitting your code, please run the following commands to ensure your code adheres to the style guidelines:
```bash
ruff format .
ruff check .
```
##### PR completeness checks (recommended)
To run a local validation flow close to CI, use:
```bash
make pr-test-neo
```
This command runs:
- `uv sync --group dev`
- `ruff format --check .` and `ruff check .`
- Neo-related critical tests
- a startup smoke test against `http://localhost:6185`
For full validation, use:
```bash
make pr-test-full
```
For faster repeated runs (skip dependency sync and dashboard build), use:
```bash
make pr-test-full-fast
```

View File

@@ -1,11 +1,9 @@
FROM python:3.11-slim
FROM python:3.12-slim
WORKDIR /AstrBot
COPY . /AstrBot/
RUN apt-get update && apt-get install -y --no-install-recommends \
nodejs \
npm \
gcc \
build-essential \
python3-dev \
@@ -13,23 +11,24 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libssl-dev \
ca-certificates \
bash \
ffmpeg \
libavcodec-extra \
curl \
gnupg \
git \
ripgrep \
&& curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN python -m pip install uv
RUN uv pip install -r requirements.txt --no-cache-dir --system
RUN uv pip install socksio uv pyffmpeg pilk --no-cache-dir --system
# 释出 ffmpeg
RUN python -c "from pyffmpeg import FFmpeg; ff = FFmpeg();"
# add /root/.pyffmpeg/bin/ffmpeg to PATH, inorder to use ffmpeg
RUN echo 'export PATH=$PATH:/root/.pyffmpeg/bin' >> ~/.bashrc
EXPOSE 6185
EXPOSE 6186
CMD [ "python", "main.py" ]
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN python -m pip install uv \
&& echo "3.12" > .python-version \
&& uv lock \
&& uv export --format requirements.txt --output-file requirements.txt --frozen \
&& uv pip install -r requirements.txt --no-cache-dir --system \
&& uv pip install socksio uv pilk --no-cache-dir --system
EXPOSE 6185
CMD ["python", "main.py"]

View File

@@ -1,35 +0,0 @@
FROM python:3.10-slim
WORKDIR /AstrBot
COPY . /AstrBot/
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
build-essential \
python3-dev \
libffi-dev \
libssl-dev \
curl \
unzip \
ca-certificates \
bash \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Installation of Node.js
ENV NVM_DIR="/root/.nvm"
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.2/install.sh | bash && \
. "$NVM_DIR/nvm.sh" && \
nvm install 22 && \
nvm use 22
RUN /bin/bash -c ". \"$NVM_DIR/nvm.sh\" && node -v && npm -v"
RUN python -m pip install uv
RUN uv pip install -r requirements.txt --no-cache-dir --system
RUN uv pip install socksio uv pyffmpeg --no-cache-dir --system
EXPOSE 6185
EXPOSE 6186
CMD ["python", "main.py"]

244
EULA.md Normal file
View File

@@ -0,0 +1,244 @@
# 最终用户许可协议EULA
> 我们热爱开源软件,并始终致力于为所有用户提供健康、安全、可靠的使用体验。 ❤️
For English edition, please refer to the section below the Chinese version.
**最后更新:** 2026-01-12
感谢您使用 **AstrBot**
在使用本项目之前,请仔细阅读以下声明内容。
**您一旦安装、运行或使用本项目,即表示您已阅读、理解并同意本声明中的全部内容。**
## 1. 项目性质
AstrBot 是一个遵循 **GNU Affero General Public License v3AGPLv3** 协议发布的**免费开源软件项目**。
* 截至目前AstrBot 项目未开展任何形式的商业化服务AstrBot 团队也未通过本项目向用户提供任何收费服务。若您因使用 AstrBot 被要求付费,请务必提高警惕,谨防诈骗行为。
* AstrBot 的代码实现未对任何第三方系统进行逆向工程、破解、反编译或绕过安全机制等行为。AstrBot 仅使用并支持各即时通讯IM平台官方公开提供的机器人接入接口、开放平台能力或相关通信协议进行集成与通信。
## 2. 无担保声明
AstrBot 按“**现状as is**”提供,不附带任何形式的明示或暗示担保。
AstrBot 团队不对以下内容作出任何保证:
* 系统本身的安全性、可靠性或稳定性;
* 任何第三方插件的安全性、正确性或可信度;
* 任何第三方 AI 模型或外部服务 API 的可用性、质量、准确性或安全性;
* 本软件对任何特定用途的适用性。
**您使用本软件所产生的一切风险均由您自行承担。**
## 3. 第三方插件与服务
* AstrBot 支持第三方插件及外部 AI 服务接入;
* AstrBot 团队**不对任何第三方插件、扩展或服务进行审计、控制、背书或担保**
* 因使用第三方插件或服务所产生的任何风险、损失、数据泄露或法律后果,均由用户自行承担。
* 第三方插件指代的是非 AstrBot 自带的插件AstrBot 自带的插件指代的是插件实现代码已经包含在 AstrBotDevs/AstrBot 代码库中的插件。插件市场中的插件都是第三方插件。
## 4. 使用与内容限制
您同意不会将 AstrBot 用于以下行为:
* 输入、生成、传播或处理任何违法、极端、暴力、色情、仇恨、辱骂或其他有害内容;
* 从事违反您所在国家或地区法律法规,或任何适用国际法律的行为;
* 试图绕过、关闭、削弱或破坏本系统内置的安全机制或内容限制。
* 任何侵犯他人合法权益、损害他人和自己身心健康、涉及个人隐私、个人信息等敏感内容的内容。
## 5. 项目用途说明
AstrBot 是一个**工具型对话与 Agent 系统**,在**安全、健康、友善**的前提下提供有限的人性化交互能力。
项目的主要目标是:
* 提供 Agent 能力与自动化辅助;
* 帮助用户提升工作、学习和信息处理效率;
* 在合理范围内提供友好的人机交互体验。
* 辅助用户成长,提供有益于用户身心健康的内容。
## 6. 安全措施说明
AstrBot 团队**已尽合理努力在技术和策略层面设置安全与内容约束机制**,以引导系统输出健康、友善、安全的内容。
但请理解:
* 世界上任何的系统均无法保证完全无误、绝对安全或无法被滥用;
* 用户仍有责任自行合理配置、监督并正确使用本系统。
如果您要关闭 AstrBot 默认启用的“健康模式”,请在 cmd_config.json 中将 `provider_settings.llm_safety_mode` 设置为 `False`。但请注意关闭健康模式不是推荐的使用方式可能导致系统输出不安全或不适当的内容。关闭该功能所产生的任何风险与后果均由用户自行承担AstrBot 团队不对此承担任何责任。
## 7. 心理健康提示
如果您在使用本项目过程中因系统输出内容而感到心理不适、情绪困扰,
或您本身正处于心理压力较大、情绪不稳定、焦虑、抑郁等状态并因此使用本项目,
请优先考虑寻求来自专业人士的帮助,例如心理咨询师、心理医生或当地心理援助机构。
如遇紧急情况(例如存在自伤或他伤风险),请立即联系当地的紧急救助电话或专业机构。
## 8. 统计信息与隐私说明
AstrBot 可能会收集有限的匿名统计信息,用于了解系统使用情况、发现问题以及持续改进项目。
所收集的统计信息仅包括与系统运行和功能使用相关的基础技术指标,例如功能使用频率、错误信息等。
AstrBot **不会收集、上传或存储您的对话内容、消息正文、输入文本,或任何能够识别您个人身份的敏感信息**
您可以手动关闭此项功能,通过在系统环境变量中设置 `ASTRBOT_DISABLE_METRICS=1` 来禁用匿名统计信息收集。
## 9. 责任限制
在法律允许的最大范围内AstrBot 团队不对因以下原因导致的任何直接或间接损失承担责任,包括但不限于:
* 使用或无法使用本软件;
* 使用第三方插件或服务;
* 系统生成的内容或输出;
* 数据丢失、服务中断或安全事件。
## 10. 条款的接受
您一旦安装、运行、修改或使用 AstrBot即确认
* 您已阅读并理解本声明内容;
* 您同意并接受上述所有条款;
* 您对自身使用行为承担全部责任。
如您不同意本声明的任何内容,请勿使用本项目。
## 11. 许可与版权
AstrBot 的源代码、文档及相关内容受版权法及相关法律保护。
在遵守本声明及 AGPLv3 协议的前提下AstrBot 授予您一项非独占、不可转让、不可再许可的许可,用于下载、安装、运行、修改和分发本软件。
除非法律另有规定或本声明另有明确说明AstrBot 团队保留本项目的所有未明确授予的权利。
## 12. 适用法律
本声明的解释与适用应遵循您所在地或项目发布地适用的法律法规。
如本声明的任何条款被认定为无效或不可执行,其余条款仍然有效。
---
# EULA
> We love open-source software and are always committed to providing all users with a healthy, safe, and reliable experience. ❤️
**Last updated:** January 12, 2026
Thank you for using **AstrBot**.
Please read the following notice carefully before using this project.
**By installing, running, or using this project, you acknowledge that you have read, understood, and agreed to all the terms stated below.**
## 1. Nature of the Project
AstrBot is a **free and open-source software project** released under the **GNU Affero General Public License v3 (AGPLv3)**.
* AstrBot does not constitute any form of commercial service;
* The AstrBot Team does not provide any paid services through this project;
* AstrBots implementation does not involve reverse engineering, cracking, decompilation, or circumvention of security mechanisms of any third-party systems. AstrBot only uses and supports officially published bot integration interfaces, open platform capabilities, or related communication protocols provided by instant messaging (IM) platforms for integration and communication.
## 2. No Warranty
AstrBot is provided **“as is”**, without any express or implied warranties.
The AstrBot Team makes no guarantees regarding:
* The security, reliability, or stability of the system;
* The security, correctness, or trustworthiness of any third-party plugins;
* The availability, quality, accuracy, or safety of any third-party AI model APIs or external services;
* The fitness of the software for any particular purpose.
**All risks arising from the use of this software are borne solely by the user.**
## 3. Third-Party Plugins and Services
* AstrBot supports third-party plugins and external AI services;
* The AstrBot Team does **not audit, control, endorse, or guarantee** any third-party plugins, extensions, or services;
* Any risks, losses, data leaks, or legal consequences arising from the use of third-party plugins or services are solely the responsibility of the user;
* “Third-party plugins” refer to plugins that are not built into AstrBot. Built-in plugins are those whose implementation code is included in the AstrBotDevs/AstrBot repository. All plugins available in the plugin marketplace are third-party plugins.
## 4. Usage and Content Restrictions
You agree not to use AstrBot for any of the following activities:
* Inputting, generating, distributing, or processing any illegal, extremist, violent, pornographic, hateful, abusive, or otherwise harmful content;
* Engaging in activities that violate the laws or regulations of your country or region, or any applicable international laws;
* Attempting to bypass, disable, weaken, or undermine the built-in safety mechanisms or content restrictions of the system;
* Any activities that infringe upon the legitimate rights and interests of others, harm the physical or mental well-being of yourself or others, or involve personal privacy or sensitive personal information.
## 5. Intended Use
AstrBot is a **tool-oriented conversational and agent system** that provides limited human-like interaction capabilities under the principles of **safety, health, and friendliness**.
The primary goals of the project are to:
* Provide agent capabilities and automation assistance;
* Help users improve efficiency in work, study, and information processing;
* Offer a friendly humancomputer interaction experience within reasonable boundaries;
* Support user growth and provide content beneficial to users physical and mental well-being.
## 6. Safety Measures
The AstrBot Team has made **reasonable efforts** at both technical and policy levels to implement safety and content restriction mechanisms, guiding the system to produce healthy, friendly, and safe outputs.
However, please understand that:
* No system in the world can be guaranteed to be completely error-free, absolutely secure, or immune to misuse;
* Users remain responsible for properly configuring, supervising, and using the system.
If you wish to disable AstrBots default “Safety Mode,” please set `provider_settings.llm_safety_mode` to `False` in `cmd_config.json`. However, please note that disabling Safety Mode is not recommended and may lead to unsafe or inappropriate outputs. Any risks or consequences arising from disabling this feature are solely borne by the user, and the AstrBot Team assumes no responsibility.
## 7. Mental Health Notice
If you experience psychological discomfort or emotional distress due to system outputs during use,
or if you are experiencing significant psychological stress, emotional instability, anxiety, or depression and are using this project for such reasons,
please prioritize seeking help from qualified professionals, such as psychologists, psychiatrists, or local mental health support services.
In case of emergency (for example, if there is a risk of self-harm or harm to others), please immediately contact your local emergency number or professional crisis support services.
## 8. Metrics and Privacy
AstrBot may collect a limited amount of anonymous usage statistics to understand system usage, identify issues, and continuously improve the project.
Collected metrics are limited to basic technical indicators related to system operation and feature usage, such as feature usage frequency and error information.
AstrBot **does not collect, upload, or store your conversation content, message bodies, input text, or any personally identifiable or sensitive information**.
You may manually disable this feature by setting the environment variable `ASTRBOT_DISABLE_METRICS=1` to turn off anonymous metrics collection.
## 9. Limitation of Liability
To the maximum extent permitted by law, the AstrBot Team shall not be liable for any direct or indirect losses arising from, including but not limited to:
* The use or inability to use this software;
* The use of third-party plugins or services;
* Generated content or system outputs;
* Data loss, service interruptions, or security incidents.
## 10. Acceptance of Terms
By installing, running, modifying, or using AstrBot, you confirm that:
* You have read and understood this Notice;
* You agree to and accept all the terms stated above;
* You assume full responsibility for your use of the software.
If you do not agree with any part of this Notice, please do not use this project.
## 11. License and Copyright
The source code, documentation, and related materials of AstrBot are protected by copyright laws and applicable regulations.
Subject to compliance with this Notice and the AGPLv3 license, AstrBot grants you a non-exclusive, non-transferable, non-sublicensable license to download, install, run, modify, and distribute this software.
Unless otherwise required by law or expressly stated in this Notice, the AstrBot Team reserves all rights not expressly granted.
## 12. Governing Law
The interpretation and application of this Notice shall be governed by the laws and regulations applicable in your jurisdiction or the jurisdiction where the project is released.
If any provision of this Notice is held to be invalid or unenforceable, the remaining provisions shall remain in full force and effect.

16
FIRST_NOTICE.en-US.md Normal file
View File

@@ -0,0 +1,16 @@
## Welcome to AstrBot
🌟 Thank you for using AstrBot!
AstrBot is an Agentic AI assistant for personal and group chats, with support for multiple IM platforms and a wide range of built-in features. We hope it brings you an efficient and enjoyable experience. ❤️
Important notice:
AstrBot is a **free and open-source software project** protected by the AGPLv3 license. You can find the full source code and related resources on our [**official website**](https://astrbot.app) and [**GitHub**](https://github.com/astrbotdevs/astrbot).
As of now, AstrBot has **no commercial services of any kind**, and the official team **will never charge users any fees** under any name.
If anyone asks you to pay while using AstrBot, **you are likely being scammed**. Please request a refund immediately and report it to us by email.
📊 Please read the [End User License Agreement](https://github.com/AstrBotDevs/AstrBot/blob/master/EULA.md) carefully before using this project. By installing, you agree to all its contents.
📮 Official email: [community@astrbot.app](mailto:community@astrbot.app)

16
FIRST_NOTICE.md Normal file
View File

@@ -0,0 +1,16 @@
## 欢迎使用 AstrBot
🌟 感谢您使用 AstrBot
AstrBot 是一款可接入多种 IM 平台的 Agentic AI 个人 / 群聊助手,内置多项强大功能,希望能为您带来高效、愉快的使用体验。❤️
我们想特别说明:
AstrBot 是受 AGPLv3 开源协议保护的**免费开源软件项目**,您可以在[**官方网站**](https://astrbot.app)、[**GitHub**](https://github.com/astrbotdevs/astrbot) 上找到 AstrBot 的全部源代码及相关资源。
截至目前AstrBot 项目**未开展任何形式的商业化服务**,官方**不会以任何名义向用户收取费用**。
如果您在使用 AstrBot 的过程中被要求付费,**表明您已经遭遇诈骗行为**。请立即向相关方申请退款,并及时通过邮件向我们反馈。
📊 在使用本项目之前,请仔细阅读 [最终用户许可协议](https://github.com/AstrBotDevs/AstrBot/blob/master/EULA.md)。安装即表示您已阅读并同意其中的全部内容。
📮 官方邮箱:[community@astrbot.app](mailto:community@astrbot.app)

16
FIRST_NOTICE.ru-RU.md Normal file
View File

@@ -0,0 +1,16 @@
## Добро пожаловать в AstrBot
🌟 Спасибо, что используете AstrBot!
AstrBot — это Agentic AI-ассистент для личных и групповых чатов с поддержкой множества IM-платформ и широким набором встроенных функций. Надеемся, что он сделает ваше общение эффективным и приятным. ❤️
Важное уведомление:
AstrBot — это **бесплатный проект с открытым исходным кодом**, защищённый лицензией AGPLv3. Полный исходный код и связанные ресурсы доступны на [**официальном сайте**](https://astrbot.app) и [**GitHub**](https://github.com/astrbotdevs/astrbot).
На данный момент AstrBot **не предоставляет никаких коммерческих услуг**, и официальная команда **никогда не будет взимать плату с пользователей** под каким-либо названием.
Если кто-то просит вас заплатить при использовании AstrBot, **вас, скорее всего, пытаются обмануть**. Немедленно запросите возврат средств и сообщите нам по электронной почте.
📊 Пожалуйста, внимательно прочитайте [Лицензионное соглашение](https://github.com/AstrBotDevs/AstrBot/blob/master/EULA.md) перед использованием. Устанавливая программу, вы соглашаетесь со всеми его условиями.
📮 Официальная почта: [community@astrbot.app](mailto:community@astrbot.app)

41
Makefile Normal file
View File

@@ -0,0 +1,41 @@
.PHONY: worktree worktree-add worktree-rm pr-test-neo pr-test-full pr-test-full-fast
WORKTREE_DIR ?= ../astrbot_worktree
BRANCH ?= $(word 2,$(MAKECMDGOALS))
BASE ?= $(word 3,$(MAKECMDGOALS))
BASE ?= master
worktree:
@echo "Usage:"
@echo " make worktree-add <branch> [base-branch]"
@echo " make worktree-rm <branch>"
worktree-add:
ifeq ($(strip $(BRANCH)),)
$(error Branch name required. Usage: make worktree-add <branch> [base-branch])
endif
@mkdir -p $(WORKTREE_DIR)
git worktree add $(WORKTREE_DIR)/$(BRANCH) -b $(BRANCH) $(BASE)
worktree-rm:
ifeq ($(strip $(BRANCH)),)
$(error Branch name required. Usage: make worktree-rm <branch>)
endif
@if [ -d "$(WORKTREE_DIR)/$(BRANCH)" ]; then \
git worktree remove $(WORKTREE_DIR)/$(BRANCH); \
else \
echo "Worktree $(WORKTREE_DIR)/$(BRANCH) not found."; \
fi
pr-test-neo:
./scripts/pr_test_env.sh --profile neo
pr-test-full:
./scripts/pr_test_env.sh --profile full
pr-test-full-fast:
./scripts/pr_test_env.sh --profile full --skip-sync --no-dashboard
# Swallow extra args (branch/base) so make doesn't treat them as targets
%:
@true

373
README.md
View File

@@ -1,213 +1,288 @@
<img width="430" height="31" alt="image" src="https://github.com/user-attachments/assets/474c822c-fab7-41be-8c23-6dae252823ed" /><p align="center">
![AstrBot-Logo-Simplified](https://github.com/user-attachments/assets/ffd99b6b-3272-4682-beaa-6fe74250f7d9)
![astrbot-github-banner-v2-light-0405_副本](https://github.com/user-attachments/assets/36fb04e4-cc75-4454-bd8b-049d11aa86f9)
</p>
<div align="center">
<a href="https://trendshift.io/repositories/12875" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12875" alt="Soulter%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh.md">简体中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh-TW.md">繁體中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ja.md">日本語</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_fr.md">Français</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ru.md">Русский</a>
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/Soulter/AstrBot?style=for-the-badge&color=76bad9)](https://github.com/Soulter/AstrBot/releases/latest)
<img src="https://img.shields.io/badge/python-3.10+-blue.svg?style=for-the-badge&color=76bad9" alt="python">
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg?style=for-the-badge&color=76bad9"/></a>
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=wtbaNx7EioxeaqS9z7RQWVXPIxg2zYr7&jump_from=webapi&authKey=vlqnv/AV2DbJEvGIcxdlNSpfxVy+8vVqijgreRdnVKOaydpc+YSw4MctmEbr0k5"><img alt="QQ_community" src="https://img.shields.io/badge/QQ群-775869627-purple?style=for-the-badge&color=76bad9"></a>
<a href="https://t.me/+hAsD2Ebl5as3NmY1"><img alt="Telegram_community" src="https://img.shields.io/badge/Telegram-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
[![wakatime](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e.svg?style=for-the-badge&color=76bad9)](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e)
![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fplugin-num&query=%24.result&suffix=%E4%B8%AA&style=for-the-badge&label=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&cacheSeconds=3600)
<br>
<a href="https://github.com/Soulter/AstrBot/blob/master/README_en.md">English</a>
<a href="https://github.com/Soulter/AstrBot/blob/master/README_ja.md">日本語</a>
<a href="https://astrbot.app/">查看文档</a>
<a href="https://github.com/Soulter/AstrBot/issues">问题提交</a>
<div>
<a href="https://trendshift.io/repositories/21369" target="_blank"><img src="https://trendshift.io/api/badge/repositories/21369" alt="AstrBotDevs%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://hellogithub.com/repository/AstrBotDevs/AstrBot" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=d127d50cd5e54c5382328acc3bb25483&claim_uid=ZO9by7qCXgSd6Lp&t=2" alt="FeaturedHelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
</div>
AstrBot 是一个开源的一站式 Agentic 聊天机器人平台及开发框架。
<br>
## 主要功能
<div>
<img src="https://img.shields.io/github/v/release/AstrBotDevs/AstrBot?color=76bad9" href="https://github.com/AstrBotDevs/AstrBot/releases/latest">
<img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="python">
<img src="https://deepwiki.com/badge.svg" href="https://deepwiki.com/AstrBotDevs/AstrBot">
<a href="https://zread.ai/AstrBotDevs/AstrBot" target="_blank"><img src="https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff" alt="zread"/></a>
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg?color=76bad9"/></a>
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fplugin-num&query=%24.result&suffix=%20plugins&label=Marketplace&cacheSeconds=3600">
<img src="https://gitcode.com/Soulter/AstrBot/star/badge.svg" href="https://gitcode.com/Soulter/AstrBot">
</div>
1. **大模型对话**。支持接入多种大模型服务。支持多模态、工具调用、MCP、原生知识库、人设等功能。
2. **多消息平台支持**。支持接入 QQ、企业微信、微信公众号、飞书、Telegram、钉钉、Discord、KOOK 等平台。支持速率限制、白名单、百度内容审核。
3. **Agent**。完善适配的 Agentic 能力。支持多轮工具调用、内置沙盒代码执行器、网页搜索等功能。
4. **插件扩展**。深度优化的插件机制,支持[开发插件](https://astrbot.app/dev/plugin.html)扩展功能,社区插件生态丰富。
5. **WebUI**。可视化配置和管理机器人,功能齐全。
<br>
## 部署方式
<a href="https://astrbot.app/">Documentation</a>
<a href="https://blog.astrbot.app/">Blog</a>
<a href="https://astrbot.featurebase.app/roadmap">Roadmap</a>
<a href="https://github.com/AstrBotDevs/AstrBot/issues">Issue Tracker</a>
<a href="mailto:community@astrbot.app">Email Support</a>
</div>
#### Docker 部署
AstrBot is an open-source all-in-one Agent chatbot platform that integrates with mainstream instant messaging apps. It provides reliable and scalable conversational AI infrastructure for individuals, developers, and teams. Whether you're building a personal AI companion, intelligent customer service, automation assistant, or enterprise knowledge base, AstrBot enables you to quickly build production-ready AI applications within your IM platform workflows.
推荐使用 Docker / Docker Compose 方式部署 AstrBot。
![screenshot_1 5x_postspark_2026-02-27_22-37-45](https://github.com/user-attachments/assets/f17cdb90-52d7-4773-be2e-ff64b566af6b)
请参阅官方文档 [使用 Docker 部署 AstrBot](https://astrbot.app/deploy/astrbot/docker.html#%E4%BD%BF%E7%94%A8-docker-%E9%83%A8%E7%BD%B2-astrbot) 。
## Key Features
#### 宝塔面板部署
1. 💯 Free & Open Source.
2. ✨ AI LLM Conversations, Multimodal, Agent, MCP, Skills, Knowledge Base, Persona Settings, Auto Context Compression.
3. 🤖 Supports integration with Dify, Alibaba Cloud Bailian, Coze, and other agent platforms.
4. 🌐 Multi-Platform: QQ, WeChat Work, Feishu, DingTalk, WeChat Official Accounts, Telegram, Slack, and [more](#supported-messaging-platforms).
5. 📦 Plugin Extensions with 1000+ plugins available for one-click installation.
6. 🛡️ [Agent Sandbox](https://docs.astrbot.app/use/astrbot-agent-sandbox.html) for isolated, safe execution of code, shell calls, and session-level resource reuse.
7. 💻 WebUI Support.
8. 🌈 Web ChatUI Support with built-in agent sandbox and web search.
9. 🌐 Internationalization (i18n) Support.
AstrBot 与宝塔面板合作,已上架至宝塔面板。
<br>
请参阅官方文档 [宝塔面板部署](https://astrbot.app/deploy/astrbot/btpanel.html) 。
<table align="center">
<tr align="center">
<th>💙 Role-playing & Emotional Companionship</th>
<th>✨ Proactive Agent</th>
<th>🚀 General Agentic Capabilities</th>
<th>🧩 1000+ Community Plugins</th>
</tr>
<tr>
<td align="center"><p align="center"><img width="984" height="1746" alt="99b587c5d35eea09d84f33e6cf6cfd4f" src="https://github.com/user-attachments/assets/89196061-3290-458d-b51f-afa178049f84" /></p></td>
<td align="center"><p align="center"><img width="976" height="1612" alt="c449acd838c41d0915cc08a3824025b1" src="https://github.com/user-attachments/assets/f75368b4-e022-41dc-a9e0-131c3e73e32e" /></p></td>
<td align="center"><p align="center"><img width="974" height="1732" alt="image" src="https://github.com/user-attachments/assets/e22a3968-87d7-4708-a7cd-e7f198c7c32e" /></p></td>
<td align="center"><p align="center"><img width="976" height="1734" alt="image" src="https://github.com/user-attachments/assets/0952b395-6b4a-432a-8a50-c294b7f89750" /></p></td>
</tr>
</table>
#### 1Panel 部署
## Quick Start
AstrBot 已由 1Panel 官方上架至 1Panel 面板。
### One-Click Deployment
请参阅官方文档 [1Panel 部署](https://astrbot.app/deploy/astrbot/1panel.html) 。
For users who want to quickly experience AstrBot, are familiar with command-line usage, and can install a `uv` environment on their own, we recommend the `uv` one-click deployment method ⚡️:
#### 在 雨云 上部署
```bash
uv tool install astrbot --python 3.12
astrbot init # Only execute this command for the first time to initialize the environment
astrbot run
```
AstrBot 已由雨云官方上架至云应用平台,可一键部署。
> Requires [uv](https://docs.astral.sh/uv/) to be installed.
> AstrBot requires Python 3.12 or later. The `--python 3.12` option ensures that `uv` creates the tool environment with Python 3.12.
> [!NOTE]
> For macOS users: due to macOS security checks, the first run of the `astrbot` command may take longer (about 10-20s).
Update `astrbot`:
```bash
uv tool upgrade astrbot --python 3.12
```
> [!WARNING]
> AstrBot deployed via `uv` **does not support upgrading through the WebUI**. To update, please run the command above from the command line.
### Docker Deployment
For users familiar with containers and looking for a more stable, production-ready deployment method, we recommend deploying AstrBot with Docker / Docker Compose.
Please refer to the official documentation: [Deploy AstrBot with Docker](https://docs.astrbot.app/deploy/astrbot/docker.html#%E4%BD%BF%E7%94%A8-docker-%E9%83%A8%E7%BD%B2-astrbot).
### Deploy on RainYun
For users who want one-click deployment and do not want to manage servers themselves, we recommend RainYun's one-click cloud deployment service ☁️:
[![Deploy on RainYun](https://rainyun-apps.cn-nb1.rains3.com/materials/deploy-on-rainyun-en.svg)](https://app.rainyun.com/apps/rca/store/5994?ref=NjU1ODg0)
#### 在 Replit 上部署
### Desktop Application Deployment
社区贡献的部署方式。
For users who want to use AstrBot on desktop and mainly use ChatUI, we recommend AstrBot App.
[![Run on Repl.it](https://repl.it/badge/github/Soulter/AstrBot)](https://repl.it/github/Soulter/AstrBot)
Visit [AstrBot-desktop](https://github.com/AstrBotDevs/AstrBot-desktop) to download and install; this method is designed for desktop usage and is not recommended for server scenarios.
#### Windows 一键安装器部署
### Launcher Deployment
请参阅官方文档 [使用 Windows 一键安装器部署 AstrBot](https://astrbot.app/deploy/astrbot/windows.html) 。
For desktop users who also want fast deployment and isolated multi-instance usage, we recommend AstrBot Launcher.
#### CasaOS 部署
Visit [AstrBot Launcher](https://github.com/Raven95676/astrbot-launcher) to download and install.
社区贡献的部署方式。
### Deploy on Replit
请参阅官方文档 [CasaOS 部署](https://astrbot.app/deploy/astrbot/casaos.html) 。
Replit deployment is maintained by the community and is suitable for online demos and lightweight trials.
#### 手动部署
[![Run on Repl.it](https://repl.it/badge/github/AstrBotDevs/AstrBot)](https://repl.it/github/AstrBotDevs/AstrBot)
首先安装 uv
### AUR
AUR deployment targets Arch Linux users who prefer installing AstrBot through the system package workflow.
Run the command below to install `astrbot-git`, then start AstrBot in your local environment.
```bash
pip install uv
yay -S astrbot-git
```
通过 Git Clone 安装 AstrBot
**More deployment methods**
If you need panel-based management or deeper customization, see [BT-Panel Deployment](https://docs.astrbot.app/deploy/astrbot/btpanel.html) for BT Panel app-store setup, [1Panel Deployment](https://docs.astrbot.app/deploy/astrbot/1panel.html) for 1Panel app-market deployment, [CasaOS Deployment](https://docs.astrbot.app/deploy/astrbot/casaos.html) for NAS/home-server visual deployment, and [Manual Deployment](https://docs.astrbot.app/deploy/astrbot/cli.html) for fully custom source-based installation with `uv`.
## Supported Messaging Platforms
Connect AstrBot to your favorite chat platform.
| Platform | Maintainer |
|---------|---------------|
| QQ | Official |
| OneBot v11 protocol implementation | Official |
| Telegram | Official |
| Wecom & Wecom AI Bot | Official |
| WeChat Official Accounts | Official |
| Feishu (Lark) | Official |
| DingTalk | Official |
| Slack | Official |
| Discord | Official |
| LINE | Official |
| Satori | Official |
| KOOK | Official |
| Misskey | Official |
| Mattermost | Official |
| WhatsApp (Coming Soon) | Official |
| [Matrix](https://github.com/stevessr/astrbot_plugin_matrix_adapter) | Community |
| [Rocket.Chat](https://github.com/NET-Homeless/astrbot_plugin_rocket_chat_adapter) | Community |
| [VoceChat](https://github.com/HikariFroya/astrbot_plugin_vocechat) | Community |
## Supported Model Services
| Service | Type |
|---------|---------------|
| OpenAI and Compatible Services | LLM Services |
| Anthropic | LLM Services |
| Google Gemini | LLM Services |
| Moonshot AI | LLM Services |
| Zhipu AI | LLM Services |
| DeepSeek | LLM Services |
| Ollama (Self-hosted) | LLM Services |
| LM Studio (Self-hosted) | LLM Services |
| [AIHubMix](https://aihubmix.com/?aff=4bfH) | LLM Services (API Gateway, supports all models) |
| [CompShare](https://www.compshare.cn/?ytag=GPU_YY-gh_astrbot&referral_code=FV7DcGowN4hB5UuXKgpE74) | LLM Services |
| [302.AI](https://share.302.ai/rr1M3l) | LLM Services |
| [TokenPony](https://www.tokenpony.cn/3YPyf) | LLM Services |
| [SiliconFlow](https://docs.siliconflow.cn/cn/usercases/use-siliconcloud-in-astrbot) | LLM Services |
| [PPIO Cloud](https://ppio.com/user/register?invited_by=AIOONE) | LLM Services |
| ModelScope | LLM Services |
| OneAPI | LLM Services |
| Dify | LLMOps Platforms |
| Alibaba Cloud Bailian Applications | LLMOps Platforms |
| Coze | LLMOps Platforms |
| OpenAI Whisper | Speech-to-Text Services |
| SenseVoice | Speech-to-Text Services |
| Xiaomi MiMo Omni | Speech-to-Text Services |
| OpenAI TTS | Text-to-Speech Services |
| Gemini TTS | Text-to-Speech Services |
| GPT-Sovits-Inference | Text-to-Speech Services |
| GPT-Sovits | Text-to-Speech Services |
| FishAudio | Text-to-Speech Services |
| Edge TTS | Text-to-Speech Services |
| Alibaba Cloud Bailian TTS | Text-to-Speech Services |
| Azure TTS | Text-to-Speech Services |
| Minimax TTS | Text-to-Speech Services |
| Xiaomi MiMo TTS | Text-to-Speech Services |
| Volcano Engine TTS | Text-to-Speech Services |
## ❤️ Sponsors
<p align="center">
<img alt="sponsors" src="https://sponsors.astrbot.app/?v=1">
</p>
## ❤️ Contributing
Issues and Pull Requests are always welcome! Feel free to submit your changes to this project :)
### How to Contribute
You can contribute by reviewing issues or helping with pull request reviews. Any issues or PRs are welcome to encourage community participation. Of course, these are just suggestions—you can contribute in any way you like. For adding new features, please discuss through an Issue first.
### Development Environment
AstrBot uses `ruff` for code formatting and linting.
```bash
git clone https://github.com/AstrBotDevs/AstrBot && cd AstrBot
uv run main.py
```
或者请参阅官方文档 [通过源码部署 AstrBot](https://astrbot.app/deploy/astrbot/cli.html) 。
## 🌍 社区
### QQ 群组
- 1 群322154837
- 3 群630166526
- 5 群822130018
- 6 群753075035
- 开发者群975206796
- 开发者群备份295657329
### Telegram 群组
<a href="https://t.me/+hAsD2Ebl5as3NmY1"><img alt="Telegram_community" src="https://img.shields.io/badge/Telegram-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
### Discord 群组
<a href="https://discord.gg/hAVk6tgV36"><img alt="Discord_community" src="https://img.shields.io/badge/Discord-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
## ⚡ 消息平台支持情况
| 平台 | 支持性 |
| -------- | ------- |
| QQ(官方机器人接口) | ✔ |
| QQ(OneBot) | ✔ |
| Telegram | ✔ |
| 企业微信 | ✔ |
| 微信客服 | ✔ |
| 微信公众号 | ✔ |
| 飞书 | ✔ |
| 钉钉 | ✔ |
| Slack | ✔ |
| Discord | ✔ |
| [KOOK](https://github.com/wuyan1003/astrbot_plugin_kook_adapter) | ✔ |
| [VoceChat](https://github.com/HikariFroya/astrbot_plugin_vocechat) | ✔ |
## ⚡ 提供商支持情况
| 名称 | 支持性 | 类型 | 备注 |
| -------- | ------- | ------- | ------- |
| OpenAI | ✔ | 文本生成 | 支持任何兼容 OpenAI API 的服务 |
| Anthropic | ✔ | 文本生成 | |
| Google Gemini | ✔ | 文本生成 | |
| Dify | ✔ | LLMOps | |
| 阿里云百炼应用 | ✔ | LLMOps | |
| Ollama | ✔ | 模型加载器 | 本地部署 DeepSeek、Llama 等开源语言模型 |
| LM Studio | ✔ | 模型加载器 | 本地部署 DeepSeek、Llama 等开源语言模型 |
| [优云智算](https://www.compshare.cn/?ytag=GPU_YY-gh_astrbot&referral_code=FV7DcGowN4hB5UuXKgpE74) | ✔ | 模型 API 及算力服务平台 | |
| [302.AI](https://share.302.ai/rr1M3l) | ✔ | 模型 API 服务平台 | |
| 硅基流动 | ✔ | 模型 API 服务平台 | |
| PPIO 派欧云 | ✔ | 模型 API 服务平台 | |
| OneAPI | ✔ | LLM 分发系统 | |
| Whisper | ✔ | 语音转文本 | 支持 API、本地部署 |
| SenseVoice | ✔ | 语音转文本 | 本地部署 |
| OpenAI TTS API | ✔ | 文本转语音 | |
| GSVI | ✔ | 文本转语音 | GPT-Sovits-Inference |
| GPT-SoVITs | ✔ | 文本转语音 | GPT-Sovits-Inference |
| FishAudio | ✔ | 文本转语音 | GPT-Sovits 作者参与的项目 |
| Edge TTS | ✔ | 文本转语音 | Edge 浏览器的免费 TTS |
| 阿里云百炼 TTS | ✔ | 文本转语音 | |
| Azure TTS | ✔ | 文本转语音 | Microsoft Azure TTS |
## ❤️ 贡献
欢迎任何 Issues/Pull Requests只需要将你的更改提交到此项目 )
### 如何贡献
你可以通过查看问题或帮助审核 PR拉取请求来贡献。任何问题或 PR 都欢迎参与,以促进社区贡献。当然,这些只是建议,你可以以任何方式进行贡献。对于新功能的添加,请先通过 Issue 讨论。
### 开发环境
AstrBot 使用 `ruff` 进行代码格式化和检查。
```bash
git clone https://github.com/Soulter/AstrBot
git clone https://github.com/AstrBotDevs/AstrBot
pip install pre-commit
pre-commit install
```
## 🌍 Community
### QQ Groups
- Group 1: 322154837 (Full)
- Group 3: 630166526 (Full)
- Group 4: 1077826412 (Full)
- Group 5: 822130018 (Full)
- Group 6: 753075035 (Full)
- Group 7: 743746109 (Full)
- Group 8: 1030353265 (Full)
- Group 9: 1076659624 (Full)
- Group 10: 1078079676 (Full)
- Group 11: 704659519 (Full)
- Group 12: 916228568 (Full)
- Group 13: 1092185289
- Group 14: 1103419483
- Developer Group(Chit-chat): 975206796
- Developer Group(Formal): 1039761811
### Discord Server
<a href="https://discord.gg/hAVk6tgV36"><img alt="Discord_community" src="https://img.shields.io/badge/Discord-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
## ❤️ Special Thanks
特别感谢所有 Contributors 和插件开发者对 AstrBot 的贡献 ❤️
Special thanks to all Contributors and plugin developers for their contributions to AstrBot ❤️
<a href="https://github.com/AstrBotDevs/AstrBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=AstrBotDevs/AstrBot" />
<img src="https://contrib.rocks/image?repo=AstrBotDevs/AstrBot&max=300&columns=15" />
</a>
此外,本项目的诞生离不开以下开源项目的帮助:
Additionally, the birth of this project would not have been possible without the help of the following open-source projects:
- [NapNeko/NapCatQQ](https://github.com/NapNeko/NapCatQQ) - 伟大的猫猫框架
另外,一些同类型其他的活跃开源 Bot 项目:
- [nonebot/nonebot2](https://github.com/nonebot/nonebot2) - 扩展性极强的 Bot 框架
- [koishijs/koishi](https://github.com/koishijs/koishi) - 扩展性极强的 Bot 框架
- [MaiM-with-u/MaiBot](https://github.com/MaiM-with-u/MaiBot) - 注重拟人功能的 ChatBot
- [langbot-app/LangBot](https://github.com/langbot-app/LangBot) - 功能丰富的 Bot 平台
- [LroMiose/nekro-agent](https://github.com/KroMiose/nekro-agent) - 注重 Agent 的 ChatBot
- [zhenxun-org/zhenxun_bot](https://github.com/zhenxun-org/zhenxun_bot) - 功能完善的 ChatBot
- [NapNeko/NapCatQQ](https://github.com/NapNeko/NapCatQQ) - The amazing cat framework
## ⭐ Star History
> [!TIP]
> 如果本项目对您的生活 / 工作产生了帮助,或者您关注本项目的未来发展,请给项目 Star这是我维护这个开源项目的动力 <3
> [!TIP]
> If this project has helped you in your life or work, or if you're interested in its future development, please give the project a Star. It's the driving force behind maintaining this open-source project <3
<div align="center">
[![Star History Chart](https://api.star-history.com/svg?repos=soulter/astrbot&type=Date)](https://star-history.com/#soulter/astrbot&Date)
[![Star History Chart](https://api.star-history.com/svg?repos=astrbotdevs/astrbot&type=Date)](https://star-history.com/#astrbotdevs/astrbot&Date)
</div>
<div align="center">
</details>
_Companionship and capability should never be at odds. What we aim to create is a robot that can understand emotions, provide genuine companionship, and reliably accomplish tasks._
_私は、高性能ですから!_
<img src="https://files.astrbot.app/watashiwa-koseino-desukara.gif" width="100"/>
</div>

View File

@@ -1,182 +0,0 @@
<p align="center">
![6e1279651f16d7fdf4727558b72bbaf1](https://github.com/user-attachments/assets/ead4c551-fc3c-48f7-a6f7-afbfdb820512)
</p>
<div align="center">
_✨ Easy-to-use Multi-platform LLM Chatbot & Development Framework ✨_
<a href="https://trendshift.io/repositories/12875" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12875" alt="Soulter%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/Soulter/AstrBot)](https://github.com/Soulter/AstrBot/releases/latest)
<img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="python">
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg"/></a>
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=wtbaNx7EioxeaqS9z7RQWVXPIxg2zYr7&jump_from=webapi&authKey=vlqnv/AV2DbJEvGIcxdlNSpfxVy+8vVqijgreRdnVKOaydpc+YSw4MctmEbr0k5"><img alt="Static Badge" src="https://img.shields.io/badge/QQ群-630166526-purple"></a>
[![wakatime](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e.svg)](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e)
![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fstats&query=v&label=7%E6%97%A5%E6%B6%88%E6%81%AF%E4%B8%8A%E8%A1%8C%E9%87%8F&cacheSeconds=3600)
[![codecov](https://codecov.io/gh/Soulter/AstrBot/graph/badge.svg?token=FF3P5967B8)](https://codecov.io/gh/Soulter/AstrBot)
<a href="https://astrbot.app/">Documentation</a>
<a href="https://github.com/Soulter/AstrBot/issues">Issue Tracking</a>
</div>
AstrBot is a loosely coupled, asynchronous chatbot and development framework that supports multi-platform deployment, featuring an easy-to-use plugin system and comprehensive Large Language Model (LLM) integration capabilities.
## ✨ Key Features
1. **LLM Conversations** - Supports various LLMs including OpenAI API, Google Gemini, Llama, Deepseek, ChatGLM, etc. Enables local model deployment via Ollama/LLMTuner. Features multi-turn dialogues, personality contexts, multimodal capabilities (image understanding), and speech-to-text (Whisper).
2. **Multi-platform Integration** - Supports QQ (OneBot), QQ Channels, WeChat (Gewechat), Feishu, and Telegram. Planned support for DingTalk, Discord, WhatsApp, and Xiaomi Smart Speakers. Includes rate limiting, whitelisting, keyword filtering, and Baidu content moderation.
3. **Agent Capabilities** - Native support for code execution, natural language TODO lists, web search. Integrates with [Dify Platform](https://dify.ai/) for easy access to Dify assistants/knowledge bases/workflows.
4. **Plugin System** - Optimized plugin mechanism with minimal development effort. Supports multiple installed plugins.
5. **Web Dashboard** - Visual configuration management, plugin controls, logging, and WebChat interface for direct LLM interaction.
6. **High Stability & Modularity** - Event bus and pipeline architecture ensures high modularization and loose coupling.
> [!TIP]
> Dashboard Demo: [https://demo.astrbot.app/](https://demo.astrbot.app/)
> Username: `astrbot`, Password: `astrbot` (LLM not configured for chat page)
## ✨ Deployment
#### Docker Deployment
See docs: [Deploy with Docker](https://astrbot.app/deploy/astrbot/docker.html#docker-deployment)
#### Windows Installer
Requires Python (>3.10). See docs: [Windows Installer Guide](https://astrbot.app/deploy/astrbot/windows.html)
#### Replit Deployment
[![Run on Repl.it](https://repl.it/badge/github/Soulter/AstrBot)](https://repl.it/github/Soulter/AstrBot)
#### CasaOS Deployment
Community-contributed method.
See docs: [CasaOS Deployment](https://astrbot.app/deploy/astrbot/casaos.html)
#### Manual Deployment
See docs: [Source Code Deployment](https://astrbot.app/deploy/astrbot/cli.html)
## ⚡ Platform Support
| Platform | Status | Details | Message Types |
| -------------------------------------------------------------- | ------ | ------------------- | ------------------- |
| QQ (Official Bot) | ✔ | Private/Group chats | Text, Images |
| QQ (OneBot) | ✔ | Private/Group chats | Text, Images, Voice |
| WeChat (Personal) | ✔ | Private/Group chats | Text, Images, Voice |
| [Telegram](https://github.com/Soulter/astrbot_plugin_telegram) | ✔ | Private/Group chats | Text, Images |
| [WeChat Work](https://github.com/Soulter/astrbot_plugin_wecom) | ✔ | Private chats | Text, Images, Voice |
| Feishu | ✔ | Group chats | Text, Images |
| WeChat Open Platform | 🚧 | Planned | - |
| Discord | 🚧 | Planned | - |
| WhatsApp | 🚧 | Planned | - |
| Xiaomi Speakers | 🚧 | Planned | - |
## Provider Support Status
| Name | Support | Type | Notes |
|---------------------------|---------|------------------------|-----------------------------------------------------------------------|
| OpenAI API | ✔ | Text Generation | Supports all OpenAI API-compatible services including DeepSeek, Google Gemini, GLM, Moonshot, Alibaba Cloud Bailian, Silicon Flow, xAI, etc. |
| Claude API | ✔ | Text Generation | |
| Google Gemini API | ✔ | Text Generation | |
| Dify | ✔ | LLMOps | |
| DashScope (Alibaba Cloud) | ✔ | LLMOps | |
| Ollama | ✔ | Model Loader | Local deployment for open-source LLMs (DeepSeek, Llama, etc.) |
| LM Studio | ✔ | Model Loader | Local deployment for open-source LLMs (DeepSeek, Llama, etc.) |
| LLMTuner | ✔ | Model Loader | Local loading of fine-tuned models (e.g. LoRA) |
| OneAPI | ✔ | LLM Distribution | |
| Whisper | ✔ | Speech-to-Text | Supports API and local deployment |
| SenseVoice | ✔ | Speech-to-Text | Local deployment |
| OpenAI TTS API | ✔ | Text-to-Speech | |
| Fishaudio | ✔ | Text-to-Speech | Project involving GPT-Sovits author |
# 🦌 Roadmap
> [!TIP]
> Suggestions welcome via Issues <3
- [ ] Ensure feature parity across all platform adapters
- [ ] Optimize plugin APIs
- [ ] Add default TTS services (e.g., GPT-Sovits)
- [ ] Enhance chat features with persistent memory
- [ ] i18n Planning
## ❤️ Contributions
All Issues/PRs welcome! Simply submit your changes to this project :)
For major features, please discuss via Issues first.
## 🌟 Support
- Star this project!
- Support via [Afdian](https://afdian.com/a/soulter)
- WeChat support: [QR Code](https://drive.soulter.top/f/pYfA/d903f4fa49a496fda3f16d2be9e023b5.png)
## ✨ Demos
> [!NOTE]
> Code executor file I/O currently tested with Napcat(QQ)/Lagrange(QQ)
<div align='center'>
<img src="https://github.com/user-attachments/assets/4ee688d9-467d-45c8-99d6-368f9a8a92d8" width="600">
_✨ Docker-based Sandboxed Code Executor (Beta) ✨_
<img src="https://github.com/user-attachments/assets/0378f407-6079-4f64-ae4c-e97ab20611d2" height=500>
_✨ Multimodal Input, Web Search, Text-to-Image ✨_
<img src="https://github.com/user-attachments/assets/8ec12797-e70f-460a-959e-48eca39ca2bb" height=100>
_✨ Natural Language TODO Lists ✨_
<img src="https://github.com/user-attachments/assets/e137a9e1-340a-4bf2-bb2b-771132780735" height=150>
<img src="https://github.com/user-attachments/assets/480f5e82-cf6a-4955-a869-0d73137aa6e1" height=150>
_✨ Plugin System Showcase ✨_
<img src="https://github.com/user-attachments/assets/592a8630-14c7-4e06-b496-9c0386e4f36c" width=600>
_✨ Web Dashboard ✨_
![webchat](https://drive.soulter.top/f/vlsA/ezgif-5-fb044b2542.gif)
_✨ Built-in Web Chat Interface ✨_
</div>
## ⭐ Star History
> [!TIP]
> If this project helps you, please give it a star <3
<div align="center">
[![Star History Chart](https://api.star-history.com/svg?repos=soulter/astrbot&type=Date)](https://star-history.com/#soulter/astrbot&Date)
</div>
## Disclaimer
1. Licensed under `AGPL-v3`.
2. WeChat integration uses [Gewechat](https://github.com/Devo919/Gewechat). Use at your own risk with non-critical accounts.
3. Users must comply with local laws and regulations.
<!-- ## ✨ ATRI [Beta]
Available as plugin: [astrbot_plugin_atri](https://github.com/Soulter/astrbot_plugin_atri)
1. Qwen1.5-7B-Chat Lora model fine-tuned with ATRI character data
2. Long-term memory
3. Meme understanding & responses
4. TTS integration
-->
_私は、高性能ですから!_

277
README_fr.md Normal file
View File

@@ -0,0 +1,277 @@
![AstrBot-Logo-Simplified](https://github.com/user-attachments/assets/ffd99b6b-3272-4682-beaa-6fe74250f7d9)
<div align="center">
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh.md">简体中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README.md">English</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh-TW.md">繁體中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ja.md">日本語</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ru.md">Русский</a>
<br>
<div>
<a href="https://trendshift.io/repositories/21369" target="_blank"><img src="https://trendshift.io/api/badge/repositories/21369" alt="AstrBotDevs%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://hellogithub.com/repository/AstrBotDevs/AstrBot" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=d127d50cd5e54c5382328acc3bb25483&claim_uid=ZO9by7qCXgSd6Lp&t=2" alt="FeaturedHelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
</div>
<br>
<div>
<img src="https://img.shields.io/github/v/release/AstrBotDevs/AstrBot?color=76bad9" href="https://github.com/AstrBotDevs/AstrBot/releases/latest">
<img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="python">
<img src="https://deepwiki.com/badge.svg" href="https://deepwiki.com/AstrBotDevs/AstrBot">
<a href="https://zread.ai/AstrBotDevs/AstrBot" target="_blank"><img src="https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFZIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff" alt="zread"/></a>
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg?color=76bad9"/></a>
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fplugin-num&query=%24.result&suffix=%20&label=Marketplace&cacheSeconds=3600">
<img src="https://gitcode.com/Soulter/AstrBot/star/badge.svg" href="https://gitcode.com/Soulter/AstrBot">
</div>
<br>
<a href="https://astrbot.app/">Documentation</a>
<a href="https://blog.astrbot.app/">Blog</a>
<a href="https://astrbot.featurebase.app/roadmap">Feuille de route</a>
<a href="https://github.com/AstrBotDevs/AstrBot/issues">Signaler un problème</a>
<a href="mailto:community@astrbot.app">Email Support</a>
</div>
AstrBot est une plateforme de chatbot Agent tout-en-un open source qui s'intègre aux principales applications de messagerie instantanée. Elle fournit une infrastructure d'IA conversationnelle fiable et évolutive pour les particuliers, les développeurs et les équipes. Que vous construisiez un compagnon IA personnel, un service client intelligent, un assistant d'automatisation ou une base de connaissances d'entreprise, AstrBot vous permet de créer rapidement des applications d'IA prêtes pour la production dans les flux de travail de votre plateforme de messagerie.
![521771166-00782c4c-4437-4d97-aabc-605e3738da5c (1)](https://github.com/user-attachments/assets/61e7b505-f7db-41aa-a75f-4ef8f079b8ba)
## Fonctionnalités principales
1. 💯 Gratuit & Open Source.
2. ✨ Dialogue avec de grands modèles d'IA, multimodal, Agent, MCP, Skills, Base de connaissances, Paramétrage de personnalité, compression automatique des dialogues.
3. 🤖 Prise en charge de l'accès aux plateformes d'Agents telles que Dify, Alibaba Cloud Bailian, Coze, etc.
4. 🌐 Multiplateforme : supporte QQ, WeChat Enterprise, Feishu, DingTalk, Comptes officiels WeChat, Telegram, Slack et [plus encore](#plateformes-de-messagerie-prises-en-charge).
5. 📦 Extension par plugins, avec plus de 1000 plugins déjà disponibles pour une installation en un clic.
6. 🛡️ Environnement isolé [Agent Sandbox](https://docs.astrbot.app/use/astrbot-agent-sandbox.html) : exécution sécurisée de code, appels Shell et réutilisation des ressources au niveau de la session.
7. 💻 Support WebUI.
8. 🌈 Support Web ChatUI, avec sandbox d'agent intégrée, recherche web, etc.
9. 🌐 Support de l'internationalisation (i18n).
<br>
<table align="center">
<tr align="center">
<th>💙 Jeux de rôle & Accompagnement émotionnel</th>
<th>✨ Agent proactif</th>
<th>🚀 Capacités agentiques générales</th>
<th>🧩 1000+ Plugins de communauté</th>
</tr>
<tr>
<td align="center"><p align="center"><img width="984" height="1746" alt="99b587c5d35eea09d84f33e6cf6cfd4f" src="https://github.com/user-attachments/assets/89196061-3290-458d-b51f-afa178049f84" /></p></td>
<td align="center"><p align="center"><img width="976" height="1612" alt="c449acd838c41d0915cc08a3824025b1" src="https://github.com/user-attachments/assets/f75368b4-e022-41dc-a9e0-131c3e73e32e" /></p></td>
<td align="center"><p align="center"><img width="974" height="1732" alt="image" src="https://github.com/user-attachments/assets/e22a3968-87d7-4708-a7cd-e7f198c7c32e" /></p></td>
<td align="center"><p align="center"><img width="976" height="1734" alt="image" src="https://github.com/user-attachments/assets/0952b395-6b4a-432a-8a50-c294b7f89750" /></p></td>
</tr>
</table>
## Démarrage rapide
### Déploiement en un clic
Pour les utilisateurs qui veulent découvrir AstrBot rapidement, qui sont familiers avec la ligne de commande et peuvent installer eux-mêmes l'environnement `uv`, nous recommandons la méthode de déploiement en un clic avec `uv` ⚡️ :
```bash
uv tool install astrbot --python 3.12
astrbot init # Exécutez cette commande uniquement la première fois pour initialiser l'environnement
astrbot run
```
> [uv](https://docs.astral.sh/uv/) doit être installé.
> AstrBot nécessite Python 3.12 ou une version plus récente. L'option `--python 3.12` garantit que `uv` crée l'environnement tool avec Python 3.12.
> [!NOTE]
> Pour les utilisateurs macOS : en raison des vérifications de sécurité de macOS, la première exécution de la commande `astrbot` peut prendre plus de temps (environ 10-20s).
Mettre à jour `astrbot` :
```bash
uv tool upgrade astrbot --python 3.12
```
> [!WARNING]
> AstrBot déployé via `uv` **ne prend pas en charge la mise à jour via le WebUI**. Pour mettre à jour, exécutez la commande ci-dessus depuis le terminal.
### Déploiement Docker
Pour les utilisateurs familiers avec les conteneurs et qui souhaitent une méthode plus stable et adaptée à la production, nous recommandons de déployer AstrBot avec Docker / Docker Compose.
Veuillez consulter la documentation officielle [Déployer AstrBot avec Docker](https://docs.astrbot.app/deploy/astrbot/docker.html#%E4%BD%BF%E7%94%A8-docker-%E9%83%A8%E7%BD%B2-astrbot).
### Déployer sur RainYun
Pour les utilisateurs qui souhaitent déployer AstrBot en un clic sans gérer le serveur eux-mêmes, nous recommandons le service de déploiement cloud en un clic de RainYun ☁️ :
[![Deploy on RainYun](https://rainyun-apps.cn-nb1.rains3.com/materials/deploy-on-rainyun-en.svg)](https://app.rainyun.com/apps/rca/store/5994?ref=NjU1ODg0)
### Déploiement de l'application de bureau
Pour les utilisateurs qui veulent utiliser AstrBot sur desktop et passer principalement par ChatUI, nous recommandons AstrBot App.
Accédez à [AstrBot-desktop](https://github.com/AstrBotDevs/AstrBot-desktop) pour télécharger et installer l'application ; cette méthode est conçue pour un usage desktop et n'est pas recommandée pour les scénarios serveur.
### Déploiement avec le lanceur
Également sur desktop, pour les utilisateurs qui souhaitent un déploiement rapide avec isolation d'environnement et multi-instances, nous recommandons AstrBot Launcher.
Accédez à [AstrBot Launcher](https://github.com/Raven95676/astrbot-launcher) pour télécharger et installer.
### Déployer sur Replit
Le déploiement sur Replit est maintenu par la communauté et convient aux démonstrations en ligne et aux essais légers.
[![Run on Repl.it](https://repl.it/badge/github/AstrBotDevs/AstrBot)](https://repl.it/github/AstrBotDevs/AstrBot)
### AUR
Le mode AUR s'adresse aux utilisateurs Arch Linux qui préfèrent installer AstrBot via le gestionnaire de paquets système.
Exécutez la commande ci-dessous pour installer `astrbot-git`, puis lancez AstrBot localement.
```bash
yay -S astrbot-git
```
**Autres méthodes de déploiement**
Si vous avez besoin d'une gestion par panneau ou d'une personnalisation plus poussée, consultez [Déploiement BT-Panel](https://docs.astrbot.app/deploy/astrbot/btpanel.html) pour une installation via BT Panel, [Déploiement 1Panel](https://docs.astrbot.app/deploy/astrbot/1panel.html) pour le marketplace 1Panel, [Déploiement CasaOS](https://docs.astrbot.app/deploy/astrbot/casaos.html) pour un déploiement visuel sur NAS/serveur domestique, et [Déploiement manuel](https://docs.astrbot.app/deploy/astrbot/cli.html) pour une installation complète depuis les sources avec `uv`.
## Plateformes de messagerie prises en charge
Connectez AstrBot à vos plateformes de chat préférées.
| Plateforme | Maintenance |
|---------|---------------|
| QQ | Officielle |
| Implémentation du protocole OneBot v11 | Officielle |
| Telegram | Officielle |
| Application WeChat Work & Bot intelligent WeChat Work | Officielle |
| Service client WeChat & Comptes officiels WeChat | Officielle |
| Feishu (Lark) | Officielle |
| DingTalk | Officielle |
| Slack | Officielle |
| Discord | Officielle |
| LINE | Officielle |
| Satori | Officielle |
| KOOK | Officielle |
| Misskey | Officielle |
| Mattermost | Officielle |
| WhatsApp (Bientôt disponible) | Officielle |
| [Matrix](https://github.com/stevessr/astrbot_plugin_matrix_adapter) | Communauté |
| [Rocket.Chat](https://github.com/NET-Homeless/astrbot_plugin_rocket_chat_adapter) | Communauté |
| [VoceChat](https://github.com/HikariFroya/astrbot_plugin_vocechat) | Communauté |
## Services de modèles pris en charge
| Service | Type |
|---------|---------------|
| OpenAI et services compatibles | Services LLM |
| Anthropic | Services LLM |
| Google Gemini | Services LLM |
| Moonshot AI | Services LLM |
| Zhipu AI | Services LLM |
| DeepSeek | Services LLM |
| Ollama (Auto-hébergé) | Services LLM |
| LM Studio (Auto-hébergé) | Services LLM |
| [AIHubMix](https://aihubmix.com/?aff=4bfH) | Services LLM (Passerelle API, prend en charge tous les modèles) |
| [CompShare](https://www.compshare.cn/?ytag=GPU_YY-gh_astrbot&referral_code=FV7DcGowN4hB5UuXKgpE74) | Services LLM |
| [302.AI](https://share.302.ai/rr1M3l) | Services LLM |
| [TokenPony](https://www.tokenpony.cn/3YPyf) | Services LLM |
| [SiliconFlow](https://docs.siliconflow.cn/cn/usercases/use-siliconcloud-in-astrbot) | Services LLM |
| [PPIO Cloud](https://ppio.com/user/register?invited_by=AIOONE) | Services LLM |
| ModelScope | Services LLM |
| OneAPI | Services LLM |
| Dify | Plateformes LLMOps |
| Applications Alibaba Cloud Bailian | Plateformes LLMOps |
| Coze | Plateformes LLMOps |
| OpenAI Whisper | Services de reconnaissance vocale |
| SenseVoice | Services de reconnaissance vocale |
| Xiaomi MiMo Omni | Services de reconnaissance vocale |
| OpenAI TTS | Services de synthèse vocale |
| Gemini TTS | Services de synthèse vocale |
| GPT-Sovits-Inference | Services de synthèse vocale |
| GPT-Sovits | Services de synthèse vocale |
| FishAudio | Services de synthèse vocale |
| Edge TTS | Services de synthèse vocale |
| Alibaba Cloud Bailian TTS | Services de synthèse vocale |
| Azure TTS | Services de synthèse vocale |
| Minimax TTS | Services de synthèse vocale |
| Xiaomi MiMo TTS | Services de synthèse vocale |
| Volcano Engine TTS | Services de synthèse vocale |
## ❤️ Contribuer
Les Issues et Pull Requests sont toujours les bienvenues ! N'hésitez pas à soumettre vos modifications à ce projet :)
### Comment contribuer
Vous pouvez contribuer en examinant les issues ou en aidant à la revue des pull requests. Toutes les issues ou PRs sont les bienvenues pour encourager la participation de la communauté. Bien sûr, ce ne sont que des suggestions - vous pouvez contribuer de la manière que vous souhaitez. Pour l'ajout de nouvelles fonctionnalités, veuillez d'abord en discuter via une Issue.
### Environnement de développement
AstrBot utilise `ruff` pour le formatage et le linting du code.
```bash
git clone https://github.com/AstrBotDevs/AstrBot
pip install pre-commit
pre-commit install
```
## 🌍 Communauté
### Groupes QQ
- Groupe 12 : 916228568 (nouveau)
- Groupe 9 : 1076659624 (complet)
- Groupe 10 : 1078079676 (complet)
- Groupe 11 : 704659519 (complet)
- Groupe 1 : 322154837 (complet)
- Groupe 3 : 630166526 (complet)
- Groupe 4 : 1077826412 (complet)
- Groupe 5 : 822130018 (complet)
- Groupe 6 : 753075035 (complet)
- Groupe 7 : 743746109 (complet)
- Groupe 8 : 1030353265 (complet)
- Groupe développeurs : 975206796
- Groupe développeurs (officiel) : 1039761811
### Serveur Discord
<a href="https://discord.gg/hAVk6tgV36"><img alt="Discord_community" src="https://img.shields.io/badge/Discord-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
## ❤️ Remerciements spéciaux
Un grand merci à tous les contributeurs et développeurs de plugins pour leurs contributions à AstrBot ❤️
<a href="https://github.com/AstrBotDevs/AstrBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=AstrBotDevs/AstrBot&max=300&columns=15" />
</a>
De plus, la naissance de ce projet n'aurait pas été possible sans l'aide des projets open source suivants :
- [NapNeko/NapCatQQ](https://github.com/NapNeko/NapCatQQ) - L'incroyable framework chat
## ⭐ Historique des étoiles
> [!TIP]
> Si ce projet vous a aidé dans votre vie ou votre travail, ou si vous êtes intéressé par son développement futur, veuillez donner une étoile au projet. C'est la force motrice derrière la maintenance de ce projet open source <3
<div align="center">
[![Star History Chart](https://api.star-history.com/svg?repos=astrbotdevs/astrbot&type=Date)](https://star-history.com/#astrbotdevs/astrbot&Date)
</div>
<div align="center">
_La compagnie et la capacité ne devraient jamais être des opposés. Nous souhaitons créer un robot capable à la fois de comprendre les émotions, d'offrir de la présence, et d'accomplir des tâches de manière fiable._
_私は、高性能ですから!_
<img src="https://files.astrbot.app/watashiwa-koseino-desukara.gif" width="100"/>
</div>

View File

@@ -1,167 +1,278 @@
<p align="center">
![6e1279651f16d7fdf4727558b72bbaf1](https://github.com/user-attachments/assets/ead4c551-fc3c-48f7-a6f7-afbfdb820512)
</p>
![AstrBot-Logo-Simplified](https://github.com/user-attachments/assets/ffd99b6b-3272-4682-beaa-6fe74250f7d9)
<div align="center">
_✨ 簡単に使えるマルチプラットフォーム LLM チャットボットおよび開発フレームワーク ✨_
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh.md">简体中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README.md">English</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh-TW.md">繁體中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_fr.md">Français</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ru.md">Русский</a>
<a href="https://trendshift.io/repositories/12875" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12875" alt="Soulter%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<br>
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/Soulter/AstrBot)](https://github.com/Soulter/AstrBot/releases/latest)
<img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="python">
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg"/></a>
<img alt="Static Badge" src="https://img.shields.io/badge/QQ群-630166526-purple">
[![wakatime](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e.svg)](https://wakatime.com/badge/user/915e5316-99c6-4563-a483-ef186cf000c9/project/018e705a-a1a7-409a-a849-3013485e6c8e)
![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fstats&query=v&label=7%E6%97%A5%E6%B6%88%E6%81%AF%E4%B8%8A%E8%A1%8C%E9%87%8F&cacheSeconds=3600)
[![codecov](https://codecov.io/gh/Soulter/AstrBot/graph/badge.svg?token=FF3P5967B8)](https://codecov.io/gh/Soulter/AstrBot)
<a href="https://astrbot.app/">ドキュメントを見る</a>
<a href="https://github.com/Soulter/AstrBot/issues">問題を報告する</a>
<div>
<a href="https://trendshift.io/repositories/21369" target="_blank"><img src="https://trendshift.io/api/badge/repositories/21369" alt="AstrBotDevs%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://hellogithub.com/repository/AstrBotDevs/AstrBot" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=d127d50cd5e54c5382328acc3bb25483&claim_uid=ZO9by7qCXgSd6Lp&t=2" alt="FeaturedHelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
</div>
AstrBot は、疎結合、非同期、複数のメッセージプラットフォームに対応したデプロイ、使いやすいプラグインシステム、および包括的な大規模言語モデルLLM接続機能を備えたチャットボットおよび開発フレームワークです。
<br>
## ✨ 主な機能
<div>
<img src="https://img.shields.io/github/v/release/AstrBotDevs/AstrBot?color=76bad9" href="https://github.com/AstrBotDevs/AstrBot/releases/latest">
<img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="python">
<img src="https://deepwiki.com/badge.svg" href="https://deepwiki.com/AstrBotDevs/AstrBot">
<a href="https://zread.ai/AstrBotDevs/AstrBot" target="_blank"><img src="https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFZIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0LjYxNTZDNS4zMTUwMiAxNC4zOTk5IDUuNjAxNTYgMTQuMTEzNCA1LjYwMTU2IDEzLjc1OTlWMTEuMDM5OUM1LjYwMTU2IDEwLjY4NjQgNS4zMTUwMiAxMC4zOTk5IDQuOTYxNTYgMTAuMzk5OVoiIGZpbGw9IiNmZmYiLz4KPHBhdGggZD0iTTEzLjc1ODQgMS42MDAxSDExLjAzODRDMTAuNjg1IDEuNjAwMSAxMC4zOTg0IDEuODg2NjQgMTAuMzk4NCAyLjI0MDFWNC45NjAxQzEwLjM5ODQgNS4zMTM1NiAxMC42ODUgNS42MDAxIDExLjAzODQgNS42MDAxSDEzLjc1ODRDMTQuMTExOSA1LjYwMDEgMTQuMzk4NCA1LjMxMzU2IDE0LjM5ODQgNC45NjAxVjIuMjQwMUMxNC4zOTg0IDEuODg2NjQgMTQuMTExOSAxLjYwMDEgMTMuNzU4NCAxLjYwMDFZIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDRMNCAxMlpFIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff" alt="zread"/></a>
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg?color=76bad9"/></a>
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fplugin-num&query=%24.result&suffix=%20&label=%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%83%9E%E3%83%BC%E3%82%B1%E3%83%83%E3%83%88&cacheSeconds=3600">
<img src="https://gitcode.com/Soulter/AstrBot/star/badge.svg" href="https://gitcode.com/Soulter/AstrBot">
</div>
1. **大規模言語モデルの対話**。OpenAI API、Google Gemini、Llama、Deepseek、ChatGLM など、さまざまな大規模言語モデルをサポートし、Ollama、LLMTuner を介してローカルにデプロイされた大規模モデルをサポートします。多輪対話、人格シナリオ、多モーダル機能を備え、画像理解、音声からテキストへの変換Whisperをサポートします。
2. **複数のメッセージプラットフォームの接続**。QQOneBot、QQ チャンネル、Feishu、Telegram への接続をサポートします。今後、DingTalk、Discord、WhatsApp、Xiaoai 音響をサポートする予定です。レート制限、ホワイトリスト、キーワードフィルタリング、Baidu コンテンツ監査をサポートします。
3. **エージェント**。一部のエージェント機能をネイティブにサポートし、コードエグゼキューター、自然言語タスク、ウェブ検索などを提供します。[Dify プラットフォーム](https://dify.ai/)と連携し、Dify スマートアシスタント、ナレッジベース、Dify ワークフローを簡単に接続できます。
4. **プラグインの拡張**。深く最適化されたプラグインメカニズムを備え、[プラグインの開発](https://astrbot.app/dev/plugin.html)をサポートし、機能を拡張できます。複数のプラグインのインストールをサポートします。
5. **ビジュアル管理パネル**。設定の視覚的な変更、プラグイン管理、ログの表示などをサポートし、設定の難易度を低減します。WebChat を統合し、パネル上で大規模モデルと対話できます。
6. **高い安定性と高いモジュール性**。イベントバスとパイプラインに基づくアーキテクチャ設計により、高度にモジュール化され、低結合です。
<br>
> [!TIP]
> 管理パネルのオンラインデモを体験する: [https://demo.astrbot.app/](https://demo.astrbot.app/)
>
> ユーザー名: `astrbot`, パスワード: `astrbot`。LLM が設定されていないため、チャットページで大規模モデルを使用することはできません。(デモのログインパスワードを変更しないでください 😭)
<a href="https://astrbot.app/">ドキュメント</a>
<a href="https://blog.astrbot.app/">Blog</a>
<a href="https://astrbot.featurebase.app/roadmap">ロードマップ</a>
<a href="https://github.com/AstrBotDevs/AstrBot/issues">Issue</a>
<a href="mailto:community@astrbot.app">Email Support</a>
</div>
## ✨ 使用方法
AstrBot は、主要なインスタントメッセージングアプリと統合できるオープンソースのオールインワン Agent チャットボットプラットフォームです。個人、開発者、チームに信頼性が高くスケーラブルな会話型 AI インフラストラクチャを提供します。パーソナル AI コンパニオン、インテリジェントカスタマーサービス、オートメーションアシスタント、エンタープライズナレッジベースなど、AstrBot を使用すると、IM プラットフォームのワークフロー内で本番環境対応の AI アプリケーションを迅速に構築できます。
#### Docker デプロイ
![screenshot_1 5x_postspark_2026-02-27_22-37-45](https://github.com/user-attachments/assets/f17cdb90-52d7-4773-be2e-ff64b566af6b)
公式ドキュメント [Docker を使用して AstrBot をデプロイする](https://astrbot.app/deploy/astrbot/docker.html#%E4%BD%BF%E7%94%A8-docker-%E9%83%A8%E7%BD%B2-astrbot) を参照してください。
## 主な機能
#### Windows ワンクリックインストーラーのデプロイ
1. 💯 無料 & オープンソース。
2. ✨ AI大規模言語モデル対話、マルチモーダル、Agent、MCP、Skills、ナレッジベース、ペルソナ設定、対話の自動圧縮。
3. 🤖 Dify、Alibaba Cloud Bailian百煉、Coze などのAgentプラットフォームへの接続をサポート。
4. 🌐 マルチプラットフォームQQ、企業微信WeCom、飛書Lark、釘釘DingTalk、WeChat公式アカウント、Telegram、Slack、[その他](#サポートされているメッセージプラットフォーム)に対応。
5. 📦 プラグイン拡張1000を超える既存プラグインをワンクリックでインストール可能。
6. 🛡️ 隔離環境[Agent Sandbox](https://docs.astrbot.app/use/astrbot-agent-sandbox.html)コードの安全な実行、Shell呼び出し、セッションレベルのリソース再利用。
7. 💻 WebUI 対応。
8. 🌈 Web ChatUI 対応ChatUI内にAgent Sandboxやウェブ検索などを内蔵。
9. 🌐 多言語対応i18n
コンピュータに Python>3.10)がインストールされている必要があります。公式ドキュメント [Windows ワンクリックインストーラーを使用して AstrBot をデプロイする](https://astrbot.app/deploy/astrbot/windows.html) を参照してください。
<br>
#### Replit デプロイ
<table align="center">
<tr align="center">
<th>💙 ロールプレイ & 感情的な対話</th>
<th>✨ プロアクティブ・エージェント (Proactive Agent)</th>
<th>🚀 汎用 エージェント的能力</th>
<th>🧩 1000+ コミュニティプラグイン</th>
</tr>
<tr>
<td align="center"><p align="center"><img width="984" height="1746" alt="99b587c5d35eea09d84f33e6cf6cfd4f" src="https://github.com/user-attachments/assets/89196061-3290-458d-b51f-afa178049f84" /></p></td>
<td align="center"><p align="center"><img width="976" height="1612" alt="c449acd838c41d0915cc08a3824025b1" src="https://github.com/user-attachments/assets/f75368b4-e022-41dc-a9e0-131c3e73e32e" /></p></td>
<td align="center"><p align="center"><img width="974" height="1732" alt="image" src="https://github.com/user-attachments/assets/e22a3968-87d7-4708-a7cd-e7f198c7c32e" /></p></td>
<td align="center"><p align="center"><img width="976" height="1734" alt="image" src="https://github.com/user-attachments/assets/0952b395-6b4a-432a-8a50-c294b7f89750" /></p></td>
</tr>
</table>
[![Run on Repl.it](https://repl.it/badge/github/Soulter/AstrBot)](https://repl.it/github/Soulter/AstrBot)
## クイックスタート
#### CasaOS デプロイ
### ワンクリックデプロイ
コミュニティが提供するデプロイ方法です。
AstrBot を素早く試したいユーザーで、コマンドラインに慣れており `uv` 環境を自分でインストールできる場合は、`uv` のワンクリックデプロイをおすすめします ⚡️:
公式ドキュメント [ソースコードを使用して AstrBot をデプロイする](https://astrbot.app/deploy/astrbot/casaos.html) を参照してください。
```bash
uv tool install astrbot --python 3.12
astrbot init # 初回のみ実行して環境を初期化します
astrbot run
```
#### 手動デプロイ
公式ドキュメント [ソースコードを使用して AstrBot をデプロイする](https://astrbot.app/deploy/astrbot/cli.html) を参照してください。
## ⚡ メッセージプラットフォームのサポート状況
| プラットフォーム | サポート状況 | 詳細 | メッセージタイプ |
| -------- | ------- | ------- | ------ |
| QQ(公式ロボットインターフェース) | ✔ | プライベートチャット、グループチャット、QQ チャンネルプライベートチャット、グループチャット | テキスト、画像 |
| QQ(OneBot) | ✔ | プライベートチャット、グループチャット | テキスト、画像、音声 |
| WeChat(個人アカウント) | ✔ | WeChat 個人アカウントのプライベートチャット、グループチャット | テキスト、画像、音声 |
| [Telegram](https://github.com/Soulter/astrbot_plugin_telegram) | ✔ | プライベートチャット、グループチャット | テキスト、画像 |
| [WeChat(企業 WeChat)](https://github.com/Soulter/astrbot_plugin_wecom) | ✔ | プライベートチャット | テキスト、画像、音声 |
| Feishu | ✔ | グループチャット | テキスト、画像 |
| WeChat 対話オープンプラットフォーム | 🚧 | 計画中 | - |
| Discord | 🚧 | 計画中 | - |
| WhatsApp | 🚧 | 計画中 | - |
| Xiaoai 音響 | 🚧 | 計画中 | - |
# 🦌 今後のロードマップ
> [!TIP]
> Issue でさらに多くの提案を歓迎します <3
- [ ] 現在のすべてのプラットフォームアダプターの機能の一貫性を確保し、改善する
- [ ] プラグインインターフェースの最適化
- [ ] GPT-Sovits などの TTS サービスをデフォルトでサポート
- [ ] "チャット強化" 部分を完成させ、永続的な記憶をサポート
- [ ] i18n の計画
## ❤️ 貢献
Issue や Pull Request を歓迎します!このプロジェクトに変更を加えるだけです :)
新機能の追加については、まず Issue で議論してください。
## 🌟 サポート
- このプロジェクトに Star を付けてください!
- [愛発電](https://afdian.com/a/soulter)で私をサポートしてください!
- [WeChat](https://drive.soulter.top/f/pYfA/d903f4fa49a496fda3f16d2be9e023b5.png)で私をサポートしてください~
## ✨ デモ
> [uv](https://docs.astral.sh/uv/) のインストールが必要です。
> AstrBot には Python 3.12 以降が必要です。`--python 3.12` を指定すると、`uv` は Python 3.12 で tool 環境を作成します。
> [!NOTE]
> コードエグゼキューターのファイル入力/出力は現在 Napcat(QQ)、Lagrange(QQ) でのみテストされています
> macOS ユーザーの場合macOS のセキュリティチェックにより、`astrbot` コマンドの初回実行に時間がかかる場合があります(約 10〜20 秒)。
<div align='center'>
`astrbot` の更新:
<img src="https://github.com/user-attachments/assets/4ee688d9-467d-45c8-99d6-368f9a8a92d8" width="600">
```bash
uv tool upgrade astrbot --python 3.12
```
_✨ Docker ベースのサンドボックス化されたコードエグゼキューター(ベータテスト中)✨_
> [!WARNING]
> `uv` 経由でデプロイした AstrBot は、**WebUI からのバージョンアップグレードに対応していません**。更新するには、上記のコマンドをコマンドラインで実行してください。
<img src="https://github.com/user-attachments/assets/0378f407-6079-4f64-ae4c-e97ab20611d2" height=500>
### Docker デプロイ
_✨ 多モーダル、ウェブ検索、長文の画像変換(設定可能)✨_
コンテナ運用に慣れており、より安定した本番向けのデプロイ方法を求めるユーザーには、Docker / Docker Compose での AstrBot デプロイをおすすめします。
<img src="https://github.com/user-attachments/assets/8ec12797-e70f-460a-959e-48eca39ca2bb" height=100>
公式ドキュメント [Docker を使用した AstrBot のデプロイ](https://docs.astrbot.app/deploy/astrbot/docker.html#%E4%BD%BF%E7%94%A8-docker-%E9%83%A8%E7%BD%B2-astrbot) をご参照ください。
_✨ 自然言語タスク ✨_
### 雨云でのデプロイ
<img src="https://github.com/user-attachments/assets/e137a9e1-340a-4bf2-bb2b-771132780735" height=150>
<img src="https://github.com/user-attachments/assets/480f5e82-cf6a-4955-a869-0d73137aa6e1" height=150>
AstrBot をワンクリックでデプロイしたく、サーバーを自分で管理したくないユーザーには、雨云のワンクリッククラウドデプロイサービスをおすすめします ☁️:
_✨ プラグインシステム - 一部のプラグインの展示 ✨_
[![Deploy on RainYun](https://rainyun-apps.cn-nb1.rains3.com/materials/deploy-on-rainyun-en.svg)](https://app.rainyun.com/apps/rca/store/5994?ref=NjU1ODg0)
<img src="https://github.com/user-attachments/assets/592a8630-14c7-4e06-b496-9c0386e4f36c" width="600">
### デスクトップアプリのデプロイ
_✨ 管理パネル ✨_
デスクトップで AstrBot を使い、主に ChatUI を入口として利用するユーザーには、AstrBot App をおすすめします。
![webchat](https://drive.soulter.top/f/vlsA/ezgif-5-fb044b2542.gif)
[AstrBot-desktop](https://github.com/AstrBotDevs/AstrBot-desktop) からダウンロードしてインストールしてください。この方式はデスクトップ向けであり、サーバー用途には推奨されません。
_✨ 内蔵 Web Chat、オンラインでボットと対話 ✨_
### ランチャーのデプロイ
</div>
同じくデスクトップで、素早くデプロイしつつ環境を分離して多重起動したいユーザーには、AstrBot Launcher をおすすめします。
[AstrBot Launcher](https://github.com/Raven95676/astrbot-launcher) からダウンロードしてインストールしてください。
### Replit でのデプロイ
Replit デプロイはコミュニティ提供の方式で、オンラインデモや軽量な試用に向いています。
[![Run on Repl.it](https://repl.it/badge/github/AstrBotDevs/AstrBot)](https://repl.it/github/AstrBotDevs/AstrBot)
### AUR
AUR 方式は Arch Linux ユーザー向けで、システムのパッケージ運用に合わせて AstrBot を導入したい場合に適しています。
次のコマンドで `astrbot-git` をインストールし、ローカル環境で AstrBot を起動してください。
```bash
yay -S astrbot-git
```
**その他のデプロイ方法**
パネル操作での導入やより高度なカスタマイズが必要な場合は、[宝塔パネルデプロイ](https://docs.astrbot.app/deploy/astrbot/btpanel.html)BT Panel 経由の導入)、[1Panel デプロイ](https://docs.astrbot.app/deploy/astrbot/1panel.html)1Panel アプリマーケット経由)、[CasaOS デプロイ](https://docs.astrbot.app/deploy/astrbot/casaos.html)NAS / ホームサーバー向け可視化導入)、[手動デプロイ](https://docs.astrbot.app/deploy/astrbot/cli.html)`uv` とソースベースのフルカスタム導入)を参照してください。
## サポートされているメッセージプラットフォーム
AstrBot をよく使うチャットプラットフォームに接続できます。
| プラットフォーム | 保守 |
|---------|---------------|
| QQ | 公式 |
| OneBot v11 プロトコル実装 | 公式 |
| Telegram | 公式 |
| WeChat Work アプリケーション & WeChat Work インテリジェントボット | 公式 |
| WeChat カスタマーサービス & WeChat 公式アカウント | 公式 |
| Feishu (Lark) | 公式 |
| DingTalk | 公式 |
| Slack | 公式 |
| Discord | 公式 |
| LINE | 公式 |
| Satori | 公式 |
| KOOK | 公式 |
| Misskey | 公式 |
| Mattermost | 公式 |
| WhatsApp (近日対応予定) | 公式 |
| [Matrix](https://github.com/stevessr/astrbot_plugin_matrix_adapter) | コミュニティ |
| [Rocket.Chat](https://github.com/NET-Homeless/astrbot_plugin_rocket_chat_adapter) | コミュニティ |
| [VoceChat](https://github.com/HikariFroya/astrbot_plugin_vocechat) | コミュニティ |
## サポートされているモデルサービス
| サービス | 種類 |
|---------|---------------|
| OpenAI および互換サービス | 大規模言語モデルサービス |
| Anthropic | 大規模言語モデルサービス |
| Google Gemini | 大規模言語モデルサービス |
| Moonshot AI | 大規模言語モデルサービス |
| 智谱 AI | 大規模言語モデルサービス |
| DeepSeek | 大規模言語モデルサービス |
| Ollama (セルフホスト) | 大規模言語モデルサービス |
| LM Studio (セルフホスト) | 大規模言語モデルサービス |
| [AIHubMix](https://aihubmix.com/?aff=4bfH) | 大規模言語モデルサービスAPIゲートウェイ、全モデル対応 |
| [優云智算](https://www.compshare.cn/?ytag=GPU_YY-gh_astrbot&referral_code=FV7DcGowN4hB5UuXKgpE74) | 大規模言語モデルサービス |
| [302.AI](https://share.302.ai/rr1M3l) | 大規模言語モデルサービス |
| [小馬算力](https://www.tokenpony.cn/3YPyf) | 大規模言語モデルサービス |
| [硅基流動](https://docs.siliconflow.cn/cn/usercases/use-siliconcloud-in-astrbot) | 大規模言語モデルサービス |
| [PPIO 派欧云](https://ppio.com/user/register?invited_by=AIOONE) | 大規模言語モデルサービス |
| ModelScope | 大規模言語モデルサービス |
| OneAPI | 大規模言語モデルサービス |
| Dify | LLMOps プラットフォーム |
| Alibaba Cloud 百炼アプリケーション | LLMOps プラットフォーム |
| Coze | LLMOps プラットフォーム |
| OpenAI Whisper | 音声認識サービス |
| SenseVoice | 音声認識サービス |
| Xiaomi MiMo Omni | 音声認識サービス |
| OpenAI TTS | 音声合成サービス |
| Gemini TTS | 音声合成サービス |
| GPT-Sovits-Inference | 音声合成サービス |
| GPT-Sovits | 音声合成サービス |
| FishAudio | 音声合成サービス |
| Edge TTS | 音声合成サービス |
| Alibaba Cloud 百炼 TTS | 音声合成サービス |
| Azure TTS | 音声合成サービス |
| Minimax TTS | 音声合成サービス |
| Xiaomi MiMo TTS | 音声合成サービス |
| Volcano Engine TTS | 音声合成サービス |
## ❤️ コントリビューション
Issue や Pull Request は大歓迎です!このプロジェクトに変更を送信してください :)
### コントリビュート方法
Issue を確認したり、PR(プルリクエスト)のレビューを手伝うことで貢献できます。どんな Issue や PR への参加も歓迎され、コミュニティ貢献を促進します。もちろん、これらは提案に過ぎず、どんな方法でも貢献できます。新機能の追加については、まず Issue で議論してください。
### 開発環境
AstrBot はコードのフォーマットとチェックに `ruff` を使用しています。
```bash
git clone https://github.com/AstrBotDevs/AstrBot
pip install pre-commit
pre-commit install
```
## 🌍 コミュニティ
### QQ グループ
- 12群: 916228568 (新)
- 9群: 1076659624 (満員)
- 10群: 1078079676 (満員)
- 11群: 704659519 (満員)
- 1群: 322154837 (満員)
- 3群: 630166526 (満員)
- 4群: 1077826412 (満員)
- 5群: 822130018 (満員)
- 6群: 753075035 (満員)
- 7群: 743746109 (満員)
- 8群: 1030353265 (満員)
- 開発者群: 975206796
- 開発者群(正式): 1039761811
### Discord サーバー
<a href="https://discord.gg/hAVk6tgV36"><img alt="Discord_community" src="https://img.shields.io/badge/Discord-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
## ❤️ Special Thanks
AstrBot への貢献をしていただいたすべてのコントリビューターとプラグイン開発者に特別な感謝を ❤️
<a href="https://github.com/AstrBotDevs/AstrBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=AstrBotDevs/AstrBot&max=300&columns=15" />
</a>
また、このプロジェクトの誕生は以下のオープンソースプロジェクトの助けなしには実現できませんでした:
- [NapNeko/NapCatQQ](https://github.com/NapNeko/NapCatQQ) - 素晴らしい猫猫フレームワーク
## ⭐ Star History
> [!TIP]
> このプロジェクトがあなたの生活や仕事に役立った場合、またはこのプロジェクトの将来の発展に関心がある場合は、プロジェクトに Star を付けてください。これこのオープンソースプロジェクトを維持するためのモチベーションです <3
> このプロジェクトがあなたの生活や仕事に役立ったり、このプロジェクトの今後の発展に関心がある場合は、プロジェクトに Star をください。これこのオープンソースプロジェクトを維持する原動力です <3
<div align="center">
[![Star History Chart](https://api.star-history.com/svg?repos=soulter/astrbot&type=Date)](https://star-history.com/#soulter/astrbot&Date)
[![Star History Chart](https://api.star-history.com/svg?repos=astrbotdevs/astrbot&type=Date)](https://star-history.com/#astrbotdevs/astrbot&Date)
</div>
## スポンサー
<div align="center">
[<img src="https://api.gitsponsors.com/api/badge/img?id=575865240" height="20">](https://api.gitsponsors.com/api/badge/link?p=XEpbdGxlitw/RbcwiTX93UMzNK/jgDYC8NiSzamIPMoKvG2lBFmyXhSS/b0hFoWlBBMX2L5X5CxTDsUdyvcIEHTOfnkXz47UNOZvMwyt5CzbYpq0SEzsSV1OJF1cCo90qC/ZyYKYOWedal3MhZ3ikw==)
## 免責事項
1. このプロジェクトは `AGPL-v3` オープンソースライセンスの下で保護されています。
2. このプロジェクトを使用する際は、現地の法律および規制を遵守してください。
<!-- ## ✨ ATRI [ベータテスト]
この機能はプラグインとしてロードされます。プラグインリポジトリのアドレス:[astrbot_plugin_atri](https://github.com/Soulter/astrbot_plugin_atri)
1. 《ATRI ~ My Dear Moments》の主人公 ATRI のキャラクターセリフを微調整データセットとして使用した `Qwen1.5-7B-Chat Lora` 微調整モデル。
2. 長期記憶
3. ミームの理解と返信
4. TTS
-->
_共感力と能力は決して対立するものではありません。私たちが目指すのは、感情を理解し、心の支えとなるだけでなく、確実に仕事をこなせるロボットの創造です。_
_私は、高性能ですから!_
<img src="https://files.astrbot.app/watashiwa-koseino-desukara.gif" width="100"/>
</div>

278
README_ru.md Normal file
View File

@@ -0,0 +1,278 @@
![AstrBot-Logo-Simplified](https://github.com/user-attachments/assets/ffd99b6b-3272-4682-beaa-6fe74250f7d9)
<div align="center">
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh.md">简体中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README.md">English</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh-TW.md">繁體中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ja.md">日本語</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_fr.md">Français</a>
<br>
<div>
<a href="https://trendshift.io/repositories/21369" target="_blank"><img src="https://trendshift.io/api/badge/repositories/21369" alt="AstrBotDevs%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://hellogithub.com/repository/AstrBotDevs/AstrBot" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=d127d50cd5e54c5382328acc3bb25483&claim_uid=ZO9by7qCXgSd6Lp&t=2" alt="FeaturedHelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
</div>
<br>
<div>
<img src="https://img.shields.io/github/v/release/AstrBotDevs/AstrBot?color=76bad9" href="https://github.com/AstrBotDevs/AstrBot/releases/latest">
<img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="python">
<img src="https://deepwiki.com/badge.svg" href="https://deepwiki.com/AstrBotDevs/AstrBot">
<a href="https://zread.ai/AstrBotDevs/AstrBot" target="_blank"><img src="https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFZIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjczODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff" alt="zread"/></a>
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg?color=76bad9"/></a>
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fplugin-num&query=%24.result&suffix=%20&label=%D0%9C%D0%B0%D1%80%D0%BA%D0%B5%D1%82%D0%BF%D0%BB%D0%B5%D0%B9%D1%81&cacheSeconds=3600">
<img src="https://gitcode.com/Soulter/AstrBot/star/badge.svg" href="https://gitcode.com/Soulter/AstrBot">
</div>
<br>
<a href="https://astrbot.app/">Документация</a>
<a href="https://blog.astrbot.app/">Блог</a>
<a href="https://astrbot.featurebase.app/roadmap">Дорожная карта</a>
<a href="https://github.com/AstrBotDevs/AstrBot/issues">Сообщить о проблеме</a>
<a href="mailto:community@astrbot.app">Email Support</a>
</div>
AstrBot — это универсальная платформа Agent-чатботов с открытым исходным кодом, которая интегрируется с основными приложениями для обмена мгновенными сообщениями. Она предоставляет надёжную и масштабируемую инфраструктуру разговорного ИИ для частных лиц, разработчиков и команд. Будь то персональный ИИ-компаньон, интеллектуальная служба поддержки, автоматизированный помощник или корпоративная база знаний — AstrBot позволяет быстро создавать готовые к использованию ИИ-приложения в рабочих процессах вашей платформы обмена сообщениями.
![521771166-00782c4c-4437-4d97-aabc-605e3738da5c (1)](https://github.com/user-attachments/assets/61e7b505-f7db-41aa-a75f-4ef8f079b8ba)
## Основные возможности
1. 💯 Бесплатно & Открытый исходный код.
2. ✨ Диалоги с ИИ-моделями, мультимодальность, Agent, MCP, Skills, База знаний, Настройка личности, автоматическое сжатие диалогов.
3. 🤖 Поддержка интеграции с платформами Agents, такими как Dify, Alibaba Cloud Bailian, Coze и др.
4. 🌐 Мультиплатформенность: поддержка QQ, WeChat для предприятий, Feishu, DingTalk, публичных аккаунтов WeChat, Telegram, Slack и [других](#Поддерживаемые-платформы-обмена-сообщениями).
5. 📦 Расширение плагинами: доступно более 1000 плагинов для установки в один клик.
6. 🛡️ Изолированная среда[Agent Sandbox](https://docs.astrbot.app/use/astrbot-agent-sandbox.html): безопасное выполнение любого кода, вызов Shell, повторное использование ресурсов на уровне сессии.
7. 💻 Поддержка WebUI.
8. 🌈 Поддержка Web ChatUI: встроенная песочница агента, веб-поиск и др.
9. 🌐 Поддержка интернационализации (i18n).
<br>
<table align="center">
<tr align="center">
<th>💙 Ролевые игры & Эмоциональная поддержка</th>
<th>✨ Проактивный Агент (Agent)</th>
<th>🚀 Универсальные возможности Агента</th>
<th>🧩 1000+ плагинов сообщества</th>
</tr>
<tr>
<td align="center"><p align="center"><img width="984" height="1746" alt="99b587c5d35eea09d84f33e6cf6cfd4f" src="https://github.com/user-attachments/assets/89196061-3290-458d-b51f-afa178049f84" /></p></td>
<td align="center"><p align="center"><img width="976" height="1612" alt="c449acd838c41d0915cc08a3824025b1" src="https://github.com/user-attachments/assets/f75368b4-e022-41dc-a9e0-131c3e73e32e" /></p></td>
<td align="center"><p align="center"><img width="974" height="1732" alt="image" src="https://github.com/user-attachments/assets/e22a3968-87d7-4708-a7cd-e7f198c7c32e" /></p></td>
<td align="center"><p align="center"><img width="976" height="1734" alt="image" src="https://github.com/user-attachments/assets/0952b395-6b4a-432a-8a50-c294b7f89750" /></p></td>
</tr>
</table>
## Быстрый старт
### Развёртывание в один клик
Для пользователей, которые хотят быстро попробовать AstrBot, знакомы с командной строкой и могут самостоятельно установить окружение `uv`, мы рекомендуем использовать развёртывание в один клик через `uv` ⚡️:
```bash
uv tool install astrbot --python 3.12
astrbot init # Выполните эту команду только при первом запуске для инициализации окружения
astrbot run
```
> Требуется установленный [uv](https://docs.astral.sh/uv/).
> Для AstrBot требуется Python 3.12 или новее. Параметр `--python 3.12` гарантирует, что `uv` создаст tool-окружение с Python 3.12.
> [!NOTE]
> Для пользователей macOS: из-за проверок безопасности macOS первый запуск команды `astrbot` может занять больше времени (около 10-20 секунд).
Обновить `astrbot`:
```bash
uv tool upgrade astrbot --python 3.12
```
> [!WARNING]
> AstrBot, развёрнутый через `uv`, **не поддерживает обновление через WebUI**. Для обновления выполните указанную выше команду из командной строки.
### Развёртывание Docker
Для пользователей, знакомых с контейнерами и которым нужен более стабильный и подходящий для production способ, мы рекомендуем разворачивать AstrBot через Docker / Docker Compose.
См. официальную документацию [Развёртывание AstrBot с Docker](https://docs.astrbot.app/deploy/astrbot/docker.html#%E4%BD%BF%E7%94%A8-docker-%E9%83%A8%E7%BD%B2-astrbot).
### Развёртывание на RainYun
Для пользователей, которые хотят развернуть AstrBot в один клик и не хотят самостоятельно управлять сервером, мы рекомендуем облачный сервис развёртывания в один клик от RainYun ☁️:
[![Deploy on RainYun](https://rainyun-apps.cn-nb1.rains3.com/materials/deploy-on-rainyun-en.svg)](https://app.rainyun.com/apps/rca/store/5994?ref=NjU1ODg0)
### Развёртывание десктопного приложения
Для пользователей, которые хотят использовать AstrBot на десктопе и в основном работают через ChatUI, мы рекомендуем AstrBot App.
Перейдите в [AstrBot-desktop](https://github.com/AstrBotDevs/AstrBot-desktop), скачайте и установите приложение; этот вариант предназначен для десктопа и не рекомендуется для серверных сценариев.
### Развёртывание через лаунчер
Также на десктопе, для пользователей, которым нужен быстрый запуск и мультиинстанс с изоляцией окружений, мы рекомендуем AstrBot Launcher.
Перейдите в [AstrBot Launcher](https://github.com/Raven95676/astrbot-launcher), чтобы скачать и установить.
### Развёртывание на Replit
Развёртывание через Replit поддерживается сообществом и подходит для онлайн-демо и лёгких тестовых запусков.
[![Run on Repl.it](https://repl.it/badge/github/AstrBotDevs/AstrBot)](https://repl.it/github/AstrBotDevs/AstrBot)
### AUR
AUR-вариант предназначен для пользователей Arch Linux, которым удобна установка через системный менеджер пакетов.
Выполните команду ниже для установки `astrbot-git`, затем запустите AstrBot локально.
```bash
yay -S astrbot-git
```
**Другие способы развёртывания**
Если вам нужна панельная установка или более глубокая кастомизация, смотрите [Развёртывание BT-Panel](https://docs.astrbot.app/deploy/astrbot/btpanel.html) (установка через BT Panel), [Развёртывание 1Panel](https://docs.astrbot.app/deploy/astrbot/1panel.html) (развёртывание через маркетплейс 1Panel), [Развёртывание CasaOS](https://docs.astrbot.app/deploy/astrbot/casaos.html) (визуальный вариант для NAS и домашних серверов) и [Ручное развёртывание](https://docs.astrbot.app/deploy/astrbot/cli.html) (полностью настраиваемая установка из исходников через `uv`).
## Поддерживаемые платформы обмена сообщениями
Подключите AstrBot к вашим любимым чат-платформам.
| Платформа | Поддержка |
|---------|---------------|
| QQ | Официальная |
| Реализация протокола OneBot v11 | Официальная |
| Telegram | Официальная |
| Приложение WeChat Work и интеллектуальный бот WeChat Work | Официальная |
| Служба поддержки WeChat и официальные аккаунты WeChat | Официальная |
| Feishu (Lark) | Официальная |
| DingTalk | Официальная |
| Slack | Официальная |
| Discord | Официальная |
| LINE | Официальная |
| Satori | Официальная |
| KOOK | Официальная |
| Misskey | Официальная |
| Mattermost | Официальная |
| WhatsApp (Скоро) | Официальная |
| [Matrix](https://github.com/stevessr/astrbot_plugin_matrix_adapter) | Сообщество |
| [Rocket.Chat](https://github.com/NET-Homeless/astrbot_plugin_rocket_chat_adapter) | Сообщество |
| [VoceChat](https://github.com/HikariFroya/astrbot_plugin_vocechat) | Сообщество |
## Поддерживаемые сервисы моделей
| Сервис | Тип |
|---------|---------------|
| OpenAI и совместимые сервисы | Сервисы LLM |
| Anthropic | Сервисы LLM |
| Google Gemini | Сервисы LLM |
| Moonshot AI | Сервисы LLM |
| Zhipu AI | Сервисы LLM |
| DeepSeek | Сервисы LLM |
| Ollama (Самостоятельное размещение) | Сервисы LLM |
| LM Studio (Самостоятельное размещение) | Сервисы LLM |
| [AIHubMix](https://aihubmix.com/?aff=4bfH) | Сервисы LLM (API-шлюз, поддерживает все модели) |
| [CompShare](https://www.compshare.cn/?ytag=GPU_YY-gh_astrbot&referral_code=FV7DcGowN4hB5UuXKgpE74) | Сервисы LLM |
| [302.AI](https://share.302.ai/rr1M3l) | Сервисы LLM |
| [TokenPony](https://www.tokenpony.cn/3YPyf) | Сервисы LLM |
| [SiliconFlow](https://docs.siliconflow.cn/cn/usercases/use-siliconcloud-in-astrbot) | Сервисы LLM |
| [PPIO Cloud](https://ppio.com/user/register?invited_by=AIOONE) | Сервисы LLM |
| ModelScope | Сервисы LLM |
| OneAPI | Сервисы LLM |
| Dify | Платформы LLMOps |
| Приложения Alibaba Cloud Bailian | Платформы LLMOps |
| Coze | Платформы LLMOps |
| OpenAI Whisper | Сервисы распознавания речи |
| SenseVoice | Сервисы распознавания речи |
| Xiaomi MiMo Omni | Сервисы распознавания речи |
| OpenAI TTS | Сервисы синтеза речи |
| Gemini TTS | Сервисы синтеза речи |
| GPT-Sovits-Inference | Сервисы синтеза речи |
| GPT-Sovits | Сервисы синтеза речи |
| FishAudio | Сервисы синтеза речи |
| Edge TTS | Сервисы синтеза речи |
| Alibaba Cloud Bailian TTS | Сервисы синтеза речи |
| Azure TTS | Сервисы синтеза речи |
| Minimax TTS | Сервисы синтеза речи |
| Xiaomi MiMo TTS | Сервисы синтеза речи |
| Volcano Engine TTS | Сервисы синтеза речи |
## ❤️ Вклад в проект
Issues и Pull Request всегда приветствуются! Не стесняйтесь отправлять свои изменения в этот проект :)
### Как внести вклад
Вы можете внести вклад, просматривая issues или помогая с ревью pull request. Любые issues или PR приветствуются для поощрения участия сообщества. Конечно, это лишь предложения — вы можете вносить вклад любым удобным для вас способом. Для добавления новых функций сначала обсудите это через Issue.
### Среда разработки
AstrBot использует `ruff` для форматирования и линтинга кода.
```bash
git clone https://github.com/AstrBotDevs/AstrBot
pip install pre-commit
pre-commit install
```
## 🌍 Сообщество
### Группы QQ
- Группа 12: 916228568 (новая)
- Группа 9: 1076659624 (полная)
- Группа 10: 1078079676 (полная)
- Группа 11: 704659519 (полная)
- Группа 1: 322154837 (полная)
- Группа 3: 630166526 (полная)
- Группа 4: 1077826412 (полная)
- Группа 5: 822130018 (полная)
- Группа 6: 753075035 (полная)
- Группа 7: 743746109 (полная)
- Группа 8: 1030353265 (полная)
- Группа разработчиков: 975206796
- Группа разработчиков (официальная): 1039761811
### Сервер Discord
<a href="https://discord.gg/hAVk6tgV36"><img alt="Discord_community" src="https://img.shields.io/badge/Discord-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
## ❤️ Особая благодарность
Особая благодарность всем контрибьюторам и разработчикам плагинов за их вклад в AstrBot ❤️
<a href="https://github.com/AstrBotDevs/AstrBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=AstrBotDevs/AstrBot&max=300&columns=15" />
</a>
Кроме того, рождение этого проекта было бы невозможно без помощи следующих проектов с открытым исходным кодом:
- [NapNeko/NapCatQQ](https://github.com/NapNeko/NapCatQQ) - Замечательный кошачий фреймворк
## ⭐ История звёзд
> [!TIP]
> Если этот проект помог вам в жизни или работе, или если вас интересует его будущее развитие, пожалуйста, поставьте проекту звезду. Это движущая сила поддержки этого проекта с открытым исходным кодом <3
<div align="center">
[![Star History Chart](https://api.star-history.com/svg?repos=astrbotdevs/astrbot&type=Date)](https://star-history.com/#astrbotdevs/astrbot&Date)
</div>
<div align="center">
_Сопровождение и способности никогда не должны быть противоположностями. Мы стремимся создать робота, который сможет как понимать эмоции, оказывать душевную поддержку, так и надёжно выполнять работу._
_私は、高性能ですから!_
<img src="https://files.astrbot.app/watashiwa-koseino-desukara.gif" width="100"/>
</div>

277
README_zh-TW.md Normal file
View File

@@ -0,0 +1,277 @@
![AstrBot-Logo-Simplified](https://github.com/user-attachments/assets/ffd99b6b-3272-4682-beaa-6fe74250f7d9)
<div align="center">
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh.md">简体中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README.md">English</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ja.md">日本語</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_fr.md">Français</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ru.md">Русский</a>
<br>
<div>
<a href="https://trendshift.io/repositories/21369" target="_blank"><img src="https://trendshift.io/api/badge/repositories/21369" alt="AstrBotDevs%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://hellogithub.com/repository/AstrBotDevs/AstrBot" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=d127d50cd5e54c5382328acc3bb25483&claim_uid=ZO9by7qCXgSd6Lp&t=2" alt="FeaturedHelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
</div>
<br>
<div>
<img src="https://img.shields.io/github/v/release/AstrBotDevs/AstrBot?color=76bad9" href="https://github.com/AstrBotDevs/AstrBot/releases/latest">
<img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="python">
<img src="https://deepwiki.com/badge.svg" href="https://deepwiki.com/AstrBotDevs/AstrBot">
<a href="https://zread.ai/AstrBotDevs/AstrBot" target="_blank"><img src="https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff" alt="zread"/></a>
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg?color=76bad9"/></a>
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fplugin-num&query=%24.result&suffix=%E5%80%8B&label=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%A0%B4&cacheSeconds=3600">
<img src="https://gitcode.com/Soulter/AstrBot/star/badge.svg" href="https://gitcode.com/Soulter/AstrBot">
</div>
<br>
<a href="https://astrbot.app/">文件</a>
<a href="https://blog.astrbot.app/">Blog</a>
<a href="https://astrbot.featurebase.app/roadmap">路線圖</a>
<a href="https://github.com/AstrBotDevs/AstrBot/issues">問題回報</a>
<a href="mailto:community@astrbot.app">Email</a>
</div>
AstrBot 是一個開源的一站式 Agent 聊天機器人平台,可接入主流即時通訊軟體,為個人、開發者和團隊打造可靠、可擴展的對話式智慧基礎設施。無論是個人 AI 夥伴、智慧客服、自動化助手還是企業知識庫AstrBot 都能在您的即時通訊軟體平台的工作流程中快速構建生產可用的 AI 應用程式。
![screenshot_1 5x_postspark_2026-02-27_22-37-45](https://github.com/user-attachments/assets/f17cdb90-52d7-4773-be2e-ff64b566af6b)
## 主要功能
1. 💯 免費 & 開源。
2. ✨ AI 大模型對話多模態AgentMCPSkills知識庫人格設定自動壓縮對話。
3. 🤖 支援接入 Dify、阿里雲百煉、Coze 等智慧體 (Agent) 平台。
4. 🌐 多平台,支援 QQ、企業微信、飛書、釘釘、微信公眾號、Telegram、Slack 以及[更多](#支援的訊息平台)。
5. 📦 插件擴展,已有 1000+ 個插件可一鍵安裝。
6. 🛡️ [Agent Sandbox](https://docs.astrbot.app/use/astrbot-agent-sandbox.html) 隔離化環境,安全地執行任何代碼、調用 Shell、會話級資源複用。
7. 💻 WebUI 支援。
8. 🌈 Web ChatUI 支援ChatUI 內置代理沙盒 (Agent Sandbox)、網頁搜尋等。
9. 🌐 國際化i18n支援。
<br>
<table align="center">
<tr align="center">
<th>💙 角色扮演 & 情感陪伴</th>
<th>✨ 主動式 Agent</th>
<th>🚀 通用 Agentic 能力</th>
<th>🧩 1000+ 社區外掛程式</th>
</tr>
<tr>
<td align="center"><p align="center"><img width="984" height="1746" alt="99b587c5d35eea09d84f33e6cf6cfd4f" src="https://github.com/user-attachments/assets/89196061-3290-458d-b51f-afa178049f84" /></p></td>
<td align="center"><p align="center"><img width="976" height="1612" alt="c449acd838c41d0915cc08a3824025b1" src="https://github.com/user-attachments/assets/f75368b4-e022-41dc-a9e0-131c3e73e32e" /></p></td>
<td align="center"><p align="center"><img width="974" height="1732" alt="image" src="https://github.com/user-attachments/assets/e22a3968-87d7-4708-a7cd-e7f198c7c32e" /></p></td>
<td align="center"><p align="center"><img width="976" height="1734" alt="image" src="https://github.com/user-attachments/assets/0952b395-6b4a-432a-8a50-c294b7f89750" /></p></td>
</tr>
</table>
## 快速開始
### 一鍵部署
對於想快速體驗 AstrBot、且熟悉命令列並能自行安裝 `uv` 環境的使用者,我們推薦使用 `uv` 一鍵部署方式 ⚡️。
```bash
uv tool install astrbot --python 3.12
astrbot init # 僅首次執行此命令以初始化環境
astrbot run
```
> 需要安裝 [uv](https://docs.astral.sh/uv/)。
> AstrBot 需要 Python 3.12 或更高版本。`--python 3.12` 會確保 `uv` 使用 Python 3.12 建立 tool 環境。
> [!NOTE]
> 對於 macOS 使用者:由於 macOS 安全性檢查,首次執行 `astrbot` 指令可能需要較長時間(約 10-20 秒)。
更新 `astrbot`
```bash
uv tool upgrade astrbot --python 3.12
```
> [!WARNING]
> 透過 `uv` 部署的 AstrBot **不支援在 WebUI 中進行版本升級**。如需更新,請透過命令列執行上述命令。
### Docker 部署
對於熟悉容器、希望獲得更穩定且更適合正式環境部署方式的使用者,我們推薦使用 Docker / Docker Compose 部署 AstrBot。
請參考官方文件 [使用 Docker 部署 AstrBot](https://docs.astrbot.app/deploy/astrbot/docker.html#%E4%BD%BF%E7%94%A8-docker-%E9%83%A8%E7%BD%B2-astrbot)。
### 在雨雲上部署
對於希望一鍵部署 AstrBot 且不想自行管理伺服器的使用者,我們推薦使用雨雲的一鍵雲端部署服務 ☁️:
[![Deploy on RainYun](https://rainyun-apps.cn-nb1.rains3.com/materials/deploy-on-rainyun-en.svg)](https://app.rainyun.com/apps/rca/store/5994?ref=NjU1ODg0)
### 桌面客戶端部署
對於希望在桌面端使用 AstrBot、並以 ChatUI 為主要入口的使用者,我們推薦使用 AstrBot App。
前往 [AstrBot-desktop](https://github.com/AstrBotDevs/AstrBot-desktop) 下載並安裝;此方式面向桌面使用,不建議伺服器場景。
### 啟動器部署
同樣在桌面端,對於希望快速部署並實現環境隔離多開的使用者,我們推薦使用 AstrBot Launcher。
前往 [AstrBot Launcher](https://github.com/Raven95676/astrbot-launcher) 下載並安裝。
### 在 Replit 上部署
Replit 部署由社群維護,適合線上示範與輕量試用情境。
[![Run on Repl.it](https://repl.it/badge/github/AstrBotDevs/AstrBot)](https://repl.it/github/AstrBotDevs/AstrBot)
### AUR
AUR 方式面向 Arch Linux 使用者,適合希望透過系統套件管理器安裝 AstrBot 的場景。
在終端執行下方命令安裝 `astrbot-git` 套件,安裝完成後即可啟動使用。
```bash
yay -S astrbot-git
```
**更多部署方式**
若你需要面板化或更高自訂程度的部署,可參考 [寶塔面板](https://docs.astrbot.app/deploy/astrbot/btpanel.html)BT Panel 應用商店安裝)、[1Panel](https://docs.astrbot.app/deploy/astrbot/1panel.html)1Panel 應用商店安裝)、[CasaOS](https://docs.astrbot.app/deploy/astrbot/casaos.html)NAS / 家用伺服器可視化部署)與 [手動部署](https://docs.astrbot.app/deploy/astrbot/cli.html)(基於原始碼與 `uv` 的完整自訂安裝)。
## 支援的訊息平台
將 AstrBot 連接到你常用的聊天平台。
| 平台 | 維護方 |
|---------|---------------|
| QQ | 官方維護 |
| OneBot v11 協議實作 | 官方維護 |
| Telegram | 官方維護 |
| 企微應用 & 企微智慧機器人 | 官方維護 |
| 微信客服 & 微信公眾號 | 官方維護 |
| 飛書 | 官方維護 |
| 釘釘 | 官方維護 |
| Slack | 官方維護 |
| Discord | 官方維護 |
| LINE | 官方維護 |
| Satori | 官方維護 |
| KOOK | 官方維護 |
| Misskey | 官方維護 |
| Mattermost | 官方維護 |
| WhatsApp即將支援 | 官方維護 |
| [Matrix](https://github.com/stevessr/astrbot_plugin_matrix_adapter) | 社群維護 |
| [Rocket.Chat](https://github.com/NET-Homeless/astrbot_plugin_rocket_chat_adapter) | 社群維護 |
| [VoceChat](https://github.com/HikariFroya/astrbot_plugin_vocechat) | 社群維護 |
## 支援的模型服務
| 服務 | 類型 |
|---------|---------------|
| OpenAI 及相容服務 | 大型模型服務 |
| Anthropic | 大型模型服務 |
| Google Gemini | 大型模型服務 |
| Moonshot AI | 大型模型服務 |
| 智譜 AI | 大型模型服務 |
| DeepSeek | 大型模型服務 |
| Ollama本機部署 | 大型模型服務 |
| LM Studio本機部署 | 大型模型服務 |
| [AIHubMix](https://aihubmix.com/?aff=4bfH) | 大型模型服務API 閘道,支援所有模型) |
| [優雲智算](https://www.compshare.cn/?ytag=GPU_YY-gh_astrbot&referral_code=FV7DcGowN4hB5UuXKgpE74) | 大型模型服務 |
| [302.AI](https://share.302.ai/rr1M3l) | 大型模型服務 |
| [小馬算力](https://www.tokenpony.cn/3YPyf) | 大型模型服務 |
| [矽基流動](https://docs.siliconflow.cn/cn/usercases/use-siliconcloud-in-astrbot) | 大型模型服務 |
| [PPIO 派歐雲](https://ppio.com/user/register?invited_by=AIOONE) | 大型模型服務 |
| ModelScope | 大型模型服務 |
| OneAPI | 大型模型服務 |
| Dify | LLMOps 平台 |
| 阿里雲百煉應用 | LLMOps 平台 |
| Coze | LLMOps 平台 |
| OpenAI Whisper | 語音轉文字服務 |
| SenseVoice | 語音轉文字服務 |
| Xiaomi MiMo Omni | 語音轉文字服務 |
| OpenAI TTS | 文字轉語音服務 |
| Gemini TTS | 文字轉語音服務 |
| GPT-Sovits-Inference | 文字轉語音服務 |
| GPT-Sovits | 文字轉語音服務 |
| FishAudio | 文字轉語音服務 |
| Edge TTS | 文字轉語音服務 |
| 阿里雲百煉 TTS | 文字轉語音服務 |
| Azure TTS | 文字轉語音服務 |
| Minimax TTS | 文字轉語音服務 |
| Xiaomi MiMo TTS | 文字轉語音服務 |
| 火山引擎 TTS | 文字轉語音服務 |
## ❤️ 貢獻
歡迎任何 Issues/Pull Requests只需要將您的變更提交到此專案 )
### 如何貢獻
您可以透過檢視問題或協助審核 PR拉取請求來貢獻。任何問題或 PR 都歡迎參與,以促進社群貢獻。當然,這些只是建議,您可以以任何方式進行貢獻。對於新功能的新增,請先透過 Issue 討論。
### 開發環境
AstrBot 使用 `ruff` 進行程式碼格式化和檢查。
```bash
git clone https://github.com/AstrBotDevs/AstrBot
pip install pre-commit
pre-commit install
```
## 🌍 社群
### QQ 群組
- 12 群916228568 (新)
- 9 群1076659624 (人滿)
- 10 群1078079676 (人滿)
- 11 群704659519 (人滿)
- 1 群322154837 (人滿)
- 3 群630166526 (人滿)
- 4 群1077826412 (人滿)
- 5 群822130018 (人滿)
- 6 群753075035 (人滿)
- 7 群743746109 (人滿)
- 8 群1030353265 (人滿)
- 開發者群闲聊吹水975206796
- 開發者群正式1039761811
### Discord 群組
<a href="https://discord.gg/hAVk6tgV36"><img alt="Discord_community" src="https://img.shields.io/badge/Discord-AstrBot-purple?style=for-the-badge&color=76bad9"></a>
## ❤️ Special Thanks
特別感謝所有 Contributors 和外掛開發者對 AstrBot 的貢獻 ❤️
<a href="https://github.com/AstrBotDevs/AstrBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=AstrBotDevs/AstrBot&max=300&columns=15" />
</a>
此外,本專案的誕生離不開以下開源專案的幫助:
- [NapNeko/NapCatQQ](https://github.com/NapNeko/NapCatQQ) - 偉大的貓貓框架
## ⭐ Star History
> [!TIP]
> 如果本專案對您的生活 / 工作產生了幫助,或者您關注本專案的未來發展,請給專案 Star這是我們維護這個開源專案的動力 <3
<div align="center">
[![Star History Chart](https://api.star-history.com/svg?repos=astrbotdevs/astrbot&type=Date)](https://star-history.com/#astrbotdevs/astrbot&Date)
</div>
<div align="center">
_陪伴與能力從來不應該是對立面。我們希望創造的是一個既能理解情緒、給予陪伴,也能可靠完成工作的機器人。_
_私は、高性能ですから!_
<img src="https://files.astrbot.app/watashiwa-koseino-desukara.gif" width="100"/>
</div>

319
README_zh.md Normal file
View File

@@ -0,0 +1,319 @@
![AstrBot-Logo-Simplified](https://github.com/user-attachments/assets/ffd99b6b-3272-4682-beaa-6fe74250f7d9)
<div align="center">
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README.md">English</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_zh-TW.md">繁體中文</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ja.md">日本語</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_fr.md">Français</a>
<a href="https://github.com/AstrBotDevs/AstrBot/blob/master/README_ru.md">Русский</a>
<div>
<a href="https://trendshift.io/repositories/21369" target="_blank"><img src="https://trendshift.io/api/badge/repositories/21369" alt="AstrBotDevs%2FAstrBot | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
<a href="https://hellogithub.com/repository/AstrBotDevs/AstrBot" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=d127d50cd5e54c5382328acc3bb25483&claim_uid=ZO9by7qCXgSd6Lp&t=2" alt="FeaturedHelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
</div>
<br>
<div>
<img src="https://img.shields.io/github/v/release/AstrBotDevs/AstrBot?color=76bad9" href="https://github.com/AstrBotDevs/AstrBot/releases/latest">
<img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="python">
<img src="https://deepwiki.com/badge.svg" href="https://deepwiki.com/AstrBotDevs/AstrBot">
<a href="https://zread.ai/AstrBotDevs/AstrBot" target="_blank"><img src="https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff" alt="zread"/></a>
<a href="https://hub.docker.com/r/soulter/astrbot"><img alt="Docker pull" src="https://img.shields.io/docker/pulls/soulter/astrbot.svg?color=76bad9"/></a>
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.soulter.top%2Fastrbot%2Fplugin-num&query=%24.result&suffix=%E4%B8%AA&label=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&cacheSeconds=3600">
<img src="https://gitcode.com/Soulter/AstrBot/star/badge.svg" href="https://gitcode.com/Soulter/AstrBot">
</div>
<br>
<a href="https://astrbot.app/">主页</a>
<a href="https://astrbot.app/">文档</a>
<a href="https://blog.astrbot.app/">博客</a>
<a href="https://astrbot.featurebase.app/roadmap">路线图</a>
<a href="https://github.com/AstrBotDevs/AstrBot/issues">问题提交</a>
<a href="mailto:community@astrbot.app">Email</a>
</div>
AstrBot 是一个开源的一站式 Agentic 个人和群聊助手,可在 QQ、Telegram、企业微信、飞书、钉钉、Slack 等数十款主流即时通讯软件上部署,此外还内置类似 OpenWebUI 的轻量化 ChatUI为个人、开发者和团队打造可靠、可扩展的对话式智能基础设施。无论是个人 AI 伙伴、智能客服、自动化助手还是企业知识库AstrBot 都能在你的即时通讯软件平台的工作流中快速构建 AI 应用。
![landingpage](https://github.com/user-attachments/assets/45fc5699-cddf-4e21-af35-13040706f6c0)
## 主要功能
1. 💯 免费 & 开源。
2. ✨ AI 大模型对话多模态AgentMCPSkills知识库人格设定自动压缩对话。
3. 🤖 支持接入 Dify、阿里云百炼、Coze 等智能体平台。
4. 🌐 多平台,支持 QQ、企业微信、飞书、钉钉、微信公众号、Telegram、Slack 以及[更多](#支持的消息平台)。
5. 📦 插件扩展,已有 1000+ 个插件可一键安装。
6. 🛡️ [Agent Sandbox](https://docs.astrbot.app/use/astrbot-agent-sandbox.html) 隔离化环境,安全地执行任何代码、调用 Shell、会话级资源复用。
7. 💻 WebUI 支持。
8. 🌈 Web ChatUI 支持ChatUI 内置代理沙盒、网页搜索等。
9. 🌐 国际化i18n支持。
<br>
<table align="center">
<tr align="center">
<th>💙 角色扮演 & 情感陪伴</th>
<th>✨ 主动式 Agent</th>
<th>🚀 通用 Agentic 能力</th>
<th>🧩 1000+ 社区插件</th>
</tr>
<tr>
<td align="center"><p align="center"><img width="984" height="1746" alt="99b587c5d35eea09d84f33e6cf6cfd4f" src="https://github.com/user-attachments/assets/89196061-3290-458d-b51f-afa178049f84" /></p></td>
<td align="center"><p align="center"><img width="976" height="1612" alt="c449acd838c41d0915cc08a3824025b1" src="https://github.com/user-attachments/assets/f75368b4-e022-41dc-a9e0-131c3e73e32e" /></p></td>
<td align="center"><p align="center"><img width="974" height="1732" alt="image" src="https://github.com/user-attachments/assets/e22a3968-87d7-4708-a7cd-e7f198c7c32e" /></p></td>
<td align="center"><p align="center"><img width="976" height="1734" alt="image" src="https://github.com/user-attachments/assets/0952b395-6b4a-432a-8a50-c294b7f89750" /></p></td>
</tr>
</table>
## 快速开始
### 一键部署
对于想快速体验 AstrBot、且熟悉命令行并能够自行安装 `uv` 环境的用户,我们推荐使用 `uv` 一键部署方式 ⚡️。
```bash
uv tool install astrbot --python 3.12
astrbot init # 仅首次执行此命令以初始化环境
astrbot run # astrbot run --backend-only 仅启动后端服务
# 安装开发版本(更多修复,新功能,但不够稳定,适合开发者)
uv tool install git+https://github.com/AstrBotDevs/AstrBot@dev
```
> 需要安装 [uv](https://docs.astral.sh/uv/)。
> AstrBot 需要 Python 3.12 或更高版本。`--python 3.12` 会确保 `uv` 使用 Python 3.12 创建 tool 环境。
> [!NOTE]
> 对于 macOS 用户:由于 macOS 安全检查,首次运行 `astrbot` 命令可能需要较长时间(约 10-20 秒)。
更新 `astrbot`
```bash
uv tool upgrade astrbot --python 3.12
```
> [!WARNING]
> 通过 `uv` 部署的 AstrBot **不支持在 WebUI 中进行版本升级**。如需更新,请通过命令行执行上述命令。
### Docker 部署
对于熟悉容器、希望获得更稳定且更适合生产环境部署方式的用户,我们推荐使用 Docker / Docker Compose 部署 AstrBot。
请参考官方文档 [使用 Docker 部署 AstrBot](https://docs.astrbot.app/deploy/astrbot/docker.html#%E4%BD%BF%E7%94%A8-docker-%E9%83%A8%E7%BD%B2-astrbot)。
### 在 雨云 上部署
对于希望一键部署 AstrBot 且不想自行管理服务器的用户,我们推荐使用雨云的一键云部署服务 ☁️:
[![Deploy on RainYun](https://rainyun-apps.cn-nb1.rains3.com/materials/deploy-on-rainyun-en.svg)](https://app.rainyun.com/apps/rca/store/5994?ref=NjU1ODg0)
### 桌面客户端部署
对于希望在桌面端使用 AstrBot、并以 ChatUI 为主要入口的用户,我们推荐使用 AstrBot App。
前往 [AstrBot-desktop](https://github.com/AstrBotDevs/AstrBot-desktop) 下载并安装;该方式面向桌面使用,不推荐服务器场景。
### 启动器部署
同样在桌面端,希望快速部署并实现环境隔离多开的用户,我们推荐使用 AstrBot Launcher。
前往 [AstrBot Launcher](https://github.com/Raven95676/astrbot-launcher) 下载并安装。
### 在 Replit 上部署
Replit 部署由社区维护,适合在线演示和轻量试用场景。
[![Run on Repl.it](https://repl.it/badge/github/AstrBotDevs/AstrBot)](https://repl.it/github/AstrBotDevs/AstrBot)
### AUR
AUR 方式面向 Arch Linux 用户,适合希望通过系统包管理器安装 AstrBot 的场景。
在终端执行下方命令安装 `astrbot-git` 包,安装完成后即可启动使用。
```bash
yay -S astrbot-git
```
**更多部署方式**
若你需要面板化或更高自定义部署,可参考 [宝塔面板](https://docs.astrbot.app/deploy/astrbot/btpanel.html)BT Panel 应用商店安装)、[1Panel](https://docs.astrbot.app/deploy/astrbot/1panel.html)1Panel 应用商店安装)、[CasaOS](https://docs.astrbot.app/deploy/astrbot/casaos.html)NAS / 家庭服务器可视化部署)和 [手动部署](https://docs.astrbot.app/deploy/astrbot/cli.html)(基于源码与 `uv` 的完整自定义安装)。
## 支持的消息平台
将 AstrBot 连接到你常用的聊天平台。
| 平台 | 维护方 |
|---------|---------------|
| **QQ** | 官方维护 |
| **OneBot v11** | 官方维护 |
| **Telegram** | 官方维护 |
| **企微应用 & 企微智能机器人** | 官方维护 |
| **微信客服 & 微信公众号** | 官方维护 |
| **飞书** | 官方维护 |
| **钉钉** | 官方维护 |
| **Slack** | 官方维护 |
| **Discord** | 官方维护 |
| **LINE** | 官方维护 |
| **Satori** | 官方维护 |
| **KOOK** | 官方维护 |
| **Misskey** | 官方维护 |
| **Mattermost** | 官方维护 |
| **WhatsApp将支持** | 官方维护 |
| [**Matrix**](https://github.com/stevessr/astrbot_plugin_matrix_adapter) | 社区维护 |
| [**Rocket.Chat**](https://github.com/NET-Homeless/astrbot_plugin_rocket_chat_adapter) | 社区维护 |
| [**VoceChat**](https://github.com/HikariFroya/astrbot_plugin_vocechat) | 社区维护 |
## 支持的模型提供商
| 提供商 | 类型 |
|---------|---------------|
| 自定义 | 任何 OpenAI API 兼容的服务 |
| OpenAI | LLM |
| Anthropic | LLM |
| Google Gemini | LLM |
| Moonshot AI | LLM |
| 智谱 AI | LLM |
| DeepSeek | LLM |
| Ollama (本地部署) | LLM |
| LM Studio (本地部署) | LLM |
| [AIHubMix](https://aihubmix.com/?aff=4bfH) | LLM (API 网关, 支持所有模型) |
| [优云智算](https://www.compshare.cn/?ytag=GPU_YY-gh_astrbot&referral_code=FV7DcGowN4hB5UuXKgpE74) | LLM (API 网关, 支持所有模型) |
| [硅基流动](https://docs.siliconflow.cn/cn/usercases/use-siliconcloud-in-astrbot) | LLM (API 网关, 支持所有模型) |
| [PPIO 派欧云](https://ppio.com/user/register?invited_by=AIOONE) | LLM (API 网关, 支持所有模型) |
| [302.AI](https://share.302.ai/rr1M3l) | LLM (API 网关, 支持所有模型)|
| [小马算力](https://www.tokenpony.cn/3YPyf) | LLM (API 网关, 支持所有模型)|
| ModelScope | LLM |
| OneAPI | LLM |
| Dify | LLMOps 平台 |
| 阿里云百炼应用 | LLMOps 平台 |
| Coze | LLMOps 平台 |
| OpenAI Whisper | 语音转文本 |
| SenseVoice | 语音转文本 |
| Xiaomi MiMo Omni | 语音转文本 |
| OpenAI TTS | 文本转语音 |
| Gemini TTS | 文本转语音 |
| GPT-Sovits-Inference | 文本转语音 |
| GPT-Sovits | 文本转语音 |
| FishAudio | 文本转语音 |
| Edge TTS | 文本转语音 |
| 阿里云百炼 TTS | 文本转语音 |
| Azure TTS | 文本转语音 |
| Minimax TTS | 文本转语音 |
| Xiaomi MiMo TTS | 文本转语音 |
| 火山引擎 TTS | 文本转语音 |
## ❤️ Sponsors
<p align="center">
<img alt="sponsors" src="https://sponsors.astrbot.app/?v=1">
</p>
## ❤️ 贡献
欢迎任何 Issues/Pull Requests只需要将你的更改提交到此项目 :)
### 如何贡献
你可以通过查看问题或帮助审核 PR拉取请求来贡献。任何问题或 PR 都欢迎参与,以促进社区贡献。当然,这些只是建议,你可以以任何方式进行贡献。对于新功能的添加,请先通过 Issue 讨论。
建议将功能性PR合并至dev分支将在测试修改后合并到主分支并发布新版本。
为了减少冲突,建议如下:
1. 工作分支最好基于 `dev` 分支创建,避免直接在 `main` 分支上工作。
2. 提交 PR 时,选择 `dev` 分支作为目标分支。
3. 定期同步 `dev` 分支到本地多使用git pull。
### 开发环境
AstrBot 使用 `ruff` 进行代码格式化和检查。
```bash
git clone https://github.com/AstrBotDevs/AstrBot
git switch dev # 切换到开发分支
pip install pre-commit # 或者uv tool install pre-commit
pre-commit install
```
推荐使用uv本地安装进行测试
```bash
uv tool install -e . --force
astrbot init
astrbot run
```
调试前端
```bash
astrbot run --backend-only
cd dashboard
bun install # 或者pnpm 等
bun dev
```
### QQ 群组
- 1 群322154837 (人满)
- 3 群630166526 (人满)
- 4 群1077826412 (人满)
- 5 群822130018 (人满)
- 6 群753075035 (人满)
- 7 群743746109 (人满)
- 8 群1030353265 (人满)
- 9 群1076659624 (人满)
- 10 群1078079676 (人满)
- 11 群704659519 (人满)
- 12 群916228568 (人满)
- 13 群1092185289
- 14 群1103419483
- 开发者群偏闲聊吹水975206796
- 开发者群正式1039761811
### Discord 频道
- [Discord](https://discord.gg/hAVk6tgV36)
## ❤️ Special Thanks
特别感谢所有 Contributors 和插件开发者对 AstrBot 的贡献 ❤️
<a href="https://github.com/AstrBotDevs/AstrBot/graphs/contributors">
<img src="https://contrib.rocks/image?repo=AstrBotDevs/AstrBot&max=300&columns=15" />
</a>
此外,本项目的诞生离不开以下开源项目的帮助:
- [NapNeko/NapCatQQ](https://github.com/NapNeko/NapCatQQ) - 伟大的猫猫框架
开源项目友情链接:
- [NoneBot2](https://github.com/nonebot/nonebot2) - 优秀的 Python 异步 ChatBot 框架
- [Koishi](https://github.com/koishijs/koishi) - 优秀的 Node.js ChatBot 框架
- [MaiBot](https://github.com/Mai-with-u/MaiBot) - 优秀的拟人化 AI ChatBot
- [nekro-agent](https://github.com/KroMiose/nekro-agent) - 优秀的 Agent ChatBot
- [LangBot](https://github.com/langbot-app/LangBot) - 优秀的多平台 AI ChatBot
- [ChatLuna](https://github.com/ChatLunaLab/chatluna) - 优秀的多平台 AI ChatBot Koishi 插件
- [Operit AI](https://github.com/AAswordman/Operit) - 优秀的 AI 智能助手 Android APP
## ⭐ Star History
> [!TIP]
> 如果本项目对您的生活 / 工作产生了帮助,或者您关注本项目的未来发展,请给项目 Star这是我们维护这个开源项目的动力 <3
<div align="center">
[![Star History Chart](https://api.star-history.com/svg?repos=astrbotdevs/astrbot&type=Date)](https://star-history.com/#astrbotdevs/astrbot&Date)
</div>
<div align="center">
_陪伴与能力从来不应该是对立面。我们希望创造的是一个既能理解情绪、给予陪伴,也能可靠完成工作的机器人。_
_私は、高性能ですから!_
<img src="https://files.astrbot.app/watashiwa-koseino-desukara.gif" width="100"/>
</div>

View File

@@ -1,3 +1,30 @@
from .core.log import LogManager
from __future__ import annotations
logger = LogManager.GetLogger(log_name="astrbot")
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as _pkg_version
from typing import TYPE_CHECKING, Any
try:
__version__ = _pkg_version("astrbot")
except PackageNotFoundError:
__version__ = "4.26.1"
if TYPE_CHECKING:
from .core import logger as logger
__all__ = ["logger"]
def __getattr__(name: str) -> Any:
if name == "cli":
from astrbot.cli.__main__ import cli
return cli()
if name == "logger":
from .core import logger
return logger
raise AttributeError(name)

147
astrbot/__main__.py Normal file
View File

@@ -0,0 +1,147 @@
import argparse
import asyncio
import mimetypes
import os
import sys
from pathlib import Path
import anyio
from astrbot.core import LogBroker, LogManager, db_helper, logger
from astrbot.core.config.default import VERSION
from astrbot.core.initial_loader import InitialLoader
from astrbot.core.utils.astrbot_path import (
get_astrbot_config_path,
get_astrbot_data_path,
get_astrbot_knowledge_base_path,
get_astrbot_plugin_path,
get_astrbot_root,
get_astrbot_site_packages_path,
get_astrbot_skills_path,
get_astrbot_temp_path,
)
from astrbot.core.utils.io import (
download_dashboard,
get_dashboard_version,
)
# 将父目录添加到 sys.path
sys.path.append(Path(__file__).parent.as_posix())
logo_tmpl = r"""
___ _______.___________..______ .______ ______ .___________.
/ \ / | || _ \ | _ \ / __ \ | |
/ ^ \ | (----`---| |----`| |_) | | |_) | | | | | `---| |----`
/ /_\ \ \ \ | | | / | _ < | | | | | |
/ _____ \ .----) | | | | |\ \----.| |_) | | `--' | | |
/__/ \__\ |_______/ |__| | _| `._____||______/ \______/ |__|
"""
def check_env() -> None:
# Python version check: require 3.12 or 3.13
if not (sys.version_info.major == 3 and sys.version_info.minor in (12, 13)):
sys.exit(1)
astrbot_root = get_astrbot_root()
if astrbot_root not in sys.path:
sys.path.insert(0, astrbot_root)
site_packages_path = get_astrbot_site_packages_path()
if site_packages_path not in sys.path:
sys.path.insert(0, site_packages_path)
os.makedirs(get_astrbot_config_path(), exist_ok=True)
os.makedirs(get_astrbot_plugin_path(), exist_ok=True)
os.makedirs(get_astrbot_temp_path(), exist_ok=True)
os.makedirs(get_astrbot_knowledge_base_path(), exist_ok=True)
os.makedirs(get_astrbot_skills_path(), exist_ok=True)
os.makedirs(site_packages_path, exist_ok=True)
# 针对问题 #181 的临时解决方案
mimetypes.add_type("text/javascript", ".js")
mimetypes.add_type("text/javascript", ".mjs")
mimetypes.add_type("application/json", ".json")
async def check_dashboard_files(webui_dir: str | None = None):
"""下载管理面板文件"""
# 指定webui目录
if webui_dir:
if await anyio.Path(webui_dir).exists():
logger.info(f"使用指定的 WebUI 目录: {webui_dir}")
return webui_dir
logger.warning(f"指定的 WebUI 目录 {webui_dir} 不存在,将使用默认逻辑。")
data_dist_path = os.path.join(get_astrbot_data_path(), "dist")
if await anyio.Path(data_dist_path).exists():
v = await get_dashboard_version()
if v is not None:
# 存在文件
if v == f"v{VERSION}":
logger.info("WebUI 版本已是最新。")
else:
logger.warning(
f"检测到 WebUI 版本 ({v}) 与当前 AstrBot 版本 (v{VERSION}) 不符。",
)
return data_dist_path
logger.info(
"开始下载管理面板文件...高峰期(晚上)可能导致较慢的速度。如多次下载失败,请前往 https://github.com/AstrBotDevs/AstrBot/releases/latest 下载 dist.zip,并将其中的 dist 文件夹解压至 data 目录下。",
)
try:
await download_dashboard(version=f"v{VERSION}", latest=False)
except Exception as e:
logger.warning(
f"下载指定版本(v{VERSION})的管理面板文件失败: {e},尝试下载最新版本。",
)
try:
await download_dashboard(latest=True)
except Exception as e:
logger.critical(f"下载管理面板文件失败: {e}")
return None
logger.info("管理面板下载完成。")
return data_dist_path
async def main_async(webui_dir_arg: str | None, log_broker: LogBroker) -> None:
"""主异步入口"""
# 检查仪表板文件
webui_dir = await check_dashboard_files(webui_dir_arg)
if webui_dir is None:
logger.warning(
"管理面板文件检查失败,WebUI 功能将不可用。"
"请检查网络连接或手动指定 --webui-dir 参数。",
)
db = db_helper
# 打印 logo
logger.info(logo_tmpl)
core_lifecycle = InitialLoader(db, log_broker)
core_lifecycle.webui_dir = webui_dir
await core_lifecycle.start()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="AstrBot")
parser.add_argument(
"--webui-dir",
type=str,
help="指定 WebUI 静态文件目录路径",
default=None,
)
args = parser.parse_args()
check_env()
# 启动日志代理
log_broker = LogBroker()
LogManager.set_queue_handler(logger, log_broker)
# 只使用一次 asyncio.run()
asyncio.run(main_async(args.webui_dir, log_broker))

View File

@@ -1,20 +1,19 @@
from astrbot.core.config.astrbot_config import AstrBotConfig
from astrbot import logger
from astrbot.core import html_renderer
from astrbot.core import sp
from astrbot.core.star.register import register_llm_tool as llm_tool
from astrbot.core.star.register import register_agent as agent
from astrbot.core.agent.tool import ToolSet, FunctionTool
from astrbot.core import html_renderer, sp
from astrbot.core.agent.tool import FunctionTool, ToolSet
from astrbot.core.agent.tool_executor import BaseFunctionToolExecutor
from astrbot.core.config.astrbot_config import AstrBotConfig
from astrbot.core.star.register import register_agent as agent
from astrbot.core.star.register import register_llm_tool as llm_tool
__all__ = [
"AstrBotConfig",
"logger",
"BaseFunctionToolExecutor",
"FunctionTool",
"ToolSet",
"agent",
"html_renderer",
"llm_tool",
"agent",
"logger",
"sp",
"ToolSet",
"FunctionTool",
"BaseFunctionToolExecutor",
]

View File

@@ -1,3 +1,4 @@
# ruff: noqa: F401, F403, F811, I001
from astrbot.core.config.astrbot_config import AstrBotConfig
from astrbot import logger
from astrbot.core import html_renderer
@@ -29,14 +30,15 @@ from astrbot.core.star.filter.platform_adapter_type import (
PlatformAdapterType,
)
from astrbot.core.star.register import (
register_star as register, # 注册插件Star
register_star as register, # 注册插件(Star)
)
from astrbot.core.star import Context, Star
from astrbot.core.star.config import *
# provider
from astrbot.core.provider import Provider, Personality, ProviderMetaData
from astrbot.core.provider import Provider, ProviderMetaData
from astrbot.core.db.po import Personality
# platform
from astrbot.core.platform import (
@@ -50,4 +52,4 @@ from astrbot.core.platform import (
from astrbot.core.platform.register import register_platform_adapter
from .message_components import *
from .message_components import *

View File

@@ -1,18 +1,17 @@
from astrbot.core.message.message_event_result import (
MessageEventResult,
MessageChain,
CommandResult,
EventResultType,
MessageChain,
MessageEventResult,
ResultContentType,
)
from astrbot.core.platform import AstrMessageEvent
__all__ = [
"MessageEventResult",
"MessageChain",
"AstrMessageEvent",
"CommandResult",
"EventResultType",
"AstrMessageEvent",
"MessageChain",
"MessageEventResult",
"ResultContentType",
]

View File

@@ -1,51 +1,72 @@
from astrbot.core.star.register import (
register_command as command,
register_command_group as command_group,
register_event_message_type as event_message_type,
register_regex as regex,
register_platform_adapter_type as platform_adapter_type,
register_permission_type as permission_type,
register_custom_filter as custom_filter,
register_on_astrbot_loaded as on_astrbot_loaded,
register_on_platform_loaded as on_platform_loaded,
register_on_llm_request as on_llm_request,
register_on_llm_response as on_llm_response,
register_llm_tool as llm_tool,
register_on_decorating_result as on_decorating_result,
register_after_message_sent as after_message_sent,
)
from astrbot.core.star.filter.event_message_type import (
EventMessageTypeFilter,
EventMessageType,
)
from astrbot.core.star.filter.platform_adapter_type import (
PlatformAdapterTypeFilter,
PlatformAdapterType,
)
from astrbot.core.star.filter.permission import PermissionTypeFilter, PermissionType
from astrbot.core.star.filter.custom_filter import CustomFilter
from astrbot.core.star.filter.event_message_type import (
EventMessageType,
EventMessageTypeFilter,
)
from astrbot.core.star.filter.permission import PermissionType, PermissionTypeFilter
from astrbot.core.star.filter.platform_adapter_type import (
PlatformAdapterType,
PlatformAdapterTypeFilter,
)
from astrbot.core.star.register import register_after_message_sent as after_message_sent
from astrbot.core.star.register import register_command as command
from astrbot.core.star.register import register_command_group as command_group
from astrbot.core.star.register import register_custom_filter as custom_filter
from astrbot.core.star.register import register_event_message_type as event_message_type
from astrbot.core.star.register import register_llm_tool as llm_tool
from astrbot.core.star.register import register_on_agent_begin as on_agent_begin
from astrbot.core.star.register import register_on_agent_done as on_agent_done
from astrbot.core.star.register import register_on_astrbot_loaded as on_astrbot_loaded
from astrbot.core.star.register import (
register_on_decorating_result as on_decorating_result,
)
from astrbot.core.star.register import register_on_llm_request as on_llm_request
from astrbot.core.star.register import register_on_llm_response as on_llm_response
from astrbot.core.star.register import (
register_on_llm_tool_respond as on_llm_tool_respond,
)
from astrbot.core.star.register import register_on_platform_loaded as on_platform_loaded
from astrbot.core.star.register import register_on_plugin_error as on_plugin_error
from astrbot.core.star.register import register_on_plugin_loaded as on_plugin_loaded
from astrbot.core.star.register import register_on_plugin_unloaded as on_plugin_unloaded
from astrbot.core.star.register import register_on_using_llm_tool as on_using_llm_tool
from astrbot.core.star.register import (
register_on_waiting_llm_request as on_waiting_llm_request,
)
from astrbot.core.star.register import register_permission_type as permission_type
from astrbot.core.star.register import (
register_platform_adapter_type as platform_adapter_type,
)
from astrbot.core.star.register import register_regex as regex
__all__ = [
"CustomFilter",
"EventMessageType",
"EventMessageTypeFilter",
"PermissionType",
"PermissionTypeFilter",
"PlatformAdapterType",
"PlatformAdapterTypeFilter",
"after_message_sent",
"command",
"command_group",
"event_message_type",
"regex",
"platform_adapter_type",
"permission_type",
"EventMessageTypeFilter",
"EventMessageType",
"PlatformAdapterTypeFilter",
"PlatformAdapterType",
"PermissionTypeFilter",
"CustomFilter",
"custom_filter",
"PermissionType",
"on_astrbot_loaded",
"on_platform_loaded",
"on_llm_request",
"event_message_type",
"llm_tool",
"on_agent_begin",
"on_agent_done",
"on_astrbot_loaded",
"on_decorating_result",
"after_message_sent",
"on_llm_request",
"on_llm_response",
"on_llm_tool_respond",
"on_platform_loaded",
"on_plugin_error",
"on_plugin_loaded",
"on_plugin_unloaded",
"on_using_llm_tool",
"on_waiting_llm_request",
"permission_type",
"platform_adapter_type",
"regex",
]

View File

@@ -1,23 +1,22 @@
from astrbot.core.message.components import *
from astrbot.core.platform import (
AstrMessageEvent,
Platform,
AstrBotMessage,
AstrMessageEvent,
Group,
MessageMember,
MessageType,
Platform,
PlatformMetadata,
Group,
)
from astrbot.core.platform.register import register_platform_adapter
from astrbot.core.message.components import *
__all__ = [
"AstrMessageEvent",
"Platform",
"AstrBotMessage",
"AstrMessageEvent",
"Group",
"MessageMember",
"MessageType",
"Platform",
"PlatformMetadata",
"register_platform_adapter",
"Group",
]

View File

@@ -1,17 +1,18 @@
from astrbot.core.provider import Provider, STTProvider, Personality
from astrbot.core.db.po import Personality
from astrbot.core.provider import Provider, STTProvider
from astrbot.core.provider.entities import (
LLMResponse,
ProviderMetaData,
ProviderRequest,
ProviderType,
ProviderMetaData,
LLMResponse,
)
__all__ = [
"Provider",
"STTProvider",
"LLMResponse",
"Personality",
"Provider",
"ProviderMetaData",
"ProviderRequest",
"ProviderType",
"ProviderMetaData",
"LLMResponse",
"STTProvider",
]

View File

@@ -1,8 +1,7 @@
from astrbot.core.star.register import (
register_star as register, # 注册插件Star
)
from astrbot.core.star import Context, Star, StarTools
from astrbot.core.star.config import *
from astrbot.core.star.register import (
register_star as register, # 注册插件(Star)
)
__all__ = ["register", "Context", "Star", "StarTools"]
__all__ = ["Context", "Star", "StarTools", "register"]

View File

@@ -1,7 +1,7 @@
from astrbot.core.utils.session_waiter import (
SessionWaiter,
SessionController,
SessionWaiter,
session_waiter,
)
__all__ = ["SessionWaiter", "SessionController", "session_waiter"]
__all__ = ["SessionController", "SessionWaiter", "session_waiter"]

453
astrbot/api/web.py Normal file
View File

@@ -0,0 +1,453 @@
from __future__ import annotations
import contextvars
from collections.abc import Callable, KeysView
from contextlib import contextmanager
from pathlib import Path
from typing import Any, Generic, TypeVar, overload
from fastapi.encoders import jsonable_encoder
from fastapi.responses import FileResponse, JSONResponse
from starlette.datastructures import Headers
from starlette.datastructures import UploadFile as StarletteUploadFile
from starlette.responses import StreamingResponse
ValueT = TypeVar("ValueT")
DefaultT = TypeVar("DefaultT")
ConvertedT = TypeVar("ConvertedT")
class PluginMultiDict(Generic[ValueT]):
"""Dictionary-like request values that preserves duplicate keys."""
def __init__(self, pairs: list[tuple[str, ValueT]]) -> None:
self._pairs = pairs
@overload
def get(self, key: str) -> ValueT | None: ...
@overload
def get(self, key: str, default: DefaultT) -> ValueT | DefaultT: ...
@overload
def get(
self,
key: str,
default: DefaultT,
type: Callable[[ValueT], ConvertedT],
) -> ConvertedT | DefaultT: ...
def get(self, key: str, default: Any = None, type: Callable | None = None):
"""Return the last value for a key.
Args:
key: Value key to read.
default: Value returned when the key is missing or conversion fails.
type: Optional callable used to convert the value.
Returns:
The matching value, converted value, or default.
"""
for item_key, item_value in reversed(self._pairs):
if item_key != key:
continue
if type is None:
return item_value
try:
return type(item_value)
except (TypeError, ValueError):
return default
return default
def getlist(self, key: str) -> list[ValueT]:
"""Return all values for a key.
Args:
key: Value key to read.
Returns:
Values in request order.
"""
return [item_value for item_key, item_value in self._pairs if item_key == key]
def keys(self) -> KeysView[str]:
return dict.fromkeys(item_key for item_key, _ in self._pairs).keys()
def values(self) -> list[ValueT]:
return [self[key] for key in self.keys()]
def items(self) -> list[tuple[str, ValueT]]:
return [(key, self[key]) for key in self.keys()]
def __contains__(self, key: str) -> bool:
return any(item_key == key for item_key, _ in self._pairs)
def __getitem__(self, key: str) -> ValueT:
value = self.get(key)
if value is None and key not in self:
raise KeyError(key)
return value
def __bool__(self) -> bool:
return bool(self._pairs)
class PluginUploadFile:
"""Uploaded file wrapper exposed to plugin Web API handlers."""
def __init__(self, upload_file: StarletteUploadFile) -> None:
self._upload_file: StarletteUploadFile = upload_file
self.filename: str | None = upload_file.filename
self.content_type: str | None = upload_file.content_type
self.headers: Headers = upload_file.headers
self.content_length: int | None = self._resolve_content_length()
def _resolve_content_length(self) -> int | None:
try:
raw = self.headers.get("content-length")
return int(raw) if raw else None
except (TypeError, ValueError):
return None
async def save(self, destination: str | Path) -> None:
"""Save the uploaded file to disk.
Args:
destination: Destination file path.
"""
path = Path(destination)
try:
await self._upload_file.seek(0)
except Exception:
pass
with path.open("wb") as output:
while True:
chunk = await self._upload_file.read(1024 * 1024)
if not chunk:
break
output.write(chunk)
async def read(self, size: int = -1) -> bytes:
"""Read bytes from the uploaded file.
Args:
size: Maximum number of bytes to read. Use -1 to read all bytes.
Returns:
File bytes.
"""
return await self._upload_file.read(size)
async def write(self, data: bytes) -> None:
"""Write bytes to the uploaded file object.
Args:
data: Bytes to write.
"""
await self._upload_file.write(data)
async def seek(self, offset: int) -> None:
"""Move the uploaded file cursor.
Args:
offset: Absolute byte offset.
"""
await self._upload_file.seek(offset)
async def close(self) -> None:
"""Close the uploaded file."""
await self._upload_file.close()
def __getattr__(self, key: str) -> Any:
return getattr(self._upload_file, key)
class PluginRequest:
"""Request object exposed to plugin Web API handlers."""
def __init__(
self,
request_: Any,
*,
path_params: dict[str, Any] | None = None,
plugin_name: str | None = None,
username: str | None = None,
) -> None:
self._request: Any = request_
self.method: str = request_.method
self.path: str = request_.url.path
self.headers: Headers = request_.headers
self.cookies: dict[str, str] = request_.cookies
self.content_type: str | None = request_.headers.get("content-type")
self.client_host: str | None = request_.client.host if request_.client else None
self.path_params: dict[str, Any] = path_params or {}
self.plugin_name: str | None = plugin_name
self.username: str | None = username
self.query: PluginMultiDict[str] = PluginMultiDict[str](
list(request_.query_params.multi_items())
)
self._form_cache: PluginMultiDict[str] | None = None
self._files_cache: PluginMultiDict[PluginUploadFile] | None = None
async def body(self) -> bytes:
"""Read the raw request body.
Returns:
Raw request body bytes.
"""
return await self._request.body()
async def json(self, default: DefaultT | None = None) -> Any | DefaultT | None:
"""Read the JSON request body.
Args:
default: Value returned when the request body cannot be parsed as JSON.
Returns:
Parsed JSON data or default.
"""
try:
return await self._request.json()
except Exception:
return default
async def _load_form_parts(self) -> None:
if self._form_cache is not None and self._files_cache is not None:
return
form = await self._request.form()
form_pairs: list[tuple[str, str]] = []
file_pairs: list[tuple[str, PluginUploadFile]] = []
for key, value in form.multi_items():
if isinstance(value, StarletteUploadFile):
file_pairs.append((key, PluginUploadFile(value)))
else:
form_pairs.append((key, value))
self._form_cache = PluginMultiDict(form_pairs)
self._files_cache = PluginMultiDict(file_pairs)
async def form(self) -> PluginMultiDict[str]:
"""Read form fields from a multipart or form-urlencoded request.
Returns:
Form values without uploaded files.
"""
await self._load_form_parts()
assert self._form_cache is not None
return self._form_cache
async def files(self) -> PluginMultiDict[PluginUploadFile]:
"""Read uploaded files from a multipart request.
Returns:
Uploaded file values.
"""
await self._load_form_parts()
assert self._files_cache is not None
return self._files_cache
_request_var: contextvars.ContextVar[PluginRequest] = contextvars.ContextVar(
"astrbot_plugin_web_request"
)
class PluginRequestProxy:
"""Typed proxy for the request bound to the current plugin Web handler."""
def _get_current(self) -> PluginRequest:
try:
return _request_var.get()
except LookupError as exc:
raise RuntimeError(
"astrbot.api.web.request is only available inside a plugin Web API "
"handler."
) from exc
@property
def method(self) -> str:
return self._get_current().method
@property
def path(self) -> str:
return self._get_current().path
@property
def headers(self) -> Headers:
return self._get_current().headers
@property
def cookies(self) -> dict[str, str]:
return self._get_current().cookies
@property
def content_type(self) -> str | None:
return self._get_current().content_type
@property
def client_host(self) -> str | None:
return self._get_current().client_host
@property
def path_params(self) -> dict[str, Any]:
return self._get_current().path_params
@property
def plugin_name(self) -> str | None:
return self._get_current().plugin_name
@property
def username(self) -> str | None:
return self._get_current().username
@property
def query(self) -> PluginMultiDict[str]:
return self._get_current().query
async def body(self) -> bytes:
return await self._get_current().body()
async def json(self, default: DefaultT | None = None) -> Any | DefaultT | None:
return await self._get_current().json(default=default)
async def form(self) -> PluginMultiDict[str]:
return await self._get_current().form()
async def files(self) -> PluginMultiDict[PluginUploadFile]:
return await self._get_current().files()
def __getattr__(self, key: str) -> Any:
return getattr(self._get_current(), key)
request: PluginRequestProxy = PluginRequestProxy()
@contextmanager
def bind_request_context(request_: PluginRequest):
"""Bind a plugin Web request for the current async context.
Args:
request_: Request object exposed through the module-level request proxy.
Yields:
The bound request object.
"""
token = _request_var.set(request_)
try:
yield request_
finally:
_request_var.reset(token)
def json_response(
data: Any = None,
*,
status_code: int = 200,
headers: dict[str, str] | None = None,
) -> JSONResponse:
"""Build a JSON response for plugin Web API handlers.
Args:
data: JSON-serializable response body.
status_code: HTTP status code.
headers: Optional response headers.
Returns:
A Starlette/FastAPI JSON response.
"""
return JSONResponse(
jsonable_encoder({} if data is None else data),
status_code=status_code,
headers=headers,
)
def error_response(
message: str,
*,
status_code: int = 400,
data: Any = None,
headers: dict[str, str] | None = None,
) -> JSONResponse:
"""Build a standard error response for plugin bridge calls.
Args:
message: Public error message.
status_code: HTTP status code.
data: Optional error details that are safe to expose.
headers: Optional response headers.
Returns:
A JSON response with the AstrBot error envelope.
"""
return json_response(
{"status": "error", "message": message, "data": data},
status_code=status_code,
headers=headers,
)
def file_response(
path: str | Path,
*,
filename: str | None = None,
content_type: str | None = None,
headers: dict[str, str] | None = None,
) -> FileResponse:
"""Build a file download response for plugin Web API handlers.
Args:
path: File path to send.
filename: Optional download filename.
content_type: Optional response media type.
headers: Optional response headers.
Returns:
A Starlette/FastAPI file response.
"""
return FileResponse(
path,
filename=filename,
media_type=content_type,
headers=headers,
)
def stream_response(
content: Any,
*,
content_type: str = "text/event-stream",
status_code: int = 200,
headers: dict[str, str] | None = None,
) -> StreamingResponse:
"""Build a streaming response for plugin Web API handlers.
Args:
content: Sync or async iterable that yields response chunks.
content_type: Response media type.
status_code: HTTP status code.
headers: Optional response headers.
Returns:
A Starlette/FastAPI streaming response.
"""
return StreamingResponse(
content,
media_type=content_type,
status_code=status_code,
headers=headers,
)
__all__ = [
"PluginMultiDict",
"PluginRequest",
"PluginRequestProxy",
"PluginUploadFile",
"bind_request_context",
"error_response",
"file_response",
"json_response",
"request",
"stream_response",
]

View File

@@ -0,0 +1,6 @@
{
"metadata": {
"display_name": "AstrBot",
"desc": "AstrBot's internal plugin, providing some basic capabilities."
}
}

View File

@@ -0,0 +1,6 @@
{
"metadata": {
"display_name": "AstrBot",
"desc": "AstrBot 的内部插件,提供一些基础能力。"
}
}

View File

@@ -0,0 +1,302 @@
import asyncio
import datetime
import random
import uuid
from collections import defaultdict, deque
from astrbot import logger
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent
from astrbot.api.message_components import (
At,
AtAll,
Face,
File,
Forward,
Image,
Plain,
Record,
Reply,
Video,
)
from astrbot.api.platform import MessageType
from astrbot.api.provider import Provider, ProviderRequest
from astrbot.core.agent.message import TextPart
from astrbot.core.astrbot_config_mgr import AstrBotConfigManager
"""
Group chat context awareness.
"""
GROUP_HISTORY_HEADER = (
"<system_reminder>"
"You are in a group chat. "
"Belows are group chat context after your last reply:\n"
"--- BEGIN CONTEXT---\n"
)
GROUP_HISTORY_FOOTER = "\n--- END CONTEXT ---\n</system_reminder>"
DEFAULT_GROUP_MESSAGE_MAX_CNT = 300
class GroupChatContext:
def __init__(self, acm: AstrBotConfigManager, context: star.Context) -> None:
self.acm = acm
self.context = context
self._locks: dict[str, asyncio.Lock] = {}
self.raw_records: dict[str, deque[str]] = defaultdict(deque)
self._record_ids: dict[str, deque[str]] = defaultdict(deque)
def _get_lock(self, umo: str) -> asyncio.Lock:
lock = self._locks.get(umo)
if lock is None:
lock = asyncio.Lock()
self._locks[umo] = lock
return lock
def cfg(self, event: AstrMessageEvent):
cfg = self.context.get_config(umo=event.unified_msg_origin)
group_context_cfg = cfg["provider_ltm_settings"]
image_caption_prompt = cfg["provider_settings"]["image_caption_prompt"]
image_caption_provider_id = group_context_cfg.get("image_caption_provider_id")
image_caption = group_context_cfg["image_caption"] and bool(
image_caption_provider_id
)
active_reply = group_context_cfg["active_reply"]
enable_active_reply = active_reply.get("enable", False)
ar_method = active_reply["method"]
ar_possibility = active_reply["possibility_reply"]
ar_prompt = active_reply.get("prompt", "")
ar_whitelist = active_reply.get("whitelist", [])
return {
"group_message_max_cnt": _positive_int(
group_context_cfg.get(
"group_message_max_cnt",
DEFAULT_GROUP_MESSAGE_MAX_CNT,
),
DEFAULT_GROUP_MESSAGE_MAX_CNT,
),
"image_caption": image_caption,
"image_caption_prompt": image_caption_prompt,
"image_caption_provider_id": image_caption_provider_id,
"enable_active_reply": enable_active_reply,
"ar_method": ar_method,
"ar_possibility": ar_possibility,
"ar_prompt": ar_prompt,
"ar_whitelist": ar_whitelist,
}
async def get_image_caption(
self,
image_url: str,
image_caption_provider_id: str,
image_caption_prompt: str,
) -> str:
if not image_caption_provider_id:
provider = self.context.get_using_provider()
else:
provider = self.context.get_provider_by_id(image_caption_provider_id)
if not provider:
raise Exception(f"没有找到 ID 为 {image_caption_provider_id} 的提供商")
if not isinstance(provider, Provider):
raise Exception(f"提供商类型错误({type(provider)}),无法获取图片描述")
response = await provider.text_chat(
prompt=image_caption_prompt,
session_id=uuid.uuid4().hex,
image_urls=[image_url],
persist=False,
)
return response.completion_text
async def need_active_reply(self, event: AstrMessageEvent) -> bool:
cfg = self.cfg(event)
if not cfg["enable_active_reply"]:
return False
if event.get_message_type() != MessageType.GROUP_MESSAGE:
return False
if event.is_at_or_wake_command:
return False
if cfg["ar_whitelist"] and (
event.unified_msg_origin not in cfg["ar_whitelist"]
and (
event.get_group_id() and event.get_group_id() not in cfg["ar_whitelist"]
)
):
return False
match cfg["ar_method"]:
case "possibility_reply":
return random.random() < cfg["ar_possibility"]
return False
async def remove_session(self, event: AstrMessageEvent) -> int:
umo = event.unified_msg_origin
lock = self._get_lock(umo)
async with lock:
cnt = len(self.raw_records.get(umo, deque()))
self.raw_records.pop(umo, None)
self._record_ids.pop(umo, None)
self._locks.pop(umo, None)
return cnt
async def handle_message(self, event: AstrMessageEvent) -> None:
if event.get_message_type() != MessageType.GROUP_MESSAGE:
return
umo = event.unified_msg_origin
cfg = self.cfg(event)
final_message = await self._format_message(event, cfg)
async with self._get_lock(umo):
records = self.raw_records[umo]
record_ids = self._record_ids[umo]
record_id = uuid.uuid4().hex
records.append(final_message)
record_ids.append(record_id)
_trim_left(records, cfg["group_message_max_cnt"], record_ids)
event.set_extra("_group_context_record_id", record_id)
event.set_extra("_group_context_raw_idx", len(records) - 1)
logger.debug(f"group_chat_context | {umo} | {final_message}")
async def on_req_llm(self, event: AstrMessageEvent, req: ProviderRequest) -> None:
umo = event.unified_msg_origin
record_id = event.get_extra("_group_context_record_id", None)
prompt_idx = event.get_extra("_group_context_raw_idx", -1)
if not isinstance(record_id, str) and (
not isinstance(prompt_idx, int) or prompt_idx < 0
):
return
async with self._get_lock(umo):
records = self.raw_records.get(umo)
if not records:
return
raw_list = list(records)
id_list = list(self._record_ids.get(umo, deque()))
if isinstance(record_id, str) and record_id in id_list:
prompt_idx = id_list.index(record_id)
if prompt_idx >= len(raw_list):
return
records_to_inject = raw_list[:prompt_idx]
remaining = raw_list[prompt_idx + 1 :]
remaining_ids = id_list[prompt_idx + 1 :] if id_list else []
records.clear()
records.extend(remaining)
if id_list:
record_ids = self._record_ids[umo]
record_ids.clear()
record_ids.extend(remaining_ids)
if records_to_inject:
req.extra_user_content_parts.append(
TextPart(text=_format_group_history_block(records_to_inject))
)
async def _format_message(self, event: AstrMessageEvent, cfg: dict) -> str:
datetime_str = datetime.datetime.now().strftime("%H:%M:%S")
parts = [f"[{event.message_obj.sender.nickname}/{datetime_str}]: "]
for comp in event.get_messages():
if isinstance(comp, Plain):
parts.append(f" {comp.text}")
elif isinstance(comp, Image):
if cfg["image_caption"]:
try:
url = comp.url if comp.url else comp.file
if not url:
raise Exception("图片 URL 为空")
caption = await self.get_image_caption(
url,
cfg["image_caption_provider_id"],
cfg["image_caption_prompt"],
)
parts.append(f" [Image: {caption}]")
except Exception as e:
logger.error(f"获取图片描述失败: {e}")
else:
parts.append(" [Image]")
elif isinstance(comp, At):
is_at_self = str(comp.qq) in (
event.get_self_id(),
"all",
)
if is_at_self:
parts.insert(1, "⚠️[DIRECTED AT YOU] ")
parts.append(f" [At: {comp.name}]")
elif isinstance(comp, Reply):
if comp.message_str:
parts.append(
f" [Quote({comp.sender_nickname}: {_truncate_reply_text(comp.message_str)})]"
)
elif comp.chain:
chain_desc = _describe_chain(comp.chain)
parts.append(f" [Quote({comp.sender_nickname}: {chain_desc})]")
else:
parts.append(" [Quote]")
return "".join(parts)
_MAX_REPLY_TEXT_LENGTH = 200
def _describe_chain(chain: list) -> str:
"""Summarize message chain content for quoted reply display."""
desc = []
for c in chain:
if isinstance(c, Plain) and getattr(c, "text", None):
desc.append(c.text)
elif isinstance(c, Image):
desc.append("[Image]")
elif isinstance(c, At):
name = getattr(c, "name", "") or getattr(c, "qq", "")
desc.append(f"[At: {name}]")
elif isinstance(c, Record):
desc.append("[Voice]")
elif isinstance(c, Video):
desc.append("[Video]")
elif isinstance(c, File):
desc.append(f"[File: {getattr(c, 'name', '') or ''}]")
elif isinstance(c, Forward):
desc.append("[Forward]")
elif isinstance(c, AtAll):
desc.append("[At: All]")
elif isinstance(c, Face):
desc.append(f"[Sticker: {getattr(c, 'id', '')}]")
elif isinstance(c, Reply):
desc.append("[Quote]")
else:
desc.append(f"[{c.__class__.__name__}]")
return "".join(desc) or "[Unknown]"
def _truncate_reply_text(text: str) -> str:
"""Truncate overly long quoted reply text."""
if len(text) <= _MAX_REPLY_TEXT_LENGTH:
return text
return text[:_MAX_REPLY_TEXT_LENGTH] + "..."
def _positive_int(value, fallback: int) -> int:
try:
parsed = int(value)
except (TypeError, ValueError):
return fallback
return parsed if parsed > 0 else fallback
def _trim_left(
records: deque[str],
max_records: int,
record_ids: deque[str] | None = None,
) -> None:
while len(records) > max_records:
records.popleft()
if record_ids:
record_ids.popleft()
def _format_group_history_block(records: list[str]) -> str:
return GROUP_HISTORY_HEADER + "\n".join(records) + GROUP_HISTORY_FOOTER

View File

@@ -0,0 +1,245 @@
import copy
import traceback
from collections.abc import Iterable
from sys import maxsize
import astrbot.api.message_components as Comp
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, filter
from astrbot.api.message_components import Image, Plain
from astrbot.api.provider import ProviderRequest
from astrbot.core import logger
from astrbot.core.utils.session_waiter import (
FILTERS,
USER_SESSIONS,
SessionController,
SessionWaiter,
session_waiter,
)
from .group_chat_context import GroupChatContext
def _iter_message_components(event: AstrMessageEvent):
messages = getattr(getattr(event, "message_obj", None), "message", None)
if not isinstance(messages, Iterable) or isinstance(messages, (str, bytes)):
return ()
return tuple(messages)
class Main(star.Star):
def __init__(self, context: star.Context) -> None:
self.context = context
self.group_chat_context = None
try:
self.group_chat_context = GroupChatContext(
self.context.astrbot_config_mgr,
self.context,
)
except BaseException as e:
logger.error(f"group chat context init failed: {e}")
@filter.event_message_type(filter.EventMessageType.ALL, priority=maxsize)
async def handle_session_control_agent(self, event: AstrMessageEvent) -> None:
"""会话控制代理"""
for session_filter in FILTERS:
session_id = session_filter.filter(event)
if session_id in USER_SESSIONS:
await SessionWaiter.trigger(session_id, event)
event.stop_event()
@filter.event_message_type(filter.EventMessageType.ALL, priority=maxsize - 1)
async def handle_empty_mention(self, event: AstrMessageEvent):
"""处理只有一个 @ 或仅有唤醒前缀的消息,并等待用户下一条内容。"""
try:
messages = event.get_messages()
cfg = self.context.get_config(umo=event.unified_msg_origin)
p_settings = cfg["platform_settings"]
wake_prefix = cfg.get("wake_prefix", [])
if len(messages) != 1:
return
is_empty_mention = (
isinstance(messages[0], Comp.At)
and str(messages[0].qq) == str(event.get_self_id())
and p_settings.get("empty_mention_waiting", True)
)
is_wake_prefix_only = (
isinstance(messages[0], Comp.Plain)
and messages[0].text.strip() in wake_prefix
)
if not (is_empty_mention or is_wake_prefix_only):
return
if p_settings.get("empty_mention_waiting_need_reply", True):
try:
curr_cid = await self.context.conversation_manager.get_curr_conversation_id(
event.unified_msg_origin,
)
conversation = None
if curr_cid:
conversation = (
await self.context.conversation_manager.get_conversation(
event.unified_msg_origin,
curr_cid,
)
)
else:
curr_cid = (
await self.context.conversation_manager.new_conversation(
event.unified_msg_origin,
platform_id=event.get_platform_id(),
)
)
yield event.request_llm(
prompt=(
"注意,你正在社交媒体上中与用户进行聊天,用户只是通过@来唤醒你,但并未在这条消息中输入内容,他可能会在接下来一条发送他想发送的内容。"
"你友好地询问用户想要聊些什么或者需要什么帮助,回复要符合人设,不要太过机械化。"
"请注意,你仅需要输出要回复用户的内容,不要输出其他任何东西"
),
session_id=curr_cid,
contexts=[],
system_prompt="",
conversation=conversation,
)
except Exception as e:
logger.error(f"LLM response failed: {e!s}")
yield event.plain_result("想要问什么呢?😄")
@session_waiter(60)
async def empty_mention_waiter(
controller: SessionController,
event: AstrMessageEvent,
) -> None:
if not event.message_str or not event.message_str.strip():
return
event.message_obj.message.insert(
0,
Comp.At(qq=event.get_self_id(), name=event.get_self_id()),
)
new_event = copy.copy(event)
self.context.get_event_queue().put_nowait(new_event)
event.stop_event()
controller.stop()
try:
await empty_mention_waiter(event)
except TimeoutError:
pass
except Exception as e:
yield event.plain_result("发生错误,请联系管理员: " + str(e))
finally:
event.stop_event()
except Exception as e:
logger.error("handle_empty_mention error: " + str(e))
def group_context_enabled(self, event: AstrMessageEvent):
group_context_settings = self.context.get_config(umo=event.unified_msg_origin)[
"provider_ltm_settings"
]
return (
group_context_settings["group_icl_enable"]
or group_context_settings["active_reply"]["enable"]
)
@filter.platform_adapter_type(filter.PlatformAdapterType.ALL)
async def on_message(self, event: AstrMessageEvent):
"""群聊上下文感知"""
message_components = _iter_message_components(event)
has_image_or_plain = False
for comp in message_components:
if isinstance(comp, Plain) or isinstance(comp, Image):
has_image_or_plain = True
break
group_context_enabled = False
if self.group_chat_context:
try:
group_context_enabled = self.group_context_enabled(event)
except BaseException as e:
logger.error(f"group chat context: {e}")
if group_context_enabled and self.group_chat_context and has_image_or_plain:
need_active = await self.group_chat_context.need_active_reply(event)
group_icl_enable = self.context.get_config(umo=event.unified_msg_origin)[
"provider_ltm_settings"
]["group_icl_enable"]
if group_icl_enable:
# Skip recording if a command handler matched (e.g. /reset,
# /help, /new). Slash commands are bot instructions, not group
# chat context that should be injected into future LLM requests.
if not event.get_extra("handlers_parsed_params", {}):
try:
await self.group_chat_context.handle_message(event)
except BaseException as e:
logger.error(e)
if need_active:
provider = self.context.get_using_provider(event.unified_msg_origin)
if not provider:
logger.error("未找到任何 LLM 提供商。请先配置。无法主动回复")
return
try:
session_curr_cid = await self.context.conversation_manager.get_curr_conversation_id(
event.unified_msg_origin,
)
if not session_curr_cid:
logger.error(
"当前未处于对话状态,无法主动回复,请确保 平台设置->会话隔离(unique_session) 未开启,并使用 /new 创建一个会话。",
)
return
conv = await self.context.conversation_manager.get_conversation(
event.unified_msg_origin,
session_curr_cid,
)
if not conv:
logger.error("未找到对话,无法主动回复")
return
prompt = event.message_str
image_urls = []
for comp in message_components:
if isinstance(comp, Image):
try:
image_urls.append(await comp.convert_to_file_path())
except Exception:
logger.exception("主动回复处理图片失败")
yield event.request_llm(
prompt=prompt,
session_id=event.session_id,
image_urls=image_urls,
conversation=conv,
)
except BaseException as e:
logger.error(traceback.format_exc())
logger.error(f"主动回复失败: {e}")
@filter.on_llm_request()
async def decorate_llm_req(
self, event: AstrMessageEvent, req: ProviderRequest
) -> None:
"""在请求 LLM 前注入人格信息、Identifier、时间、回复内容等 System Prompt"""
if self.group_chat_context and self.group_context_enabled(event):
try:
await self.group_chat_context.on_req_llm(event, req)
except BaseException as e:
logger.error(f"group chat context: {e}")
@filter.after_message_sent()
async def after_message_sent(self, event: AstrMessageEvent) -> None:
"""消息发送后处理"""
if self.group_chat_context and self.group_context_enabled(event):
try:
clean_session = event.get_extra("_clean_group_context_session", False)
if clean_session:
await self.group_chat_context.remove_session(event)
except Exception as e:
logger.error(f"group chat context: {e}")

View File

@@ -0,0 +1,4 @@
name: astrbot
desc: AstrBot's internal plugin, providing some basic capabilities.
author: AstrBot Team
version: 4.1.0

View File

@@ -0,0 +1,6 @@
{
"metadata": {
"display_name": "Built-in Commands",
"desc": "AstrBot's internal plugin, providing built-in commands such as /reset, /help, and /sid."
}
}

View File

@@ -0,0 +1,6 @@
{
"metadata": {
"display_name": "内置指令",
"desc": "AstrBot 自带插件,提供 /reset、/help、/sid 等内置指令。"
}
}

View File

@@ -0,0 +1,29 @@
# Commands module
from .admin import AdminCommands
from .alter_cmd import AlterCmdCommands
from .conversation import ConversationCommands
from .help import HelpCommand
from .llm import LLMCommands
from .name import NameCommand
from .plugin import PluginCommands
from .provider import ProviderCommands
from .setunset import SetUnsetCommands
from .sid import SIDCommand
from .t2i import T2ICommand
from .tts import TTSCommand
__all__ = [
"AdminCommands",
"AlterCmdCommands",
"ConversationCommands",
"HelpCommand",
"LLMCommands",
"NameCommand",
"PluginCommands",
"ProviderCommands",
"SIDCommand",
"SetUnsetCommands",
"T2ICommand",
"TTSCommand",
]

View File

@@ -0,0 +1,77 @@
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageChain, MessageEventResult
from astrbot.core.config.default import VERSION
from astrbot.core.utils.io import download_dashboard
class AdminCommands:
def __init__(self, context: star.Context) -> None:
self.context = context
async def op(self, event: AstrMessageEvent, admin_id: str = "") -> None:
"""授权管理员。op <admin_id>"""
if not admin_id:
event.set_result(
MessageEventResult().message(
"使用方法: /op <id> 授权管理员;/deop <id> 取消管理员。可通过 /sid 获取 ID。",
),
)
return
self.context.get_config()["admins_id"].append(str(admin_id))
self.context.get_config().save_config()
event.set_result(MessageEventResult().message("授权成功。"))
async def deop(self, event: AstrMessageEvent, admin_id: str = "") -> None:
"""取消授权管理员。deop <admin_id>"""
if not admin_id:
event.set_result(
MessageEventResult().message(
"使用方法: /deop <id> 取消管理员。可通过 /sid 获取 ID。",
),
)
return
try:
self.context.get_config()["admins_id"].remove(str(admin_id))
self.context.get_config().save_config()
event.set_result(MessageEventResult().message("取消授权成功。"))
except ValueError:
event.set_result(
MessageEventResult().message("此用户 ID 不在管理员名单内。"),
)
async def wl(self, event: AstrMessageEvent, sid: str = "") -> None:
"""添加白名单。wl <sid>"""
if not sid:
event.set_result(
MessageEventResult().message(
"使用方法: /wl <id> 添加白名单;/dwl <id> 删除白名单。可通过 /sid 获取 ID。",
),
)
return
cfg = self.context.get_config(umo=event.unified_msg_origin)
cfg["platform_settings"]["id_whitelist"].append(str(sid))
cfg.save_config()
event.set_result(MessageEventResult().message("添加白名单成功。"))
async def dwl(self, event: AstrMessageEvent, sid: str = "") -> None:
"""删除白名单。dwl <sid>"""
if not sid:
event.set_result(
MessageEventResult().message(
"使用方法: /dwl <id> 删除白名单。可通过 /sid 获取 ID。",
),
)
return
try:
cfg = self.context.get_config(umo=event.unified_msg_origin)
cfg["platform_settings"]["id_whitelist"].remove(str(sid))
cfg.save_config()
event.set_result(MessageEventResult().message("删除白名单成功。"))
except ValueError:
event.set_result(MessageEventResult().message("此 SID 不在白名单内。"))
async def update_dashboard(self, event: AstrMessageEvent) -> None:
"""更新管理面板"""
await event.send(MessageChain().message("正在尝试更新管理面板..."))
await download_dashboard(version=f"v{VERSION}", latest=False)
await event.send(MessageChain().message("管理面板更新完成。"))

View File

@@ -0,0 +1,187 @@
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageChain
from astrbot.core.star.filter.command import CommandFilter
from astrbot.core.star.filter.command_group import CommandGroupFilter
from astrbot.core.star.filter.permission import PermissionTypeFilter
from astrbot.core.star.star import star_map
from astrbot.core.star.star_handler import StarHandlerMetadata, star_handlers_registry
from astrbot.core.utils.command_parser import CommandParserMixin
from .utils.rst_scene import RstScene
class AlterCmdCommands(CommandParserMixin):
def __init__(self, context: star.Context) -> None:
self.context = context
async def update_reset_permission(self, scene_key: str, perm_type: str) -> None:
"""更新reset命令在特定场景下的权限设置"""
from astrbot.api import sp
alter_cmd_cfg: dict[str, dict[str, dict[str, str]]] = (
await sp.global_get("alter_cmd", {}) or {}
)
plugin_cfg = alter_cmd_cfg.get("astrbot", {})
reset_cfg = plugin_cfg.get("reset", {})
reset_cfg[scene_key] = perm_type
plugin_cfg["reset"] = reset_cfg
alter_cmd_cfg["astrbot"] = plugin_cfg
await sp.global_put("alter_cmd", alter_cmd_cfg)
async def alter_cmd(self, event: AstrMessageEvent) -> None:
token = self.parse_commands(event.message_str)
if token.len < 3:
await event.send(
MessageChain().message(
"该指令用于设置指令或指令组的权限。\n"
"格式: /alter_cmd <cmd_name> <admin/member>\n"
"例1: /alter_cmd c1 admin 将 c1 设为管理员指令\n"
"例2: /alter_cmd g1 c1 admin 将 g1 指令组的 c1 子指令设为管理员指令\n"
"/alter_cmd reset config 打开 reset 权限配置",
),
)
return
# 兼容 reset scene 的专门配置
cmd_name = token.get(1)
cmd_type = token.get(2)
if cmd_name == "reset" and cmd_type == "config":
from astrbot.api import sp
alter_cmd_cfg: dict[str, dict[str, dict[str, str]]] = (
await sp.global_get("alter_cmd", {}) or {}
)
plugin_ = alter_cmd_cfg.get("astrbot", {})
reset_cfg = plugin_.get("reset", {})
group_unique_on = reset_cfg.get("group_unique_on", "admin")
group_unique_off = reset_cfg.get("group_unique_off", "admin")
private = reset_cfg.get("private", "member")
config_menu = f"""reset命令权限细粒度配置
当前配置:
1. 群聊+会话隔离开: {group_unique_on}
2. 群聊+会话隔离关: {group_unique_off}
3. 私聊: {private}
修改指令格式:
/alter_cmd reset scene <场景编号> <admin/member>
例如: /alter_cmd reset scene 2 member"""
await event.send(MessageChain().message(config_menu))
return
if cmd_name == "reset" and cmd_type == "scene" and token.len >= 4:
scene_num = token.get(3)
perm_type = token.get(4)
if scene_num is None or perm_type is None:
await event.send(MessageChain().message("场景编号和权限类型不能为空"))
return
if not scene_num.isdigit() or int(scene_num) < 1 or int(scene_num) > 3:
await event.send(
MessageChain().message("场景编号必须是 1-3 之间的数字"),
)
return
if perm_type not in ["admin", "member"]:
await event.send(
MessageChain().message("权限类型错误,只能是 admin 或 member"),
)
return
scene_index = int(scene_num)
scene = RstScene.from_index(scene_index)
scene_key = scene.key
await self.update_reset_permission(scene_key, perm_type)
await event.send(
MessageChain().message(
f"已将 reset 命令在{scene.name}场景下的权限设为{perm_type}",
),
)
return
if cmd_type not in ["admin", "member"]:
await event.send(
MessageChain().message("指令类型错误,可选类型有 admin, member"),
)
return
# 查找指令
cmd_name = " ".join(token.tokens[1:-1])
permission_type = token.get(-1)
if permission_type not in ["admin", "member"]:
await event.send(
MessageChain().message("指令类型错误,可选类型有 admin, member"),
)
return
found_command = None
cmd_group = False
for handler in star_handlers_registry:
assert isinstance(handler, StarHandlerMetadata)
for filter_ in handler.event_filters:
if isinstance(filter_, CommandFilter):
if filter_.equals(cmd_name):
found_command = handler
break
elif isinstance(filter_, CommandGroupFilter):
if filter_.equals(cmd_name):
found_command = handler
cmd_group = True
break
if not found_command:
await event.send(MessageChain().message("未找到该指令"))
return
found_plugin = star_map[found_command.handler_module_path]
from astrbot.api import sp
stored_alter_cmd_cfg: dict[str, dict[str, dict[str, str]]] = (
await sp.global_get("alter_cmd", {}) or {}
)
if found_plugin.name is None:
await event.send(MessageChain().message("未找到指令对应的插件名称"))
return
plugin_ = stored_alter_cmd_cfg.get(found_plugin.name, {})
cfg = plugin_.get(found_command.handler_name, {})
cfg["permission"] = permission_type
plugin_[found_command.handler_name] = cfg
stored_alter_cmd_cfg[found_plugin.name] = plugin_
await sp.global_put("alter_cmd", stored_alter_cmd_cfg)
# 注入权限过滤器
found_permission_filter = False
for filter_ in found_command.event_filters:
if isinstance(filter_, PermissionTypeFilter):
if permission_type == "admin":
from astrbot.api.event import filter
filter_.permission_type = filter.PermissionType.ADMIN
else:
from astrbot.api.event import filter
filter_.permission_type = filter.PermissionType.MEMBER
found_permission_filter = True
break
if not found_permission_filter:
from astrbot.api.event import filter
found_command.event_filters.insert(
0,
PermissionTypeFilter(
filter.PermissionType.ADMIN
if permission_type == "admin"
else filter.PermissionType.MEMBER,
),
)
cmd_group_str = "指令组" if cmd_group else "指令"
await event.send(
MessageChain().message(
f"已将「{cmd_name}{cmd_group_str} 的权限级别调整为 {permission_type}",
),
)

View File

@@ -0,0 +1,311 @@
from sqlalchemy import case, func, select
from sqlmodel import col
from astrbot.api import sp, star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
from astrbot.core import logger
from astrbot.core.agent.runners.deerflow.constants import (
DEERFLOW_AGENT_RUNNER_PROVIDER_ID_KEY,
DEERFLOW_PROVIDER_TYPE,
DEERFLOW_THREAD_ID_KEY,
)
from astrbot.core.agent.runners.deerflow.deerflow_api_client import DeerFlowAPIClient
from astrbot.core.db.po import ProviderStat
from astrbot.core.utils.active_event_registry import active_event_registry
from .utils.rst_scene import RstScene
THIRD_PARTY_AGENT_RUNNER_KEY = {
"dify": "dify_conversation_id",
"coze": "coze_conversation_id",
"dashscope": "dashscope_conversation_id",
DEERFLOW_PROVIDER_TYPE: DEERFLOW_THREAD_ID_KEY,
}
THIRD_PARTY_AGENT_RUNNER_STR = ", ".join(THIRD_PARTY_AGENT_RUNNER_KEY.keys())
async def _cleanup_deerflow_thread_if_present(
context: star.Context,
umo: str,
) -> None:
try:
thread_id = await sp.get_async(
scope="umo",
scope_id=umo,
key=DEERFLOW_THREAD_ID_KEY,
default="",
)
if not thread_id:
return
cfg = context.get_config(umo=umo)
provider_id = cfg["provider_settings"].get(
DEERFLOW_AGENT_RUNNER_PROVIDER_ID_KEY,
"",
)
if not provider_id:
return
merged_provider_config = context.provider_manager.get_provider_config_by_id(
provider_id,
merged=True,
)
if not merged_provider_config:
logger.warning(
"Failed to resolve DeerFlow provider config for remote thread cleanup: provider_id=%s",
provider_id,
)
return
client = DeerFlowAPIClient(
api_base=merged_provider_config.get(
"deerflow_api_base",
"http://127.0.0.1:2026",
),
api_key=merged_provider_config.get("deerflow_api_key", ""),
auth_header=merged_provider_config.get("deerflow_auth_header", ""),
proxy=merged_provider_config.get("proxy", ""),
)
try:
await client.delete_thread(thread_id)
finally:
try:
await client.close()
except Exception as e:
logger.warning(
"Failed to close DeerFlow API client after thread cleanup: %s",
e,
)
except Exception as e:
logger.warning(
"Failed to clean up DeerFlow thread for session %s: %s",
umo,
e,
)
async def _clear_third_party_agent_runner_state(
context: star.Context,
umo: str,
agent_runner_type: str,
) -> None:
session_key = THIRD_PARTY_AGENT_RUNNER_KEY.get(agent_runner_type)
if not session_key:
return
if agent_runner_type == DEERFLOW_PROVIDER_TYPE:
await _cleanup_deerflow_thread_if_present(context, umo)
await sp.remove_async(
scope="umo",
scope_id=umo,
key=session_key,
)
class ConversationCommands:
def __init__(self, context: star.Context) -> None:
self.context = context
async def _get_current_persona_id(self, session_id):
curr = await self.context.conversation_manager.get_curr_conversation_id(
session_id,
)
if not curr:
return None
conv = await self.context.conversation_manager.get_conversation(
session_id,
curr,
)
if not conv:
return None
return conv.persona_id
async def reset(self, message: AstrMessageEvent) -> None:
"""重置 LLM 会话"""
umo = message.unified_msg_origin
cfg = self.context.get_config(umo=message.unified_msg_origin)
is_unique_session = cfg["platform_settings"]["unique_session"]
is_group = bool(message.get_group_id())
scene = RstScene.get_scene(is_group, is_unique_session)
alter_cmd_cfg = await sp.get_async("global", "global", "alter_cmd", {})
plugin_config = alter_cmd_cfg.get("astrbot", {})
reset_cfg = plugin_config.get("reset", {})
required_perm = reset_cfg.get(
scene.key,
"admin" if is_group and not is_unique_session else "member",
)
if required_perm == "admin" and message.role != "admin":
message.set_result(
MessageEventResult().message(
f"Reset command requires admin permission in {scene.name} scenario, "
f"you (ID {message.get_sender_id()}) are not admin, cannot perform this action.",
),
)
return
agent_runner_type = cfg["provider_settings"]["agent_runner_type"]
if agent_runner_type in THIRD_PARTY_AGENT_RUNNER_KEY:
active_event_registry.stop_all(umo, exclude=message)
await _clear_third_party_agent_runner_state(
self.context,
umo,
agent_runner_type,
)
message.set_result(
MessageEventResult().message("✅ Conversation reset successfully.")
)
return
if not self.context.get_using_provider(umo):
message.set_result(
MessageEventResult().message(
"😕 Cannot find any LLM provider. Configure one first."
),
)
return
cid = await self.context.conversation_manager.get_curr_conversation_id(umo)
if not cid:
message.set_result(
MessageEventResult().message(
"😕 You are not in a conversation. Use /new to create one.",
),
)
return
active_event_registry.stop_all(umo, exclude=message)
await self.context.conversation_manager.update_conversation(
umo,
cid,
[],
)
ret = "✅ Conversation reset successfully."
message.set_extra("_clean_group_context_session", True)
message.set_result(MessageEventResult().message(ret))
async def stop(self, message: AstrMessageEvent) -> None:
"""停止当前会话正在运行的 Agent"""
cfg = self.context.get_config(umo=message.unified_msg_origin)
agent_runner_type = cfg["provider_settings"]["agent_runner_type"]
umo = message.unified_msg_origin
if agent_runner_type in THIRD_PARTY_AGENT_RUNNER_KEY:
stopped_count = active_event_registry.stop_all(umo, exclude=message)
else:
stopped_count = active_event_registry.request_agent_stop_all(
umo,
exclude=message,
)
if stopped_count > 0:
message.set_result(
MessageEventResult().message(
f"✅ Requested to stop {stopped_count} running tasks."
)
)
return
message.set_result(
MessageEventResult().message("✅ No running tasks in the current session.")
)
async def new_conv(self, message: AstrMessageEvent) -> None:
"""创建新对话"""
cfg = self.context.get_config(umo=message.unified_msg_origin)
agent_runner_type = cfg["provider_settings"]["agent_runner_type"]
if agent_runner_type in THIRD_PARTY_AGENT_RUNNER_KEY:
active_event_registry.stop_all(message.unified_msg_origin, exclude=message)
await _clear_third_party_agent_runner_state(
self.context,
message.unified_msg_origin,
agent_runner_type,
)
message.set_result(
MessageEventResult().message("✅ New conversation created.")
)
return
active_event_registry.stop_all(message.unified_msg_origin, exclude=message)
cpersona = await self._get_current_persona_id(message.unified_msg_origin)
cid = await self.context.conversation_manager.new_conversation(
message.unified_msg_origin,
message.get_platform_id(),
persona_id=cpersona,
)
message.set_extra("_clean_group_context_session", True)
message.set_result(
MessageEventResult().message(
f"✅ Switched to new conversation: {cid[:4]}"
),
)
async def stats(self, message: AstrMessageEvent) -> None:
"""Show token usage statistics for the current conversation."""
umo = message.unified_msg_origin
cid = await self.context.conversation_manager.get_curr_conversation_id(umo)
if not cid:
message.set_result(
MessageEventResult().message(
"❌ You are not in a conversation. Use /new to create one."
),
)
return
db = self.context.get_db()
async with db.get_db() as session:
result = await session.execute(
select(
func.count(case((col(ProviderStat.id).is_not(None), 1))).label(
"record_count",
),
func.coalesce(func.sum(ProviderStat.token_input_other), 0).label(
"total_input_other",
),
func.coalesce(func.sum(ProviderStat.token_input_cached), 0).label(
"total_input_cached",
),
func.coalesce(func.sum(ProviderStat.token_output), 0).label(
"total_output",
),
).where(
col(ProviderStat.agent_type) == "internal",
col(ProviderStat.conversation_id) == cid,
)
)
stats = result.one()
if stats.record_count == 0:
message.set_result(
MessageEventResult().message(
"📊 No stats available for this conversation yet."
),
)
return
total_input_other = stats.total_input_other
total_input_cached = stats.total_input_cached
total_output = stats.total_output
total_tokens = total_input_other + total_input_cached + total_output
ret = (
f"📊 Conversation Token usage (ID: {cid[:8]}...)\n"
f"Total: {total_tokens:,}\n"
f"Input (cached): {total_input_cached:,}\n"
f"Input (other): {total_input_other:,}\n"
f"Output: {total_output:,}\n"
)
message.set_result(MessageEventResult().message(ret))

View File

@@ -0,0 +1,89 @@
import aiohttp
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
from astrbot.core.config.default import VERSION
from astrbot.core.star import command_management
from astrbot.core.utils.io import get_dashboard_version
class HelpCommand:
def __init__(self, context: star.Context) -> None:
self.context = context
async def _query_astrbot_notice(self):
try:
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.get(
"https://astrbot.app/notice.json",
timeout=2,
) as resp:
return (await resp.json())["notice"]
except BaseException:
return ""
async def _build_reserved_command_lines(self) -> list[str]:
"""使用实时指令配置生成内置指令清单,确保重命名/禁用后与实际生效状态保持一致。"""
try:
commands = await command_management.list_commands()
except BaseException:
return []
lines: list[str] = []
def walk(items: list[dict], indent: int = 0) -> None:
for item in items:
if not item.get("reserved") or not item.get("enabled"):
continue
# 仅展示顶级指令或指令组
if item.get("type") == "sub_command":
continue
if item.get("parent_signature"):
continue
effective = (
item.get("effective_command")
or item.get("original_command")
or item.get("handler_name")
)
if not effective or effective in [
"set",
"unset",
"help",
"dashboard_update",
]:
continue
description = item.get("description") or ""
desc_text = f" - {description}" if description else ""
indent_prefix = " " * indent
lines.append(f"{indent_prefix}/{effective}{desc_text}")
walk(commands)
return lines
async def help(self, event: AstrMessageEvent) -> None:
"""查看帮助"""
notice = ""
try:
notice = await self._query_astrbot_notice()
except BaseException:
pass
dashboard_version = await get_dashboard_version()
command_lines = await self._build_reserved_command_lines()
commands_section = (
"\n".join(command_lines)
if command_lines
else "No enabled built-in commands."
)
msg_parts = [
f"AstrBot v{VERSION}(WebUI: {dashboard_version})",
commands_section,
]
if notice:
msg_parts.append(notice)
msg = "\n".join(msg_parts)
event.set_result(MessageEventResult().message(msg).use_t2i(False))

View File

@@ -0,0 +1,20 @@
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageChain
class LLMCommands:
def __init__(self, context: star.Context) -> None:
self.context = context
async def llm(self, event: AstrMessageEvent) -> None:
"""开启/关闭 LLM"""
cfg = self.context.get_config(umo=event.unified_msg_origin)
enable = cfg["provider_settings"].get("enable", True)
if enable:
cfg["provider_settings"]["enable"] = False
status = "关闭"
else:
cfg["provider_settings"]["enable"] = True
status = "开启"
cfg.save_config()
await event.send(MessageChain().message(f"{status} LLM 聊天功能。"))

View File

@@ -0,0 +1,48 @@
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
from astrbot.core.umo_alias import get_event_auto_name, normalize_umo_name
class NameCommand:
def __init__(self, context: star.Context) -> None:
self.context = context
async def name(self, event: AstrMessageEvent, alias: str) -> None:
umo = event.unified_msg_origin
auto_name = get_event_auto_name(event)
alias = normalize_umo_name(alias)
if not alias:
saved_alias = await self.context.get_db().get_umo_alias(umo)
user_alias = normalize_umo_name(
saved_alias.user_alias if saved_alias else ""
)
event.set_result(
MessageEventResult()
.message(
"\n".join(
[
"Usage: /name <name>",
f"UMO: {umo}",
f"Auto name: {auto_name or '(empty)'}",
f"Alias: {user_alias or '(empty)'}",
]
)
)
.use_t2i(False)
)
return
sender_id = str(event.get_sender_id() or "")
await self.context.get_db().upsert_umo_alias(
umo=umo,
creator_sender_id=sender_id,
auto_name=auto_name,
user_alias=alias,
)
event.set_result(
MessageEventResult()
.message(f"UMO name set to: {alias}\nUMO: {umo}")
.use_t2i(False)
)

View File

@@ -0,0 +1,214 @@
import builtins
from typing import TYPE_CHECKING
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
if TYPE_CHECKING:
from astrbot.core.db.po import Persona
class PersonaCommands:
def __init__(self, context: star.Context) -> None:
self.context = context
def _build_tree_output(
self,
folder_tree: list[dict],
all_personas: list["Persona"],
depth: int = 0,
) -> list[str]:
"""递归构建树状输出,使用短线条表示层级"""
lines: list[str] = []
# 使用短线条作为缩进前缀,每层只用 "" 加一个空格
prefix = " " * depth
for folder in folder_tree:
# 输出文件夹
lines.append(f"{prefix}├ 📁 {folder['name']}/")
# 获取该文件夹下的人格
folder_personas = [
p for p in all_personas if p.folder_id == folder["folder_id"]
]
child_prefix = " " * (depth + 1)
# 输出该文件夹下的人格
for persona in folder_personas:
lines.append(f"{child_prefix}├ 👤 {persona.persona_id}")
# 递归处理子文件夹
children = folder.get("children", [])
if children:
lines.extend(
self._build_tree_output(
children,
all_personas,
depth + 1,
),
)
return lines
async def persona(self, message: AstrMessageEvent) -> None:
parts = message.message_str.split(" ")
umo = message.unified_msg_origin
curr_persona_name = ""
cid = await self.context.conversation_manager.get_curr_conversation_id(umo)
default_persona = await self.context.persona_manager.get_default_persona_v3(
umo=umo,
)
force_applied_persona_id = None
curr_cid_title = ""
if cid:
conv = await self.context.conversation_manager.get_conversation(
unified_msg_origin=umo,
conversation_id=cid,
create_if_not_exists=True,
)
if conv is None:
message.set_result(
MessageEventResult().message(
"当前对话不存在,请先使用 /new 新建一个对话。",
),
)
return
provider_settings = self.context.get_config(umo=umo).get(
"provider_settings",
{},
)
(
persona_id,
_,
force_applied_persona_id,
_,
) = await self.context.persona_manager.resolve_selected_persona(
umo=umo,
conversation_persona_id=conv.persona_id,
platform_name=message.get_platform_name(),
provider_settings=provider_settings,
)
if persona_id == "[%None]":
curr_persona_name = ""
elif persona_id:
curr_persona_name = persona_id
if force_applied_persona_id:
curr_persona_name = f"{curr_persona_name} (自定义规则)"
curr_cid_title = conv.title or "新对话"
curr_cid_title += f"({cid[:4]})"
if len(parts) == 1:
message.set_result(
MessageEventResult()
.message(
f"""[Persona]
- 人格情景列表: `/persona list`
- 设置人格情景: `/persona 人格`
- 人格情景详细信息: `/persona view 人格`
- 取消人格: `/persona unset`
默认人格情景: {default_persona["name"]}
当前对话 {curr_cid_title} 的人格情景: {curr_persona_name}
配置人格情景请前往管理面板-配置页
""",
)
.use_t2i(False),
)
elif parts[1] == "list":
# 获取文件夹树和所有人格
folder_tree = await self.context.persona_manager.get_folder_tree()
all_personas = self.context.persona_manager.personas
lines = ["📂 人格列表:\n"]
# 构建树状输出
tree_lines = self._build_tree_output(folder_tree, all_personas)
lines.extend(tree_lines)
# 输出根目录下的人格(没有文件夹的)
root_personas = [p for p in all_personas if p.folder_id is None]
if root_personas:
if tree_lines: # 如果有文件夹内容,加个空行
lines.append("")
for persona in root_personas:
lines.append(f"👤 {persona.persona_id}")
# 统计信息
total_count = len(all_personas)
lines.append(f"\n{total_count} 个人格")
lines.append("\n*使用 `/persona <人格名>` 设置人格")
lines.append("*使用 `/persona view <人格名>` 查看详细信息")
msg = "\n".join(lines)
message.set_result(MessageEventResult().message(msg).use_t2i(False))
elif parts[1] == "view":
if len(parts) == 2:
message.set_result(MessageEventResult().message("请输入人格情景名"))
return
ps = parts[2].strip()
if persona_info := next(
builtins.filter(
lambda persona: persona["name"] == ps,
self.context.provider_manager.personas,
),
None,
):
msg = f"人格{ps}的详细信息:\n"
msg += f"{persona_info['prompt']}\n"
else:
msg = f"人格{ps}不存在"
message.set_result(MessageEventResult().message(msg))
elif parts[1] == "unset":
if not cid:
message.set_result(
MessageEventResult().message("当前没有对话,无法取消人格。"),
)
return
await self.context.conversation_manager.update_conversation_persona_id(
message.unified_msg_origin,
"[%None]",
)
message.set_result(MessageEventResult().message("取消人格成功。"))
else:
ps = "".join(parts[1:]).strip()
if not cid:
message.set_result(
MessageEventResult().message(
"当前没有对话,请先开始对话或使用 /new 创建一个对话。",
),
)
return
if persona_info := next(
builtins.filter(
lambda persona: persona["name"] == ps,
self.context.provider_manager.personas,
),
None,
):
await self.context.conversation_manager.update_conversation_persona_id(
message.unified_msg_origin,
ps,
)
force_warn_msg = ""
if force_applied_persona_id:
force_warn_msg = "提醒:由于自定义规则,您现在切换的人格将不会生效。"
message.set_result(
MessageEventResult().message(
f"设置成功。如果您正在切换到不同的人格,请注意使用 /reset 来清空上下文,防止原人格对话影响现人格。{force_warn_msg}",
),
)
else:
message.set_result(
MessageEventResult().message(
"不存在该人格情景。使用 /persona list 查看所有。",
),
)

View File

@@ -0,0 +1,125 @@
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
from astrbot.core import DEMO_MODE, logger
from astrbot.core.star.filter.command import CommandFilter
from astrbot.core.star.filter.command_group import CommandGroupFilter
from astrbot.core.star.star_handler import StarHandlerMetadata, star_handlers_registry
class PluginCommands:
def __init__(self, context: star.Context) -> None:
self.context = context
async def plugin_ls(self, event: AstrMessageEvent) -> None:
"""获取已经安装的插件列表。"""
parts = ["已加载的插件:\n"]
for plugin in self.context.get_all_stars():
line = f"- `{plugin.name}` By {plugin.author}: {plugin.desc}"
if not plugin.activated:
line += " (未启用)"
parts.append(line + "\n")
if len(parts) == 1:
plugin_list_info = "没有加载任何插件。"
else:
plugin_list_info = "".join(parts)
plugin_list_info += "\n使用 /plugin help <插件名> 查看插件帮助和加载的指令。\n使用 /plugin on/off <插件名> 启用或者禁用插件。"
event.set_result(
MessageEventResult().message(f"{plugin_list_info}").use_t2i(False),
)
async def plugin_off(self, event: AstrMessageEvent, plugin_name: str = "") -> None:
"""禁用插件"""
if DEMO_MODE:
event.set_result(MessageEventResult().message("演示模式下无法禁用插件。"))
return
if not plugin_name:
event.set_result(
MessageEventResult().message("/plugin off <插件名> 禁用插件。"),
)
return
if self.context._star_manager is None:
event.set_result(MessageEventResult().message("插件管理器未初始化。"))
return
await self.context._star_manager.turn_off_plugin(plugin_name)
event.set_result(MessageEventResult().message(f"插件 {plugin_name} 已禁用。"))
async def plugin_on(self, event: AstrMessageEvent, plugin_name: str = "") -> None:
"""启用插件"""
if DEMO_MODE:
event.set_result(MessageEventResult().message("演示模式下无法启用插件。"))
return
if not plugin_name:
event.set_result(
MessageEventResult().message("/plugin on <插件名> 启用插件。"),
)
return
if self.context._star_manager is None:
event.set_result(MessageEventResult().message("插件管理器未初始化。"))
return
await self.context._star_manager.turn_on_plugin(plugin_name)
event.set_result(MessageEventResult().message(f"插件 {plugin_name} 已启用。"))
async def plugin_get(self, event: AstrMessageEvent, plugin_repo: str = "") -> None:
"""安装插件"""
if DEMO_MODE:
event.set_result(MessageEventResult().message("演示模式下无法安装插件。"))
return
if not plugin_repo:
event.set_result(
MessageEventResult().message("/plugin get <插件仓库地址> 安装插件"),
)
return
logger.info(f"准备从 {plugin_repo} 安装插件。")
if self.context._star_manager:
star_mgr = self.context._star_manager
try:
await star_mgr.install_plugin(plugin_repo)
event.set_result(MessageEventResult().message("安装插件成功。"))
except Exception as e:
logger.error(f"安装插件失败: {e}")
event.set_result(MessageEventResult().message(f"安装插件失败: {e}"))
return
async def plugin_help(self, event: AstrMessageEvent, plugin_name: str = "") -> None:
"""获取插件帮助"""
if not plugin_name:
event.set_result(
MessageEventResult().message("/plugin help <插件名> 查看插件信息。"),
)
return
plugin = self.context.get_registered_star(plugin_name)
if plugin is None:
event.set_result(MessageEventResult().message("未找到此插件。"))
return
help_msg = ""
help_msg += f"\n\n✨ 作者: {plugin.author}\n✨ 版本: {plugin.version}"
command_handlers = []
command_names = []
for handler in star_handlers_registry:
assert isinstance(handler, StarHandlerMetadata)
if handler.handler_module_path != plugin.module_path:
continue
for filter_ in handler.event_filters:
if isinstance(filter_, CommandFilter):
command_handlers.append(handler)
command_names.append(filter_.command_name)
break
if isinstance(filter_, CommandGroupFilter):
command_handlers.append(handler)
command_names.append(filter_.group_name)
if len(command_handlers) > 0:
parts = ["\n\n🔧 指令列表:\n"]
for i in range(len(command_handlers)):
line = f"- {command_names[i]}"
if command_handlers[i].desc:
line += f": {command_handlers[i].desc}"
parts.append(line + "\n")
parts.append("\nTip: 指令的触发需要添加唤醒前缀,默认为 /。")
help_msg += "".join(parts)
ret = f"🧩 插件 {plugin_name} 帮助信息:\n" + help_msg
ret += "更多帮助信息请查看插件仓库 README。"
event.set_result(MessageEventResult().message(ret).use_t2i(False))

View File

@@ -0,0 +1,330 @@
from __future__ import annotations
import asyncio
from astrbot import logger
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
from astrbot.core.provider.entities import ProviderType
from astrbot.core.utils.error_redaction import safe_error
class ProviderCommands:
def __init__(self, context: star.Context) -> None:
self.context = context
def _log_reachability_failure(
self,
provider,
provider_capability_type: ProviderType | None,
err_code: str,
err_reason: str,
) -> None:
meta = provider.meta()
logger.warning(
"Provider reachability check failed: id=%s type=%s code=%s reason=%s",
meta.id,
provider_capability_type.name if provider_capability_type else "unknown",
err_code,
err_reason,
)
async def _test_provider_capability(self, provider):
meta = provider.meta()
provider_capability_type = meta.provider_type
try:
await provider.test()
return True, None, None
except Exception as e:
err_code = "TEST_FAILED"
err_reason = safe_error("", e)
self._log_reachability_failure(
provider,
provider_capability_type,
err_code,
err_reason,
)
return False, err_code, err_reason
async def _build_provider_display_data(
self,
providers,
provider_type: str,
reachability_check_enabled: bool,
) -> list[dict]:
if not providers:
return []
if reachability_check_enabled:
check_results = await asyncio.gather(
*[self._test_provider_capability(provider) for provider in providers],
return_exceptions=True,
)
else:
check_results = [None for _ in providers]
display_data = []
for provider, reachable in zip(providers, check_results, strict=False):
meta = provider.meta()
id_ = meta.id
error_code = None
if isinstance(reachable, asyncio.CancelledError):
raise reachable
if isinstance(reachable, Exception):
self._log_reachability_failure(
provider,
None,
reachable.__class__.__name__,
safe_error("", reachable),
)
reachable_flag = False
error_code = reachable.__class__.__name__
elif isinstance(reachable, tuple):
reachable_flag, error_code, _ = reachable
else:
reachable_flag = reachable
if provider_type == "llm":
info = f"{id_} ({meta.model})"
else:
info = f"{id_}"
if reachable_flag is True:
mark = ""
elif reachable_flag is False:
if error_code:
mark = f" ❌(errcode: {error_code})"
else:
mark = ""
else:
mark = ""
display_data.append(
{
"info": info,
"mark": mark,
"provider": provider,
},
)
return display_data
async def provider(
self,
event: AstrMessageEvent,
idx: str | int | None = None,
idx2: int | None = None,
) -> None:
"""查看或者切换 LLM Provider"""
umo = event.unified_msg_origin
cfg = self.context.get_config(umo).get("provider_settings", {})
reachability_check_enabled = cfg.get("reachability_check", True)
if idx is None:
parts = ["## LLM Providers\n"]
llms = list(self.context.get_all_providers())
ttss = self.context.get_all_tts_providers()
stts = self.context.get_all_stt_providers()
if reachability_check_enabled and (llms or ttss or stts):
await event.send(
MessageEventResult().message("👀 Testing provider reachability..."),
)
llm_data, tts_data, stt_data = await asyncio.gather(
self._build_provider_display_data(
llms,
"llm",
reachability_check_enabled,
),
self._build_provider_display_data(
ttss,
"tts",
reachability_check_enabled,
),
self._build_provider_display_data(
stts,
"stt",
reachability_check_enabled,
),
)
provider_using = self.context.get_using_provider(umo=umo)
for i, d in enumerate(llm_data):
line = f"{i + 1}. {d['info']}{d['mark']}"
if (
provider_using
and provider_using.meta().id == d["provider"].meta().id
):
line += " 👈"
parts.append(line + "\n")
if tts_data:
parts.append("\n## TTS Providers\n")
tts_using = self.context.get_using_tts_provider(umo=umo)
for i, d in enumerate(tts_data):
line = f"{i + 1}. {d['info']}{d['mark']}"
if tts_using and tts_using.meta().id == d["provider"].meta().id:
line += " 👈"
parts.append(line + "\n")
if stt_data:
parts.append("\n## STT Providers\n")
stt_using = self.context.get_using_stt_provider(umo=umo)
for i, d in enumerate(stt_data):
line = f"{i + 1}. {d['info']}{d['mark']}"
if stt_using and stt_using.meta().id == d["provider"].meta().id:
line += " 👈"
parts.append(line + "\n")
parts.append("\nUse /provider <idx> to switch LLM providers.")
ret = "".join(parts)
if ttss:
ret += "\nUse /provider tts <idx> to switch TTS providers."
if stts:
ret += "\nUse /provider stt <idx> to switch STT providers."
event.set_result(MessageEventResult().message(ret))
elif idx == "tts":
if idx2 is None:
event.set_result(
MessageEventResult().message("Please enter the index."),
)
return
if idx2 > len(self.context.get_all_tts_providers()) or idx2 < 1:
event.set_result(
MessageEventResult().message("❌ Invalid provider index."),
)
return
provider = self.context.get_all_tts_providers()[idx2 - 1]
id_ = provider.meta().id
await self.context.provider_manager.set_provider(
provider_id=id_,
provider_type=ProviderType.TEXT_TO_SPEECH,
umo=umo,
)
event.set_result(
MessageEventResult().message(f"✅ Successfully switched to {id_}."),
)
elif idx == "stt":
if idx2 is None:
event.set_result(
MessageEventResult().message("Please enter the index."),
)
return
if idx2 > len(self.context.get_all_stt_providers()) or idx2 < 1:
event.set_result(
MessageEventResult().message("❌ Invalid provider index."),
)
return
provider = self.context.get_all_stt_providers()[idx2 - 1]
id_ = provider.meta().id
await self.context.provider_manager.set_provider(
provider_id=id_,
provider_type=ProviderType.SPEECH_TO_TEXT,
umo=umo,
)
event.set_result(
MessageEventResult().message(f"✅ Successfully switched to {id_}."),
)
elif isinstance(idx, int):
if idx > len(self.context.get_all_providers()) or idx < 1:
event.set_result(
MessageEventResult().message("❌ Invalid provider index."),
)
return
provider = self.context.get_all_providers()[idx - 1]
id_ = provider.meta().id
await self.context.provider_manager.set_provider(
provider_id=id_,
provider_type=ProviderType.CHAT_COMPLETION,
umo=umo,
)
event.set_result(
MessageEventResult().message(f"✅ Successfully switched to {id_}."),
)
else:
event.set_result(MessageEventResult().message("❌ Invalid parameter."))
async def model_ls(
self,
event: AstrMessageEvent,
idx_or_name: int | str | None = None,
) -> None:
"""查看或者切换当前 Provider 的模型。"""
umo = event.unified_msg_origin
provider = self.context.get_using_provider(umo=umo)
if provider is None:
event.set_result(
MessageEventResult().message("未找到任何 LLM 提供商。请先配置。"),
)
return
try:
models = await provider.get_models()
except Exception as e:
event.set_result(
MessageEventResult().message(
f"获取模型列表失败: {safe_error('', e)}",
),
)
return
current_model = provider.get_model()
if idx_or_name is None:
if not models:
event.set_result(
MessageEventResult().message(
f"当前模型: {current_model}\n此提供商未返回可切换模型列表。",
),
)
return
parts = [f"当前模型: {current_model}\n\n可用模型:\n"]
for index, model_name in enumerate(models, start=1):
suffix = " 👈" if model_name == current_model else ""
parts.append(f"{index}. {model_name}{suffix}\n")
parts.append("\n使用 /model <序号> 或 /model <模型名> 切换模型。")
event.set_result(MessageEventResult().message("".join(parts)))
return
selected_model: str | None = None
if isinstance(idx_or_name, int):
if 1 <= idx_or_name <= len(models):
selected_model = models[idx_or_name - 1]
else:
text = idx_or_name.strip()
if text.isdigit():
model_index = int(text)
if 1 <= model_index <= len(models):
selected_model = models[model_index - 1]
elif text:
selected_model = text
if not selected_model:
event.set_result(MessageEventResult().message("❌ Invalid model index."))
return
provider.set_model(selected_model)
provider.provider_config["model"] = selected_model
cfg = self.context.get_config(umo)
providers_config = cfg.get("provider", [])
if isinstance(providers_config, list):
for provider_config in providers_config:
if not isinstance(provider_config, dict):
continue
if provider_config.get("id") == provider.meta().id:
provider_config["model"] = selected_model
break
cfg.save_config()
event.set_result(
MessageEventResult().message(
f"✅ Successfully switched model to {selected_model}.",
),
)

View File

@@ -0,0 +1,50 @@
from astrbot.api import sp, star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
def _normalize_session_variables(value: object) -> dict[str, str]:
if not isinstance(value, dict):
return {}
return {
key: value
for key, value in value.items()
if isinstance(key, str) and isinstance(value, str)
}
class SetUnsetCommands:
def __init__(self, context: star.Context) -> None:
self.context = context
async def set_variable(self, event: AstrMessageEvent, key: str, value: str) -> None:
"""设置会话变量"""
uid = event.unified_msg_origin
session_var = _normalize_session_variables(
await sp.session_get(uid, "session_variables", {}),
)
session_var[key] = value
await sp.session_put(uid, "session_variables", session_var)
event.set_result(
MessageEventResult().message(
f"会话 {uid} 变量 {key} 存储成功。使用 /unset 移除。",
),
)
async def unset_variable(self, event: AstrMessageEvent, key: str) -> None:
"""移除会话变量"""
uid = event.unified_msg_origin
session_var = _normalize_session_variables(
await sp.session_get(uid, "session_variables", {}),
)
if key not in session_var:
event.set_result(
MessageEventResult().message("没有那个变量名。格式 /unset 变量名。"),
)
else:
del session_var[key]
await sp.session_put(uid, "session_variables", session_var)
event.set_result(
MessageEventResult().message(f"会话 {uid} 变量 {key} 移除成功。"),
)

View File

@@ -0,0 +1,36 @@
"""会话ID命令"""
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
class SIDCommand:
"""会话ID命令类"""
def __init__(self, context: star.Context) -> None:
self.context = context
async def sid(self, event: AstrMessageEvent) -> None:
"""获取消息来源信息"""
sid = event.unified_msg_origin
user_id = str(event.get_sender_id())
umo_platform = event.session.platform_id
umo_msg_type = event.session.message_type.value
umo_session_id = event.session.session_id
ret = (
f"UMO: 「{sid}」 此值可用于设置白名单。\n"
f"UID: 「{user_id}」 此值可用于设置管理员。\n"
f"消息会话来源信息:\n"
f" 机器人 ID: 「{umo_platform}\n"
f" 消息类型: 「{umo_msg_type}\n"
f" 会话 ID: 「{umo_session_id}\n"
f"消息来源可用于配置机器人的配置文件路由。"
)
if (
self.context.get_config()["platform_settings"]["unique_session"]
and event.get_group_id()
):
ret += f"\n\n当前处于独立会话模式, 此群 ID: 「{event.get_group_id()}」, 也可将此 ID 加入白名单来放行整个群聊。"
event.set_result(MessageEventResult().message(ret).use_t2i(False))

View File

@@ -0,0 +1,23 @@
"""文本转图片命令"""
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
class T2ICommand:
"""文本转图片命令类"""
def __init__(self, context: star.Context) -> None:
self.context = context
async def t2i(self, event: AstrMessageEvent) -> None:
"""开关文本转图片"""
config = self.context.get_config(umo=event.unified_msg_origin)
if config["t2i"]:
config["t2i"] = False
config.save_config()
event.set_result(MessageEventResult().message("已关闭文本转图片模式。"))
return
config["t2i"] = True
config.save_config()
event.set_result(MessageEventResult().message("已开启文本转图片模式。"))

View File

@@ -0,0 +1,36 @@
"""文本转语音命令"""
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageEventResult
from astrbot.core.star.session_llm_manager import SessionServiceManager
class TTSCommand:
"""文本转语音命令类"""
def __init__(self, context: star.Context) -> None:
self.context = context
async def tts(self, event: AstrMessageEvent) -> None:
"""开关文本转语音(会话级别)"""
umo = event.unified_msg_origin
ses_tts = await SessionServiceManager.is_tts_enabled_for_session(umo)
cfg = self.context.get_config(umo=umo)
tts_enable = cfg["provider_tts_settings"]["enable"]
# 切换状态
new_status = not ses_tts
await SessionServiceManager.set_tts_status_for_session(umo, new_status)
status_text = "已开启" if new_status else "已关闭"
if new_status and not tts_enable:
event.set_result(
MessageEventResult().message(
f"{status_text}当前会话的文本转语音。但 TTS 功能在配置中未启用,请前往 WebUI 开启。",
),
)
else:
event.set_result(
MessageEventResult().message(f"{status_text}当前会话的文本转语音。"),
)

View File

@@ -0,0 +1,26 @@
from enum import Enum
class RstScene(Enum):
GROUP_UNIQUE_ON = ("group_unique_on", "群聊+会话隔离开启")
GROUP_UNIQUE_OFF = ("group_unique_off", "群聊+会话隔离关闭")
PRIVATE = ("private", "私聊")
@property
def key(self) -> str:
return self.value[0]
@property
def name(self) -> str:
return self.value[1]
@classmethod
def from_index(cls, index: int) -> "RstScene":
mapping = {1: cls.GROUP_UNIQUE_ON, 2: cls.GROUP_UNIQUE_OFF, 3: cls.PRIVATE}
return mapping[index]
@classmethod
def get_scene(cls, is_group: bool, is_unique_session: bool) -> "RstScene":
if is_group:
return cls.GROUP_UNIQUE_ON if is_unique_session else cls.GROUP_UNIQUE_OFF
return cls.PRIVATE

View File

@@ -0,0 +1,195 @@
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, filter
from astrbot.core.star.filter.command import GreedyStr
from .commands import (
AdminCommands,
AlterCmdCommands,
ConversationCommands,
HelpCommand,
LLMCommands,
NameCommand,
PluginCommands,
ProviderCommands,
SetUnsetCommands,
SIDCommand,
T2ICommand,
TTSCommand,
)
class Main(star.Star):
def __init__(self, context: star.Context) -> None:
self.context = context
self.help_c = HelpCommand(self.context)
self.llm_c = LLMCommands(self.context)
self.plugin_c = PluginCommands(self.context)
self.admin_c = AdminCommands(self.context)
self.conversation_c = ConversationCommands(self.context)
self.name_c = NameCommand(self.context)
self.provider_c = ProviderCommands(self.context)
self.setunset_c = SetUnsetCommands(self.context)
self.t2i_c = T2ICommand(self.context)
self.tts_c = TTSCommand(self.context)
self.sid_c = SIDCommand(self.context)
self.alter_cmd_c = AlterCmdCommands(self.context)
@filter.command("help")
async def help(self, event: AstrMessageEvent) -> None:
"""查看帮助"""
await self.help_c.help(event)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("llm")
async def llm(self, event: AstrMessageEvent) -> None:
"""开启/关闭 LLM"""
await self.llm_c.llm(event)
@filter.command_group("plugin")
def plugin(self) -> None:
"""插件管理"""
@plugin.command("ls")
async def plugin_ls(self, event: AstrMessageEvent) -> None:
"""获取已经安装的插件列表。"""
await self.plugin_c.plugin_ls(event)
@filter.permission_type(filter.PermissionType.ADMIN)
@plugin.command("off")
async def plugin_off(self, event: AstrMessageEvent, plugin_name: str = "") -> None:
"""禁用插件"""
await self.plugin_c.plugin_off(event, plugin_name)
@filter.permission_type(filter.PermissionType.ADMIN)
@plugin.command("on")
async def plugin_on(self, event: AstrMessageEvent, plugin_name: str = "") -> None:
"""启用插件"""
await self.plugin_c.plugin_on(event, plugin_name)
@filter.permission_type(filter.PermissionType.ADMIN)
@plugin.command("get")
async def plugin_get(self, event: AstrMessageEvent, plugin_repo: str = "") -> None:
"""安装插件"""
await self.plugin_c.plugin_get(event, plugin_repo)
@plugin.command("help")
async def plugin_help(self, event: AstrMessageEvent, plugin_name: str = "") -> None:
"""获取插件帮助"""
await self.plugin_c.plugin_help(event, plugin_name)
@filter.command("t2i")
async def t2i(self, event: AstrMessageEvent) -> None:
"""开关文本转图片"""
await self.t2i_c.t2i(event)
@filter.command("tts")
async def tts(self, event: AstrMessageEvent) -> None:
"""开关文本转语音(会话级别)"""
await self.tts_c.tts(event)
@filter.command("sid")
async def sid(self, event: AstrMessageEvent) -> None:
"""获取会话 ID 和 管理员 ID"""
await self.sid_c.sid(event)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("name")
async def name(self, event: AstrMessageEvent, alias: GreedyStr) -> None:
"""Set display name for current UMO"""
await self.name_c.name(event, alias)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("op")
async def op(self, event: AstrMessageEvent, admin_id: str = "") -> None:
"""授权管理员。op <admin_id>"""
await self.admin_c.op(event, admin_id)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("deop")
async def deop(self, event: AstrMessageEvent, admin_id: str) -> None:
"""取消授权管理员。deop <admin_id>"""
await self.admin_c.deop(event, admin_id)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("wl")
async def wl(self, event: AstrMessageEvent, sid: str = "") -> None:
"""添加白名单。wl <sid>"""
await self.admin_c.wl(event, sid)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("dwl")
async def dwl(self, event: AstrMessageEvent, sid: str) -> None:
"""删除白名单。dwl <sid>"""
await self.admin_c.dwl(event, sid)
@filter.command("stats")
async def stats(self, message: AstrMessageEvent) -> None:
"""Show token usage statistics for the current conversation"""
await self.conversation_c.stats(message)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("provider")
async def provider(
self,
event: AstrMessageEvent,
idx: str | int | None = None,
idx2: int | None = None,
) -> None:
"""查看或者切换 LLM Provider"""
await self.provider_c.provider(event, idx, idx2)
@filter.command("reset")
async def reset(self, message: AstrMessageEvent) -> None:
"""重置 LLM 会话"""
await self.conversation_c.reset(message)
@filter.command("stop")
async def stop(self, message: AstrMessageEvent) -> None:
"""停止当前会话中正在运行的 Agent"""
await self.conversation_c.stop(message)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("model")
async def model_ls(
self,
message: AstrMessageEvent,
idx_or_name: int | str | None = None,
) -> None:
"""查看或者切换模型"""
await self.provider_c.model_ls(message, idx_or_name)
@filter.command("history")
async def his(self, message: AstrMessageEvent, page: int = 1) -> None:
"""查看对话记录"""
await self.conversation_c.his(message, page)
@filter.command("ls")
async def convs(self, message: AstrMessageEvent, page: int = 1) -> None:
"""查看对话列表"""
await self.conversation_c.convs(message, page)
@filter.command("new")
async def new_conv(self, message: AstrMessageEvent) -> None:
"""创建新对话"""
await self.conversation_c.new_conv(message)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("dashboard_update")
async def update_dashboard(self, event: AstrMessageEvent) -> None:
"""更新管理面板"""
await self.admin_c.update_dashboard(event)
@filter.command("set")
async def set_variable(self, event: AstrMessageEvent, key: str, value: str) -> None:
await self.setunset_c.set_variable(event, key, value)
@filter.command("unset")
async def unset_variable(self, event: AstrMessageEvent, key: str) -> None:
await self.setunset_c.unset_variable(event, key)
@filter.permission_type(filter.PermissionType.ADMIN)
@filter.command("alter_cmd", alias={"alter"})
async def alter_cmd(self, event: AstrMessageEvent) -> None:
"""修改命令权限"""
await self.alter_cmd_c.alter_cmd(event)

View File

@@ -0,0 +1,4 @@
name: builtin_commands
desc: AstrBot's internal plugin, providing all built-in commands such as /reset.
author: Soulter
version: 0.0.1

View File

@@ -1,26 +1,27 @@
import astrbot.api.message_components as Comp
import copy
from sys import maxsize
import astrbot.api.message_components as Comp
from astrbot.api import logger
from astrbot.api.event import AstrMessageEvent, filter
from astrbot.api.star import Context, Star
from astrbot.core.utils.session_waiter import (
SessionWaiter,
USER_SESSIONS,
FILTERS,
session_waiter,
USER_SESSIONS,
SessionController,
SessionWaiter,
session_waiter,
)
from sys import maxsize
class Waiter(Star):
class Main(Star):
"""会话控制"""
def __init__(self, context: Context):
def __init__(self, context: Context) -> None:
super().__init__(context)
@filter.event_message_type(filter.EventMessageType.ALL, priority=maxsize)
async def handle_session_control_agent(self, event: AstrMessageEvent):
async def handle_session_control_agent(self, event: AstrMessageEvent) -> None:
"""会话控制代理"""
for session_filter in FILTERS:
session_id = session_filter.filter(event)
@@ -48,17 +49,18 @@ class Waiter(Star):
if p_settings.get("empty_mention_waiting_need_reply", True):
try:
# 尝试使用 LLM 生成更生动的回复
func_tools_mgr = self.context.get_llm_tool_manager()
# func_tools_mgr = self.context.get_llm_tool_manager()
# 获取用户当前的对话信息
curr_cid = await self.context.conversation_manager.get_curr_conversation_id(
event.unified_msg_origin
event.unified_msg_origin,
)
conversation = None
if curr_cid:
conversation = await self.context.conversation_manager.get_conversation(
event.unified_msg_origin, curr_cid
event.unified_msg_origin,
curr_cid,
)
else:
# 创建新对话
@@ -70,27 +72,30 @@ class Waiter(Star):
# 使用 LLM 生成回复
yield event.request_llm(
prompt=(
"注意你正在社交媒体上中与用户进行聊天用户只是通过@来唤醒你但并未在这条消息中输入内容他可能会在接下来一条发送他想发送的内容"
"你友好地询问用户想要聊些什么或者需要什么帮助回复要符合人设不要太过机械化"
"请注意你仅需要输出要回复用户的内容不要输出其他任何东西"
"注意,你正在社交媒体上中与用户进行聊天,用户只是通过@来唤醒你,但并未在这条消息中输入内容,他可能会在接下来一条发送他想发送的内容"
"你友好地询问用户想要聊些什么或者需要什么帮助,回复要符合人设,不要太过机械化"
"请注意,你仅需要输出要回复用户的内容,不要输出其他任何东西"
),
func_tool_manager=func_tools_mgr,
session_id=curr_cid,
contexts=[],
system_prompt="",
conversation=conversation,
)
except Exception as e:
logger.error(f"LLM response failed: {str(e)}")
# LLM 回复失败使用原始预设回复
yield event.plain_result("想要问什么呢😄")
logger.error(f"LLM response failed: {e!s}")
# LLM 回复失败,使用原始预设回复
yield event.plain_result("想要问什么呢?😄")
@session_waiter(60)
async def empty_mention_waiter(
controller: SessionController, event: AstrMessageEvent
):
controller: SessionController,
event: AstrMessageEvent,
) -> None:
if not event.message_str or not event.message_str.strip():
return
event.message_obj.message.insert(
0, Comp.At(qq=event.get_self_id(), name=event.get_self_id())
0,
Comp.At(qq=event.get_self_id(), name=event.get_self_id()),
)
new_event = copy.copy(event)
# 重新推入事件队列
@@ -103,7 +108,7 @@ class Waiter(Star):
except TimeoutError as _:
pass
except Exception as e:
yield event.plain_result("发生错误请联系管理员: " + str(e))
yield event.plain_result("发生错误,请联系管理员: " + str(e))
finally:
event.stop_event()
except Exception as e:

View File

@@ -0,0 +1,146 @@
import random
import urllib.parse
from collections.abc import Callable
from dataclasses import dataclass
from aiohttp import ClientSession, ClientTimeout
from bs4 import BeautifulSoup, Tag
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; rv:84.0) Gecko/20100101 Firefox/84.0",
"Accept": "*/*",
"Connection": "keep-alive",
"Accept-Language": "en-GB,en;q=0.5",
}
USER_AGENT_BING = "Mozilla/5.0 (Windows NT 6.1; rv:84.0) Gecko/20100101 Firefox/84.0"
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Version/14.1.2 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Version/14.1 Safari/537.36",
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0",
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0",
]
@dataclass
class SearchResult:
title: str
url: str
snippet: str
favicon: str | None = None
def __str__(self) -> str:
return f"{self.title} - {self.url}\n{self.snippet}"
class SearchEngine:
"""搜索引擎爬虫基类"""
def __init__(self) -> None:
self.TIMEOUT = ClientTimeout(total=10)
self.page = 1
self.headers = HEADERS
def _set_selector(self, selector: str) -> str:
raise NotImplementedError
async def _get_next_page(self, query: str) -> str:
raise NotImplementedError
async def _get_html(self, url: str, data: dict | None = None) -> str:
headers = self.headers
headers["Referer"] = url
headers["User-Agent"] = random.choice(USER_AGENTS)
if data:
async with (
ClientSession() as session,
session.post(
url,
headers=headers,
data=data,
timeout=self.TIMEOUT,
) as resp,
):
ret = await resp.text(encoding="utf-8")
return ret
else:
async with (
ClientSession() as session,
session.get(
url,
headers=headers,
timeout=self.TIMEOUT,
) as resp,
):
ret = await resp.text(encoding="utf-8")
return ret
def tidy_text(self, text: str) -> str:
"""清理文本,去除空格、换行符等"""
return text.strip().replace("\n", " ").replace("\r", " ").replace(" ", " ")
def _get_url(self, tag: Tag) -> str:
return self.tidy_text(tag.get_text())
async def search(self, query: str, num_results: int) -> list[SearchResult]:
query = urllib.parse.quote(query)
try:
resp = await self._get_next_page(query)
soup = BeautifulSoup(resp, "html.parser")
links = soup.select(self._set_selector("links"))
results = []
try:
text_selector = self._set_selector("text")
except (KeyError, NotImplementedError):
# Keep backward compatibility with engines that only expose
# title/url/link selectors and do not provide snippets.
text_selector = ""
for link in links:
# Safely get the title text (select_one may return None)
title_elem = link.select_one(self._set_selector("title"))
title = ""
if title_elem is not None:
title = self.tidy_text(title_elem.get_text())
url_tag = link.select_one(self._set_selector("url"))
snippet = ""
if text_selector:
text_elem = link.select_one(text_selector)
if text_elem is not None:
snippet = self.tidy_text(text_elem.get_text())
if title and url_tag:
url = self._get_url(url_tag)
if not url:
continue
if url.startswith("//"):
url = f"https:{url}"
results.append(SearchResult(title=title, url=url, snippet=snippet))
return results[:num_results] if len(results) > num_results else results
except Exception as e:
raise e
async def _search_with_result_filter(
self,
query: str,
num_results: int,
predicate: Callable[[SearchResult], bool],
) -> list[SearchResult]:
if num_results <= 0:
return []
rough_results = await SearchEngine.search(self, query, max(num_results * 2, 10))
final_results: list[SearchResult] = []
for result in rough_results:
if not predicate(result):
continue
final_results.append(result)
if len(final_results) >= num_results:
break
return final_results

View File

@@ -1,12 +1,13 @@
from typing import List
from . import SearchEngine, SearchResult
from . import USER_AGENT_BING
from . import USER_AGENT_BING, SearchEngine
class Bing(SearchEngine):
NAME = "bing"
def __init__(self) -> None:
super().__init__()
self.base_urls = ["https://cn.bing.com", "https://www.bing.com"]
# Prefer international Bing first, keep cn endpoint as compatibility fallback.
self.base_urls = ["https://www.bing.com", "https://cn.bing.com"]
self.headers.update({"User-Agent": USER_AGENT_BING})
def _set_selector(self, selector: str):
@@ -30,11 +31,3 @@ class Bing(SearchEngine):
self.base_url = base_url
continue
raise Exception("Bing search failed")
async def search(self, query: str, num_results: int) -> List[SearchResult]:
results = await super().search(query, num_results)
for result in results:
if not isinstance(result.url, str):
result.url = result.url.text
return results

View File

@@ -0,0 +1,64 @@
from urllib.parse import unquote, urlencode, urlparse
from bs4 import Tag
from . import SearchEngine, SearchResult
class Comet(SearchEngine):
"""Best-effort search via public Perplexity/Comet page.
Note:
- This endpoint is often protected by anti-bot challenges.
- We intentionally treat failures as non-fatal and rely on fallback engines.
"""
NAME = "comet"
def __init__(self) -> None:
super().__init__()
self.base_url = "https://www.perplexity.ai"
def _set_selector(self, selector: str):
selectors = {
"url": "a[href^='http'], a[href^='//']",
"title": "main h1, main h2, main h3, h3, h2",
"text": "main article, main div[role='article'], main section, main p, p",
"links": "main article, main div[role='article'], main li, main div.result, article, div[role='article'], li, div.result",
"next": "",
}
return selectors[selector]
async def _get_next_page(self, query: str) -> str:
url = f"{self.base_url}/search?{urlencode({'q': unquote(query)})}"
return await self._get_html(url, None)
def _get_url(self, tag: Tag) -> str:
href = str(tag.get("href") or "")
if href.startswith("//"):
return f"https:{href}"
return href
@staticmethod
def _is_valid_result_url(url: str) -> bool:
lowered = (url or "").strip().lower()
if not lowered:
return False
if lowered.startswith(("#", "javascript:", "mailto:")):
return False
if not lowered.startswith(("http://", "https://")):
return False
netloc = urlparse(lowered).netloc
if not netloc:
return False
if netloc.endswith("perplexity.ai"):
return False
return True
async def search(self, query: str, num_results: int) -> list[SearchResult]:
return await self._search_with_result_filter(
query=query,
num_results=num_results,
predicate=lambda result: self._is_valid_result_url(result.url),
)

View File

@@ -0,0 +1,43 @@
import urllib.parse
from bs4 import Tag
from . import SearchEngine, SearchResult
class DuckDuckGo(SearchEngine):
NAME = "duckduckgo"
def __init__(self) -> None:
super().__init__()
self.base_url = "https://html.duckduckgo.com/html"
def _set_selector(self, selector: str):
selectors = {
"url": "a.result__a, h2 a",
"title": "a.result__a, h2",
"text": "a.result__snippet, div.result__snippet",
"links": "div.result, div.web-result",
"next": "a.result--more__btn",
}
return selectors[selector]
async def _get_next_page(self, query: str) -> str:
params = {"q": urllib.parse.unquote(query), "kl": "us-en"}
url = f"{self.base_url}/?{urllib.parse.urlencode(params)}"
return await self._get_html(url, None)
def _get_url(self, tag: Tag) -> str:
href = str(tag.get("href") or "")
if "duckduckgo.com/l/?" in href:
parsed = urllib.parse.urlparse(href)
target = urllib.parse.parse_qs(parsed.query).get("uddg", [""])[0]
return urllib.parse.unquote(target)
return href
async def search(self, query: str, num_results: int) -> list[SearchResult]:
return await self._search_with_result_filter(
query=query,
num_results=num_results,
predicate=lambda result: result.url.startswith("http"),
)

View File

@@ -0,0 +1,51 @@
import urllib.parse
from bs4 import Tag
from . import SearchEngine, SearchResult
class Google(SearchEngine):
NAME = "google"
def __init__(self) -> None:
super().__init__()
self.base_url = "https://www.google.com"
def _set_selector(self, selector: str):
selectors = {
"url": "a[href]",
"title": "h3",
"text": "div.VwiC3b, span.aCOpRe",
"links": "div#search div.g, div#search div.MjjYud",
"next": "a#pnnext",
}
return selectors[selector]
async def _get_next_page(self, query: str) -> str:
params = {
"q": urllib.parse.unquote(query),
"hl": "en",
"gl": "us",
"pws": "0",
"num": "10",
}
url = f"{self.base_url}/search?{urllib.parse.urlencode(params)}"
return await self._get_html(url, None)
def _get_url(self, tag: Tag) -> str:
href = str(tag.get("href") or "")
if href.startswith("/url?"):
parsed = urllib.parse.urlparse(href)
q = urllib.parse.parse_qs(parsed.query).get("q", [""])[0]
return urllib.parse.unquote(q)
return href
async def search(self, query: str, num_results: int) -> list[SearchResult]:
return await self._search_with_result_filter(
query=query,
num_results=num_results,
predicate=lambda result: (
result.url.startswith("http") and "google.com/search?" not in result.url
),
)

View File

@@ -1,13 +1,14 @@
import random
import re
from bs4 import BeautifulSoup
from . import SearchEngine, SearchResult
from . import USER_AGENTS
from typing import List
from bs4 import BeautifulSoup, Tag
from . import USER_AGENTS, SearchEngine, SearchResult
class Sogo(SearchEngine):
NAME = "sogo"
def __init__(self) -> None:
super().__init__()
self.base_url = "https://www.sogou.com"
@@ -27,10 +28,12 @@ class Sogo(SearchEngine):
url = f"{self.base_url}/web?query={query}"
return await self._get_html(url, None)
async def search(self, query: str, num_results: int) -> List[SearchResult]:
def _get_url(self, tag: Tag) -> str:
return str(tag.get("href") or "")
async def search(self, query: str, num_results: int) -> list[SearchResult]:
results = await super().search(query, num_results)
for result in results:
result.url = result.url.get("href")
if result.url.startswith("/link?"):
result.url = self.base_url + result.url
result.url = await self._parse_url(result.url)
@@ -41,7 +44,10 @@ class Sogo(SearchEngine):
soup = BeautifulSoup(html, "html.parser")
script = soup.find("script")
if script:
url = re.search(r'window.location.replace\("(.+?)"\)', script.string).group(
1
script_text = (
script.string if script.string is not None else script.get_text()
)
match = re.search('window.location.replace\\("(.+?)"\\)', script_text)
if match:
url = match.group(1)
return url

View File

@@ -0,0 +1,663 @@
import asyncio
import json
import random
import uuid
from typing import ClassVar
import aiohttp
from bs4 import BeautifulSoup
from readability import Document
from astrbot.api import AstrBotConfig, llm_tool, logger, sp, star
from astrbot.api.event import AstrMessageEvent, filter
from astrbot.api.provider import ProviderRequest
from astrbot.core.provider.func_tool_manager import FunctionToolManager
from .engines import HEADERS, USER_AGENTS, SearchResult
from .engines.bing import Bing
from .engines.comet import Comet
from .engines.duckduckgo import DuckDuckGo
from .engines.google import Google
from .engines.sogo import Sogo
from .provider_routing import (
DEFAULT_WEB_SEARCH_PROVIDER,
build_default_engine_order,
normalize_websearch_provider,
normalize_websearch_provider_for_tools,
validate_default_engine_registry,
)
class Main(star.Star):
TOOLS: ClassVar[list[str]] = [
"web_search",
"fetch_url",
"web_search_tavily",
"tavily_extract_web_page",
"web_search_bocha",
]
def __init__(self, context: star.Context) -> None:
self.context = context
self.tavily_key_index = 0
self.tavily_key_lock = asyncio.Lock()
self.bocha_key_index = 0
self.bocha_key_lock = asyncio.Lock()
# 将 str 类型的 key 迁移至 list[str],并保存
cfg = self.context.get_config()
provider_settings = cfg.get("provider_settings")
if provider_settings:
tavily_key = provider_settings.get("websearch_tavily_key")
if isinstance(tavily_key, str):
logger.info(
"检测到旧版 websearch_tavily_key (字符串格式),自动迁移为列表格式并保存。",
)
if tavily_key:
provider_settings["websearch_tavily_key"] = [tavily_key]
else:
provider_settings["websearch_tavily_key"] = []
cfg.save_config()
bocha_key = provider_settings.get("websearch_bocha_key")
if isinstance(bocha_key, str):
if bocha_key:
provider_settings["websearch_bocha_key"] = [bocha_key]
else:
provider_settings["websearch_bocha_key"] = []
cfg.save_config()
self.google_search = Google()
self.bing_search = Bing()
self.ddg_search = DuckDuckGo()
self.comet_search = Comet()
self.sogo_search = Sogo()
self.default_search_engines = {
engine.NAME: engine
for engine in (
self.google_search,
self.bing_search,
self.ddg_search,
self.comet_search,
self.sogo_search,
)
}
validate_default_engine_registry(self.default_search_engines)
self.baidu_initialized = False
async def _tidy_text(self, text: str) -> str:
"""清理文本,去除空格、换行符等"""
return text.strip().replace("\n", " ").replace("\r", " ").replace(" ", " ")
async def _get_from_url(self, url: str) -> str:
"""获取网页内容"""
header = HEADERS
header.update({"User-Agent": random.choice(USER_AGENTS)})
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.get(url, headers=header) as response:
html = await response.text(encoding="utf-8")
doc = Document(html)
ret = doc.summary(html_partial=True)
soup = BeautifulSoup(ret, "html.parser")
ret = await self._tidy_text(soup.get_text())
return ret
async def _process_search_result(
self,
result: SearchResult,
idx: int,
websearch_link: bool,
) -> str:
"""处理单个搜索结果"""
logger.info(f"web_searcher - scraping web: {result.title} - {result.url}")
try:
site_result = await self._get_from_url(result.url)
except BaseException:
site_result = ""
site_result = (
f"{site_result[:700]}..." if len(site_result) > 700 else site_result
)
header = f"{idx}. {result.title} "
if websearch_link and result.url:
header += result.url
return f"{header}\n{result.snippet}\n{site_result}\n\n"
async def _web_search_default(
self,
query,
num_results: int = 5,
preferred_provider: str = DEFAULT_WEB_SEARCH_PROVIDER,
) -> list[SearchResult]:
for engine_name in build_default_engine_order(preferred_provider):
engine = self.default_search_engines.get(engine_name)
if not engine:
continue
try:
results = await engine.search(query, num_results)
except Exception as e:
logger.error(
f"{engine_name} search error: {e}, try the next one...",
)
continue
if results:
logger.info(
f"web_searcher - provider `{engine_name}` success: {len(results)} results",
)
return results
logger.debug(f"search {engine_name} returned no results")
return []
async def _get_tavily_key(self, cfg: AstrBotConfig) -> str:
"""并发安全的从列表中获取并轮换Tavily API密钥。"""
tavily_keys = cfg.get("provider_settings", {}).get("websearch_tavily_key", [])
if not tavily_keys:
raise ValueError("错误:Tavily API密钥未在AstrBot中配置。")
async with self.tavily_key_lock:
key = tavily_keys[self.tavily_key_index]
self.tavily_key_index = (self.tavily_key_index + 1) % len(tavily_keys)
return key
async def _web_search_tavily(
self,
cfg: AstrBotConfig,
payload: dict,
) -> list[SearchResult]:
"""使用 Tavily 搜索引擎进行搜索"""
tavily_key = await self._get_tavily_key(cfg)
url = "https://api.tavily.com/search"
header = {
"Authorization": f"Bearer {tavily_key}",
"Content-Type": "application/json",
}
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.post(
url,
json=payload,
headers=header,
) as response:
if response.status != 200:
reason = await response.text()
raise Exception(
f"Tavily web search failed: {reason}, status: {response.status}",
)
data = await response.json()
results = []
for item in data.get("results", []):
result = SearchResult(
title=item.get("title"),
url=item.get("url"),
snippet=item.get("content"),
favicon=item.get("favicon"),
)
results.append(result)
return results
async def _extract_tavily(self, cfg: AstrBotConfig, payload: dict) -> list[dict]:
"""使用 Tavily 提取网页内容"""
tavily_key = await self._get_tavily_key(cfg)
url = "https://api.tavily.com/extract"
header = {
"Authorization": f"Bearer {tavily_key}",
"Content-Type": "application/json",
}
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.post(
url,
json=payload,
headers=header,
) as response:
if response.status != 200:
reason = await response.text()
raise Exception(
f"Tavily web search failed: {reason}, status: {response.status}",
)
data = await response.json()
results: list[dict] = data.get("results", [])
if not results:
raise ValueError(
"Error: Tavily web searcher does not return any results.",
)
return results
@llm_tool(name="web_search")
async def search_from_search_engine(
self,
event: AstrMessageEvent,
query: str,
max_results: int = 5,
) -> str:
"""搜索网络以回答用户的问题。当用户需要搜索网络以获取即时性的信息时调用此工具。
Args:
query(string): 和用户的问题最相关的搜索关键词,用于在 Google 上搜索。
max_results(number): 返回的最大搜索结果数量,默认为 5。
"""
logger.info(f"web_searcher - search_from_search_engine: {query}")
cfg = self.context.get_config(umo=event.unified_msg_origin)
websearch_link = cfg["provider_settings"].get("web_search_link", False)
preferred_provider = normalize_websearch_provider(
cfg.get("provider_settings", {}).get(
"websearch_provider",
DEFAULT_WEB_SEARCH_PROVIDER,
),
)
results = await self._web_search_default(
query,
max_results,
preferred_provider=preferred_provider,
)
if not results:
return "Error: web searcher does not return any results."
tasks = []
for idx, result in enumerate(results, 1):
task = self._process_search_result(result, idx, websearch_link)
tasks.append(task)
processed_results = await asyncio.gather(*tasks, return_exceptions=True)
ret = ""
for processed_result in processed_results:
if isinstance(processed_result, BaseException):
logger.error(f"Error processing search result: {processed_result}")
continue
ret += processed_result
if websearch_link:
ret += "\n\n针对问题,请根据上面的结果分点总结,并且在结尾处附上对应内容的参考链接(如有)。"
return ret
async def ensure_baidu_ai_search_mcp(self, umo: str | None = None) -> None:
if self.baidu_initialized:
return
cfg = self.context.get_config(umo=umo)
key = cfg.get("provider_settings", {}).get(
"websearch_baidu_app_builder_key",
"",
)
if not key:
raise ValueError(
"Error: Baidu AI Search API key is not configured in AstrBot.",
)
func_tool_mgr = self.context.get_llm_tool_manager()
await func_tool_mgr.enable_mcp_server(
"baidu_ai_search",
config={
"transport": "sse",
"url": f"http://appbuilder.baidu.com/v2/ai_search/mcp/sse?api_key={key}",
"headers": {},
"timeout": 600,
},
)
self.baidu_initialized = True
logger.info("Successfully initialized Baidu AI Search MCP server.")
@llm_tool(name="fetch_url")
async def fetch_website_content(self, event: AstrMessageEvent, url: str) -> str:
"""Fetch the content of a website with the given web url
Args:
url(string): The url of the website to fetch content from
"""
resp = await self._get_from_url(url)
return resp
@llm_tool("web_search_tavily")
async def search_from_tavily(
self,
event: AstrMessageEvent,
query: str,
max_results: int = 7,
search_depth: str = "basic",
topic: str = "general",
days: int = 3,
time_range: str = "",
start_date: str = "",
end_date: str = "",
) -> str:
"""A web search tool that uses Tavily to search the web for relevant content.
Ideal for gathering current information, news, and detailed web content analysis.
Args:
query(string): Required. Search query.
max_results(number): Optional. The maximum number of results to return. Default is 7. Range is 5-20.
search_depth(string): Optional. The depth of the search, must be one of 'basic', 'advanced'. Default is "basic".
topic(string): Optional. The topic of the search, must be one of 'general', 'news'. Default is "general".
days(number): Optional. The number of days back from the current date to include in the search results. Please note that this feature is only available when using the 'news' search topic.
time_range(string): Optional. The time range back from the current date to include in the search results. This feature is available for both 'general' and 'news' search topics. Must be one of 'day', 'week', 'month', 'year'.
start_date(string): Optional. The start date for the search results in the format 'YYYY-MM-DD'.
end_date(string): Optional. The end date for the search results in the format 'YYYY-MM-DD'.
"""
logger.info(f"web_searcher - search_from_tavily: {query}")
cfg = self.context.get_config(umo=event.unified_msg_origin)
# websearch_link = cfg["provider_settings"].get("web_search_link", False)
if not cfg.get("provider_settings", {}).get("websearch_tavily_key", []):
raise ValueError("Error: Tavily API key is not configured in AstrBot.")
# build payload
payload = {"query": query, "max_results": max_results, "include_favicon": True}
if search_depth not in ["basic", "advanced"]:
search_depth = "basic"
payload["search_depth"] = search_depth
if topic not in ["general", "news"]:
topic = "general"
payload["topic"] = topic
if topic == "news":
payload["days"] = days
if time_range in ["day", "week", "month", "year"]:
payload["time_range"] = time_range
if start_date:
payload["start_date"] = start_date
if end_date:
payload["end_date"] = end_date
results = await self._web_search_tavily(cfg, payload)
if not results:
return "Error: Tavily web searcher does not return any results."
ret_ls = []
ref_uuid = str(uuid.uuid4())[:4]
for idx, result in enumerate(results, 1):
index = f"{ref_uuid}.{idx}"
ret_ls.append(
{
"title": f"{result.title}",
"url": f"{result.url}",
"snippet": f"{result.snippet}",
# TODO: do not need ref for non-webchat platform adapter
"index": index,
},
)
if result.favicon:
sp.temporary_cache["_ws_favicon"][result.url] = result.favicon
# ret = "\n".join(ret_ls)
ret = json.dumps({"results": ret_ls}, ensure_ascii=False)
return ret
@llm_tool("tavily_extract_web_page")
async def tavily_extract_web_page(
self,
event: AstrMessageEvent,
url: str = "",
extract_depth: str = "basic",
) -> str:
"""Extract the content of a web page using Tavily.
Args:
url(string): Required. An URl to extract content from.
extract_depth(string): Optional. The depth of the extraction, must be one of 'basic', 'advanced'. Default is "basic".
"""
cfg = self.context.get_config(umo=event.unified_msg_origin)
if not cfg.get("provider_settings", {}).get("websearch_tavily_key", []):
raise ValueError("Error: Tavily API key is not configured in AstrBot.")
if not url:
raise ValueError("Error: url must be a non-empty string.")
if extract_depth not in ["basic", "advanced"]:
extract_depth = "basic"
payload = {
"urls": [url],
"extract_depth": extract_depth,
}
results = await self._extract_tavily(cfg, payload)
ret_ls = []
for result in results:
ret_ls.append(f"URL: {result.get('url', 'No URL')}")
ret_ls.append(f"Content: {result.get('raw_content', 'No content')}")
ret = "\n".join(ret_ls)
if not ret:
return "Error: Tavily web searcher does not return any results."
return ret
async def _get_bocha_key(self, cfg: AstrBotConfig) -> str:
"""并发安全的从列表中获取并轮换BoCha API密钥。"""
bocha_keys = cfg.get("provider_settings", {}).get("websearch_bocha_key", [])
if not bocha_keys:
raise ValueError("错误:BoCha API密钥未在AstrBot中配置。")
async with self.bocha_key_lock:
key = bocha_keys[self.bocha_key_index]
self.bocha_key_index = (self.bocha_key_index + 1) % len(bocha_keys)
return key
async def _web_search_bocha(
self,
cfg: AstrBotConfig,
payload: dict,
) -> list[SearchResult]:
"""使用 BoCha 搜索引擎进行搜索"""
bocha_key = await self._get_bocha_key(cfg)
url = "https://api.bochaai.com/v1/web-search"
header = {
"Authorization": f"Bearer {bocha_key}",
"Content-Type": "application/json",
}
async with aiohttp.ClientSession(trust_env=True) as session:
async with session.post(
url,
json=payload,
headers=header,
) as response:
if response.status != 200:
reason = await response.text()
raise Exception(
f"BoCha web search failed: {reason}, status: {response.status}",
)
data = await response.json()
data = data["data"]["webPages"]["value"]
results = []
for item in data:
result = SearchResult(
title=item.get("name"),
url=item.get("url"),
snippet=item.get("snippet"),
favicon=item.get("siteIcon"),
)
results.append(result)
return results
@llm_tool("web_search_bocha")
async def search_from_bocha(
self,
event: AstrMessageEvent,
query: str,
freshness: str = "noLimit",
summary: bool = False,
include: str = "",
exclude: str = "",
count: int = 10,
) -> str:
"""A web search tool based on Bocha Search API, used to retrieve web pages
related to the user's query.
Args:
query (string): Required. User's search query.
freshness (string): Optional. Specifies the time range of the search.
Supported values:
- "noLimit": No time limit (default, recommended).
- "oneDay": Within one day.
- "oneWeek": Within one week.
- "oneMonth": Within one month.
- "oneYear": Within one year.
- "YYYY-MM-DD..YYYY-MM-DD": Search within a specific date range.
Example: "2025-01-01..2025-04-06".
- "YYYY-MM-DD": Search on a specific date.
Example: "2025-04-06".
It is recommended to use "noLimit", as the search algorithm will
automatically optimize time relevance. Manually restricting the
time range may result in no search results.
summary (boolean): Optional. Whether to include a text summary
for each search result.
- True: Include summary.
- False: Do not include summary (default).
include (string): Optional. Specifies the domains to include in
the search. Multiple domains can be separated by "|" or ",".
A maximum of 100 domains is allowed.
Examples:
- "qq.com"
- "qq.com|m.163.com"
exclude (string): Optional. Specifies the domains to exclude from
the search. Multiple domains can be separated by "|" or ",".
A maximum of 100 domains is allowed.
Examples:
- "qq.com"
- "qq.com|m.163.com"
count (number): Optional. Number of search results to return.
- Range: 150
- Default: 10
The actual number of returned results may be less than the
specified count.
"""
logger.info(f"web_searcher - search_from_bocha: {query}")
cfg = self.context.get_config(umo=event.unified_msg_origin)
# websearch_link = cfg["provider_settings"].get("web_search_link", False)
if not cfg.get("provider_settings", {}).get("websearch_bocha_key", []):
raise ValueError("Error: BoCha API key is not configured in AstrBot.")
# build payload
payload = {
"query": query,
"count": count,
}
# freshness:时间范围
if freshness:
payload["freshness"] = freshness
# 是否返回摘要
payload["summary"] = summary
# include:限制搜索域
if include:
payload["include"] = include
# exclude:排除搜索域
if exclude:
payload["exclude"] = exclude
results = await self._web_search_bocha(cfg, payload)
if not results:
return "Error: BoCha web searcher does not return any results."
ret_ls = []
ref_uuid = str(uuid.uuid4())[:4]
for idx, result in enumerate(results, 1):
index = f"{ref_uuid}.{idx}"
ret_ls.append(
{
"title": f"{result.title}",
"url": f"{result.url}",
"snippet": f"{result.snippet}",
"index": index,
},
)
if result.favicon:
sp.temporary_cache["_ws_favicon"][result.url] = result.favicon
# ret = "\n".join(ret_ls)
ret = json.dumps({"results": ret_ls}, ensure_ascii=False)
return ret
@filter.on_llm_request(priority=-10000)
async def edit_web_search_tools(
self,
event: AstrMessageEvent,
req: ProviderRequest,
) -> None:
"""Get the session conversation for the given event."""
cfg = self.context.get_config(umo=event.unified_msg_origin)
prov_settings = cfg.get("provider_settings", {})
websearch_enable = prov_settings.get("web_search", False)
raw_provider = prov_settings.get(
"websearch_provider",
DEFAULT_WEB_SEARCH_PROVIDER,
)
branch_provider, is_known_provider = normalize_websearch_provider_for_tools(
raw_provider,
)
tool_set = req.func_tool
if isinstance(tool_set, FunctionToolManager):
req.func_tool = tool_set.get_full_tool_set()
tool_set = req.func_tool
if not tool_set:
return
if not websearch_enable:
# pop tools
for tool_name in self.TOOLS:
tool_set.remove_tool(tool_name)
return
func_tool_mgr = self.context.get_llm_tool_manager()
if branch_provider == "default":
if not is_known_provider:
logger.warning(
"Unsupported websearch_provider `%s`, fallback to default search tool branch.",
raw_provider,
)
web_search_t = func_tool_mgr.get_func("web_search")
fetch_url_t = func_tool_mgr.get_func("fetch_url")
if web_search_t and web_search_t.active:
tool_set.add_tool(web_search_t)
if fetch_url_t and fetch_url_t.active:
tool_set.add_tool(fetch_url_t)
tool_set.remove_tool("web_search_tavily")
tool_set.remove_tool("tavily_extract_web_page")
tool_set.remove_tool("AIsearch")
tool_set.remove_tool("web_search_bocha")
elif branch_provider == "tavily":
web_search_tavily = func_tool_mgr.get_func("web_search_tavily")
tavily_extract_web_page = func_tool_mgr.get_func("tavily_extract_web_page")
if web_search_tavily and web_search_tavily.active:
tool_set.add_tool(web_search_tavily)
if tavily_extract_web_page and tavily_extract_web_page.active:
tool_set.add_tool(tavily_extract_web_page)
tool_set.remove_tool("web_search")
tool_set.remove_tool("fetch_url")
tool_set.remove_tool("AIsearch")
tool_set.remove_tool("web_search_bocha")
elif branch_provider == "baidu_ai_search":
try:
await self.ensure_baidu_ai_search_mcp(event.unified_msg_origin)
aisearch_tool = func_tool_mgr.get_func("AIsearch")
if aisearch_tool and aisearch_tool.active:
tool_set.add_tool(aisearch_tool)
tool_set.remove_tool("web_search")
tool_set.remove_tool("fetch_url")
tool_set.remove_tool("web_search_tavily")
tool_set.remove_tool("tavily_extract_web_page")
tool_set.remove_tool("web_search_bocha")
except Exception as e:
logger.error(f"Cannot Initialize Baidu AI Search MCP Server: {e}")
elif branch_provider == "bocha":
web_search_bocha = func_tool_mgr.get_func("web_search_bocha")
if web_search_bocha and web_search_bocha.active:
tool_set.add_tool(web_search_bocha)
tool_set.remove_tool("web_search")
tool_set.remove_tool("fetch_url")
tool_set.remove_tool("AIsearch")
tool_set.remove_tool("web_search_tavily")
tool_set.remove_tool("tavily_extract_web_page")

View File

@@ -0,0 +1,24 @@
from __future__ import annotations
DEFAULT_WEB_SEARCH_PROVIDER = "default"
# Canonical provider ids shown in config UI options.
WEB_SEARCH_PROVIDER_OPTIONS: tuple[str, ...] = (
DEFAULT_WEB_SEARCH_PROVIDER,
"duckduckgo",
"google",
"bing",
"comet",
"sogo",
"tavily",
"baidu_ai_search",
"bocha",
)
# Provider ids that select non-default tool branches directly.
WEB_SEARCH_TOOL_BRANCH_PROVIDERS: tuple[str, ...] = (
DEFAULT_WEB_SEARCH_PROVIDER,
"tavily",
"baidu_ai_search",
"bocha",
)

View File

@@ -0,0 +1,132 @@
from __future__ import annotations
from collections.abc import Mapping
from dataclasses import dataclass
from .engines.bing import Bing
from .engines.comet import Comet
from .engines.duckduckgo import DuckDuckGo
from .engines.google import Google
from .engines.sogo import Sogo
from .provider_constants import (
DEFAULT_WEB_SEARCH_PROVIDER,
WEB_SEARCH_PROVIDER_OPTIONS,
WEB_SEARCH_TOOL_BRANCH_PROVIDERS,
)
ENGINE_REGISTRY: tuple[tuple[str, type[object], bool], ...] = (
(Bing.NAME, Bing, True),
(Sogo.NAME, Sogo, True),
# Compatibility first: DDG should stay as fallback and cannot become primary.
(DuckDuckGo.NAME, DuckDuckGo, False),
(Google.NAME, Google, True),
(Comet.NAME, Comet, True),
)
DEFAULT_ENGINE_ORDER: tuple[str, ...] = tuple(name for name, _, _ in ENGINE_REGISTRY)
_ENGINE_PROVIDER_SET = {name for name, _, _ in ENGINE_REGISTRY}
_ENGINE_CAN_BE_PRIMARY = {
name: can_be_primary for name, _, can_be_primary in ENGINE_REGISTRY
}
_TOOL_BRANCH_PROVIDER_SET = set(WEB_SEARCH_TOOL_BRANCH_PROVIDERS)
_CANONICAL_PROVIDER_SET = _ENGINE_PROVIDER_SET | _TOOL_BRANCH_PROVIDER_SET
if not _CANONICAL_PROVIDER_SET.issubset(set(WEB_SEARCH_PROVIDER_OPTIONS)):
raise RuntimeError(
"web search provider options and routing providers are out of sync: "
f"canonical={sorted(_CANONICAL_PROVIDER_SET)} options={list(WEB_SEARCH_PROVIDER_OPTIONS)}",
)
_WEB_SEARCH_PROVIDER_ALIASES: dict[str, str] = {
"": DEFAULT_WEB_SEARCH_PROVIDER,
"default": DEFAULT_WEB_SEARCH_PROVIDER,
"native": DEFAULT_WEB_SEARCH_PROVIDER,
}
_WEB_SEARCH_PROVIDER_ALIASES.update({name: name for name in _CANONICAL_PROVIDER_SET})
_WEB_SEARCH_PROVIDER_ALIASES.update(
{
"duckduck_go": DuckDuckGo.NAME,
"duckduck-go": DuckDuckGo.NAME,
"ddg": DuckDuckGo.NAME,
"baidu_ai": "baidu_ai_search",
"baidu": "baidu_ai_search",
"bochaai": "bocha",
# ZeroClaw compatibility: AstrBot has no Brave provider yet, so downgrade to default.
"brave": DEFAULT_WEB_SEARCH_PROVIDER,
},
)
@dataclass(frozen=True)
class NormalizedProvider:
canonical: str
tool_branch: str
is_known: bool
def _normalize_raw_provider(provider: object) -> str:
return str(provider or "").strip().lower().replace(" ", "")
def normalize_websearch(provider: object) -> NormalizedProvider:
raw = _normalize_raw_provider(provider)
alias = _WEB_SEARCH_PROVIDER_ALIASES.get(raw, raw)
canonical = alias or DEFAULT_WEB_SEARCH_PROVIDER
is_engine = canonical in _ENGINE_PROVIDER_SET
is_tool_branch = canonical in _TOOL_BRANCH_PROVIDER_SET
is_known = is_engine or is_tool_branch
tool_branch = canonical if is_tool_branch else DEFAULT_WEB_SEARCH_PROVIDER
return NormalizedProvider(
canonical=canonical,
tool_branch=tool_branch,
is_known=is_known,
)
def normalize_websearch_provider(provider: object) -> str:
return normalize_websearch(provider).canonical
def normalize_websearch_provider_for_tools(provider: object) -> tuple[str, bool]:
normalized = normalize_websearch(provider)
return normalized.tool_branch, normalized.is_known
def resolve_tool_branch_provider(provider: object) -> str:
return normalize_websearch(provider).tool_branch
def build_default_engine_order(provider: object) -> tuple[str, ...]:
normalized = normalize_websearch(provider)
engine_name = normalized.canonical
if engine_name not in _ENGINE_PROVIDER_SET:
return DEFAULT_ENGINE_ORDER
if not _ENGINE_CAN_BE_PRIMARY.get(engine_name, False):
return DEFAULT_ENGINE_ORDER
return (
engine_name,
*tuple(name for name in DEFAULT_ENGINE_ORDER if name != engine_name),
)
def is_known_websearch_provider(provider: object) -> bool:
return normalize_websearch(provider).is_known
def validate_default_engine_registry(engines_by_name: Mapping[str, object]) -> None:
expected_names = {name for name, _, _ in ENGINE_REGISTRY}
missing = [name for name in DEFAULT_ENGINE_ORDER if name not in engines_by_name]
extra = [name for name in engines_by_name if name not in expected_names]
if not missing and not extra:
return
raise ValueError(
"default search engine registry mismatch. "
f"missing={missing}, extra={extra}, expected_order={list(DEFAULT_ENGINE_ORDER)}",
)

View File

@@ -1 +1,3 @@
__version__ = "3.5.23"
from astrbot import __version__
__all__ = ["__version__"]

View File

@@ -1,59 +1,187 @@
"""
AstrBot CLI入口
"""
"""AstrBot CLI entry point"""
import os
import platform
import sys
from pathlib import Path
import click
import sys
from click.shell_completion import get_completion_class
from . import __version__
from .commands import init, run, plug, conf
logo_tmpl = r"""
___ _______.___________..______ .______ ______ .___________.
/ \ / | || _ \ | _ \ / __ \ | |
/ ^ \ | (----`---| |----`| |_) | | |_) | | | | | `---| |----`
/ /_\ \ \ \ | | | / | _ < | | | | | |
/ _____ \ .----) | | | | |\ \----.| |_) | | `--' | | |
/__/ \__\ |_______/ |__| | _| `._____||______/ \______/ |__|
"""
from .commands import bk, config, init, password, plugin, run, service, uninstall
from .i18n import t
@click.group()
def print_version_detail() -> None:
"""Print detailed version info (same for --version and version command)"""
from astrbot.core.utils.astrbot_path import astrbot_paths
click.echo(f"AstrBot: {__version__}")
click.echo(f"Python: {sys.version.split()[0]}")
click.echo(f"System: {platform.system()} {platform.release()}")
click.echo(f"Machine: {platform.machine()}")
git_root = Path(astrbot_paths.root) / ".git"
if git_root.exists():
import subprocess
try:
git_hash = subprocess.check_output(
["git", "rev-parse", "--short", "HEAD"],
cwd=str(astrbot_paths.root),
text=True,
).strip()
git_branch = subprocess.check_output(
["git", "rev-parse", "--abbrev-ref", "HEAD"],
cwd=str(astrbot_paths.root),
text=True,
).strip()
click.echo(f"Git Branch: {git_branch}")
click.echo(f"Git Commit: {git_hash}")
except Exception:
pass
click.echo(f"AstrBot Root: {astrbot_paths.root}")
click.echo(f"Platform: {platform.platform()}")
def version_callback(ctx: click.Context, param: click.Parameter, value: bool) -> bool:
"""Callback for --version to show detailed version and exit."""
if not value:
return value
print_version_detail()
ctx.exit()
return value
class AstrBotCLIGroup(click.Group):
COMMAND_ALIASES = {
"conf": "config",
"plug": "plugin",
}
def get_command(self, ctx: click.Context, cmd_name: str) -> click.Command | None:
command = super().get_command(ctx, cmd_name)
if command is not None:
return command
alias_target = self.COMMAND_ALIASES.get(cmd_name)
if alias_target is None:
return None
return super().get_command(ctx, alias_target)
@click.group(cls=AstrBotCLIGroup)
@click.version_option(__version__, prog_name="AstrBot")
def cli() -> None:
"""The AstrBot CLI"""
click.echo(logo_tmpl)
click.echo("Welcome to AstrBot CLI!")
click.echo(f"AstrBot CLI version: {__version__}")
"""Astrbot
Agentic IM Chatbot infrastructure that integrates lots of IM platforms, LLMs, plugins and AI feature, and can be your openclaw alternative. ✨
"""
@click.command()
@click.argument("command_name", required=False, type=str)
def help(command_name: str | None) -> None:
"""显示命令的帮助信息
@click.option(
"--all",
"-a",
is_flag=True,
help="Show help for all commands recursively.",
)
def help(command_name: str | None, all: bool) -> None:
"""Display help information for commands
如果提供了 COMMAND_NAME,则显示该命令的详细帮助信息。
否则,显示通用帮助信息。
If COMMAND_NAME is provided, display detailed help for that command.
Otherwise, display general help information.
"""
ctx = click.get_current_context()
if all:
def print_recursive_help(command, parent_ctx):
name = command.name
if parent_ctx is None:
name = "astrbot"
cmd_ctx = click.Context(command, info_name=name, parent=parent_ctx)
click.echo(command.get_help(cmd_ctx))
click.echo("\n" + "-" * 50 + "\n")
if isinstance(command, click.Group):
for subcommand in command.commands.values():
print_recursive_help(subcommand, cmd_ctx)
print_recursive_help(cli, None)
return
if command_name:
# 查找指定命令
# Find the specified command
command = cli.get_command(ctx, command_name)
if command:
# 显示特定命令的帮助信息
click.echo(command.get_help(ctx))
# Display help for the specific command
parent = ctx.parent or ctx
cmd_ctx = click.Context(command, info_name=command.name, parent=parent)
click.echo(command.get_help(cmd_ctx))
else:
click.echo(f"Unknown command: {command_name}")
click.echo(t("cli_unknown_command", command=command_name))
sys.exit(1)
else:
# 显示通用帮助信息
# Display general help information
click.echo(cli.get_help(ctx))
cli.add_command(init)
cli.add_command(run)
cli.add_command(help)
cli.add_command(plug)
cli.add_command(conf)
cli.add_command(plugin)
cli.add_command(config)
cli.add_command(uninstall)
cli.add_command(bk)
cli.add_command(password)
cli.add_command(service)
@click.command()
@click.argument("shell", required=False, type=click.Choice(["bash", "zsh", "fish"]))
def completion(shell: str | None) -> None:
"""Generate shell completion script"""
if shell is None:
shell_path = os.environ.get("SHELL", "")
if "zsh" in shell_path:
shell = "zsh"
elif "bash" in shell_path:
shell = "bash"
elif "fish" in shell_path:
shell = "fish"
else:
click.echo(
"Could not detect shell. Please specify one of: bash, zsh, fish",
err=True,
)
sys.exit(1)
comp_cls = get_completion_class(shell)
if comp_cls is None:
click.echo(f"No completion support for shell: {shell}", err=True)
sys.exit(1)
comp = comp_cls(
cli,
ctx_args={},
prog_name="astrbot",
complete_var="_ASTRBOT_COMPLETE",
)
click.echo(comp.source())
cli.add_command(completion)
@click.command(name="version")
def version_cmd() -> None:
"""Display detailed version information"""
print_version_detail()
cli.add_command(version_cmd)
if __name__ == "__main__":
cli()

28
astrbot/cli/banner.py Normal file
View File

@@ -0,0 +1,28 @@
"""ASCII logo and interactive mode utilities for CLI"""
import sys
logo_tmpl = r"""
___ _______.___________..______ .______ ______ .___________.
/ \ / | || _ \ | _ \ / __ \ | |
/ ^ \ | (----`---| |----`| |_) | | |_) | | | | | `---| |----`
/ /_\ \ \ \ | | | / | _ < | | | | | |
/ _____ \ .----) | | | | |\ \----.| |_) | | `--' | | |
/__/ \__\ |_______/ |__| | _| `._____||______/ \______/ |__|
"""
def is_interactive() -> bool:
"""Check if stdout is connected to a TTY (interactive terminal)"""
try:
return sys.stdout.isatty()
except Exception:
return False
def print_logo() -> None:
"""Print ASCII logo if in interactive mode"""
import click
if is_interactive():
click.echo(logo_tmpl)

View File

@@ -1,6 +1,24 @@
from .cmd_bk import bk
from .cmd_conf import conf as config
from .cmd_init import init
from .cmd_password import password
from .cmd_plug import plug as plugin
from .cmd_run import run
from .cmd_plug import plug
from .cmd_conf import conf
from .cmd_service import service
from .cmd_uninstall import uninstall
__all__ = ["init", "run", "plug", "conf"]
conf = config
plug = plugin
__all__ = [
"bk",
"conf",
"config",
"init",
"password",
"plug",
"plugin",
"run",
"service",
"uninstall",
]

View File

@@ -0,0 +1,392 @@
import asyncio
import hashlib
import shutil
import subprocess
from pathlib import Path
import anyio
import click
from astrbot.core import db_helper
from astrbot.core.backup import AstrBotExporter, AstrBotImporter
async def _get_kb_manager():
"""Initialize and return a KnowledgeBaseManager with full dependency chain."""
from astrbot.core import astrbot_config, sp
from astrbot.core.astrbot_config_mgr import AstrBotConfigManager
from astrbot.core.knowledge_base.kb_mgr import KnowledgeBaseManager
from astrbot.core.persona_mgr import PersonaManager
from astrbot.core.provider.manager import ProviderManager
from astrbot.core.umop_config_router import UmopConfigRouter
ucr = UmopConfigRouter(sp=sp)
await ucr.initialize()
acm = AstrBotConfigManager(
default_config=astrbot_config,
ucr=ucr,
sp=sp,
)
persona_mgr = PersonaManager(db_helper, acm)
await persona_mgr.initialize()
provider_manager = ProviderManager(
acm,
db_helper,
persona_mgr,
)
kb_manager = KnowledgeBaseManager(provider_manager)
await kb_manager.initialize()
return kb_manager
@click.group(name="bk")
def bk():
"""Backup management (Export/Import)"""
@bk.command(name="export")
@click.option("--output", "-o", help="Output directory", default=None)
@click.option(
"--gpg-sign",
"-S",
is_flag=True,
help="Sign backup with GPG default private key",
)
@click.option(
"--gpg-encrypt",
"-E",
help="Encrypt for GPG recipient (Asymmetric)",
metavar="RECIPIENT",
)
@click.option(
"--gpg-symmetric",
"-C",
is_flag=True,
help="Encrypt with symmetric cipher (GPG)",
)
@click.option(
"--digest",
"-d",
type=click.Choice(["md5", "sha1", "sha256", "sha512"]),
help="Generate digital digest",
)
def export_data(
output: str | None,
gpg_sign: bool,
gpg_encrypt: str | None,
gpg_symmetric: bool,
digest: str | None,
):
"""Export all AstrBot data to a backup archive.
If any GPG option (-S, -E, -C) is used, the output file will be processed by GPG
and saved with a .gpg extension.
Examples:
\b
1. Standard Export:
astrbot bk export
-> Generates a plain .zip file.
\b
2. Signed Backup (Integrity Check):
astrbot bk export -S
-> Generates a .zip.gpg file containing the backup and your signature.
-> NOT ENCRYPTED, but packaged in OpenPGP format.
-> Use 'astrbot bk import' or 'gpg --verify' to check integrity.
\b
3. Password Protected (Symmetric Encryption):
astrbot bk export -C
-> Generates an encrypted .zip.gpg file.
-> Prompts for a passphrase.
-> Only accessible with the passphrase.
\b
4. Encrypted for Recipient (Asymmetric Encryption):
astrbot bk export -E "alice@example.com"
-> Generates an encrypted .zip.gpg file for Alice.
-> Only Alice's private key can decrypt it.
\b
5. Signed and Encrypted with Digest:
astrbot bk export -S -E "bob@example.com" -d sha256
-> Signs, encrypts for Bob, and generates a SHA256 checksum file.
"""
# Handle case where -E consumes the next flag (e.g. -E -S)
if gpg_encrypt and gpg_encrypt.startswith("-"):
consumed_flag = gpg_encrypt
click.echo(
click.style(
f"Warning: Flag '{consumed_flag}' was interpreted as the recipient for -E.",
fg="yellow",
),
)
# Recover flags
if consumed_flag == "-S":
gpg_sign = True
click.echo("Recovered flag -S (Sign).")
elif consumed_flag == "-C":
gpg_symmetric = True
click.echo("Recovered flag -C (Symmetric).")
# Prompt for the actual recipient
gpg_encrypt = click.prompt("Please enter the GPG recipient (email or key ID)")
async def _run():
if gpg_sign or gpg_encrypt or gpg_symmetric:
if not shutil.which("gpg"):
raise click.ClickException(
"GPG tool not found. Please install GnuPG to use encryption/signing features.",
)
exporter = AstrBotExporter(db_helper)
async def on_progress(stage, current, total, message):
click.echo(f"[{stage}] {message}")
try:
path_str = await exporter.export_all(output, progress_callback=on_progress)
final_path = Path(path_str)
click.echo(
click.style(f"\nRaw backup exported to: {final_path}", fg="green"),
)
# GPG Operations
if gpg_sign or gpg_encrypt or gpg_symmetric:
# Construct GPG command
# output file usually ends with .gpg
gpg_output = final_path.with_name(final_path.name + ".gpg")
cmd = ["gpg", "--output", str(gpg_output), "--yes"]
if gpg_symmetric:
if gpg_encrypt:
click.echo(
click.style(
"Warning: Symmetric encryption selected, ignoring asymmetric recipient.",
fg="yellow",
),
)
cmd.append("--symmetric")
# No --batch to allow interactive passphrase entry on TTY
else:
# Asymmetric or just Sign
# Note: If encrypting, -s adds signature to the encrypted packet.
if gpg_encrypt:
cmd.extend(["--encrypt", "--recipient", gpg_encrypt])
if gpg_sign:
cmd.append("--sign")
cmd.append(str(final_path))
click.echo(f"Running GPG: {' '.join(cmd)}")
# Replace subprocess.run with asyncio.create_subprocess_exec to avoid blocking the event loop
process = await asyncio.create_subprocess_exec(*cmd)
await process.wait()
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode or 1, cmd)
# Clean up original file
await anyio.Path(final_path).unlink()
final_path = gpg_output
click.echo(
click.style(f"Processed backup created: {final_path}", fg="green"),
)
# Digest Generation
if digest:
click.echo(f"Calculating {digest} digest...")
hash_func = getattr(hashlib, digest)()
# Read file in chunks
async with await anyio.open_file(final_path, "rb") as f:
while chunk := await f.read(8192):
hash_func.update(chunk)
digest_val = hash_func.hexdigest()
digest_file = final_path.with_name(final_path.name + f".{digest}")
await anyio.Path(digest_file).write_text(
f"{digest_val} *{final_path.name}\n",
encoding="utf-8",
)
click.echo(click.style(f"Digest generated: {digest_file}", fg="green"))
except subprocess.CalledProcessError as e:
click.echo(click.style(f"\nGPG process failed: {e}", fg="red"), err=True)
except Exception as e:
click.echo(click.style(f"\nExport failed: {e}", fg="red"), err=True)
asyncio.run(_run())
@bk.command(name="import")
@click.argument("backup_file")
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation prompts")
def import_data_command(backup_file: str, yes: bool):
"""Import AstrBot data from a backup archive.
Automatically handles .zip files and .gpg files (signed or encrypted).
If the file is encrypted, you will be prompted for the passphrase.
If a digest file (.sha256, .md5, etc.) exists, it will be verified automatically.
"""
backup_path = Path(backup_file)
if not backup_path.exists():
raise click.ClickException(f"Backup file not found: {backup_file}")
# 1. Verify Digest if exists
def _verify_digest(file_path: Path) -> bool:
supported_digests = ["sha256", "sha512", "md5", "sha1"]
digest_verified = True # Default true if no digest file found
for algo in supported_digests:
digest_file = file_path.with_name(f"{file_path.name}.{algo}")
if digest_file.exists():
click.echo(f"Found digest file: {digest_file.name}")
try:
# Parse digest file
content = digest_file.read_text(encoding="utf-8").strip()
# Format: "digest *filename" or "digest filename"
# We expect the hash to be the first part
if " " in content:
expected_digest = content.split()[0].lower()
else:
expected_digest = content.lower()
click.echo(f"Verifying {algo} digest...")
hash_func = getattr(hashlib, algo)()
with open(file_path, "rb") as f:
while chunk := f.read(8192):
hash_func.update(chunk)
calculated_digest = hash_func.hexdigest().lower()
if calculated_digest == expected_digest:
click.echo(
click.style("Digest verification PASSED.", fg="green"),
)
else:
click.echo(
click.style(
"Digest verification FAILED!",
fg="red",
bold=True,
),
)
click.echo(f" Expected: {expected_digest}")
click.echo(f" Actual: {calculated_digest}")
digest_verified = False
except Exception as e:
click.echo(click.style(f"Error checking digest: {e}", fg="red"))
digest_verified = False
return digest_verified
if not _verify_digest(backup_path):
if not yes:
if not click.confirm(
"Digest verification failed. Abort import?",
default=True,
abort=True,
):
pass
else:
click.echo(
click.style(
"Warning: Digest verification failed. Continuing due to --yes.",
fg="yellow",
),
)
if not yes:
click.confirm(
"This will OVERWRITE all current data (DB, Config, Plugins). Continue?",
abort=True,
default=False,
)
async def _run():
zip_path = backup_path
is_temp_file = False
# Handle GPG encrypted files
if backup_path.suffix == ".gpg":
if not shutil.which("gpg"):
raise click.ClickException(
"GPG tool not found. Cannot decrypt .gpg file.",
)
# Remove .gpg extension for output
decrypted_path = backup_path.with_suffix("")
# If it doesn't look like a zip after stripping .gpg, maybe append .zip?
# But the exporter creates .zip.gpg, so stripping .gpg gives .zip.
click.echo(f"Processing GPG file {backup_path}...")
try:
cmd = [
"gpg",
"--output",
str(decrypted_path),
"--decrypt", # This handles both decryption and signature verification/extraction
str(backup_path),
]
# Allow interactive passphrase
process = await asyncio.create_subprocess_exec(*cmd)
await process.wait()
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode or 1, cmd)
zip_path = decrypted_path
is_temp_file = True
except subprocess.CalledProcessError:
click.echo(
click.style(
"GPG processing failed. Verify signature or decryption key.",
fg="red",
),
err=True,
)
return
kb_mgr = await _get_kb_manager()
importer = AstrBotImporter(db_helper, kb_mgr)
async def on_progress(stage, current, total, message):
click.echo(f"[{stage}] {message}")
try:
result = await importer.import_all(
str(zip_path),
progress_callback=on_progress,
)
if result.errors:
click.echo(
click.style("\nImport failed with errors:", fg="red"),
err=True,
)
for err in result.errors:
click.echo(f" - {err}", err=True)
else:
click.echo(click.style("\nImport completed successfully!", fg="green"))
if result.warnings:
click.echo(click.style("\nWarnings:", fg="yellow"))
for warn in result.warnings:
click.echo(f" - {warn}")
finally:
if is_temp_file and await anyio.Path(zip_path).exists():
await anyio.Path(zip_path).unlink()
click.echo(f"Cleaned up temporary file: {zip_path}")
asyncio.run(_run())

View File

@@ -1,63 +1,95 @@
"""Configuration CLI for AstrBot.
This module provides:
- secure hashing utilities for the dashboard password (argon2)
- validators for commonly configurable items
- click CLI group with `set`, `get`, and `password` subcommands
"""
from __future__ import annotations
import json
import click
import hashlib
import zoneinfo
from typing import Any, Callable
from ..utils import get_astrbot_root, check_astrbot_root
from collections.abc import Callable
from typing import Any
import click
from filelock import FileLock, Timeout
from astrbot.cli.i18n import t
from astrbot.core.config.default import DEFAULT_CONFIG
from astrbot.core.utils.astrbot_path import astrbot_paths
from astrbot.core.utils.auth_password import (
_is_argon2_hash,
_is_pbkdf2_hash,
hash_dashboard_password,
hash_legacy_dashboard_password,
is_legacy_dashboard_password,
validate_dashboard_password,
)
# --- Password hashing & validation utilities ---
def is_dashboard_password_hash(value: str) -> bool:
"""Heuristic: return True if `value` looks like a supported dashboard password hash."""
if not isinstance(value, str) or not value:
return False
return _is_argon2_hash(value) or _is_pbkdf2_hash(value)
# --- Validators for CLI configuration items ---
def _validate_log_level(value: str) -> str:
"""验证日志级别"""
value = value.upper()
if value not in ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]:
raise click.ClickException(
"日志级别必须是 DEBUG/INFO/WARNING/ERROR/CRITICAL 之一"
)
return value
value_up = value.upper()
allowed = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
if value_up not in allowed:
raise click.ClickException(t("config_log_level_invalid"))
return value_up
def _validate_dashboard_port(value: str) -> int:
"""验证 Dashboard 端口"""
try:
port = int(value)
if port < 1 or port > 65535:
raise click.ClickException("端口必须在 1-65535 范围内")
return port
except ValueError:
raise click.ClickException("端口必须是数字")
raise click.ClickException(t("config_port_must_be_number")) from None
if port < 1 or port > 65535:
raise click.ClickException(t("config_port_range_invalid"))
return port
def _validate_dashboard_username(value: str) -> str:
"""验证 Dashboard 用户名"""
if not value:
raise click.ClickException("用户名不能为空")
return value
if value is None or value.strip() == "":
raise click.ClickException(t("config_username_empty"))
return value.strip()
def _validate_dashboard_password(value: str) -> str:
"""验证 Dashboard 密码"""
if not value:
raise click.ClickException("密码不能为空")
return hashlib.md5(value.encode()).hexdigest()
if value is None or value == "":
raise click.ClickException(t("config_password_empty"))
try:
validate_dashboard_password(value)
except ValueError as e:
raise click.ClickException(str(e)) from e
# Return the plaintext value; callers hash it before storage.
return value
def _validate_timezone(value: str) -> str:
"""验证时区"""
try:
zoneinfo.ZoneInfo(value)
except Exception:
raise click.ClickException(f"无效的时区: {value}请使用有效的IANA时区名称")
except Exception as e:
raise click.ClickException(t("config_timezone_invalid", value=value)) from e
return value
def _validate_callback_api_base(value: str) -> str:
"""验证回调接口基址"""
if not value.startswith("http://") and not value.startswith("https://"):
raise click.ClickException("回调接口基址必须以 http:// 或 https:// 开头")
if not (value.startswith("http://") or value.startswith("https://")):
raise click.ClickException(t("config_callback_invalid"))
return value
# 可通过CLI设置的配置项配置键到验证器函数的映射
CONFIG_VALIDATORS: dict[str, Callable[[str], Any]] = {
"timezone": _validate_timezone,
"log_level": _validate_log_level,
@@ -68,18 +100,22 @@ CONFIG_VALIDATORS: dict[str, Callable[[str], Any]] = {
}
# --- Config file helpers ---
def _load_config() -> dict[str, Any]:
"""加载或初始化配置文件"""
root = get_astrbot_root()
if not check_astrbot_root(root):
"""Load or initialize the CLI config file (data/cmd_config.json).
Ensures the astrbot root is valid before proceeding.
"""
root = astrbot_paths.root
if not astrbot_paths.is_root:
raise click.ClickException(
f"{root}不是有效的 AstrBot 根目录,如需初始化请使用 astrbot init"
f"{root} is not a valid AstrBot root directory. Use 'astrbot init' to initialize",
)
config_path = root / "data" / "cmd_config.json"
config_path = astrbot_paths.data / "cmd_config.json"
if not config_path.exists():
from astrbot.core.config.default import DEFAULT_CONFIG
# Write DEFAULT_CONFIG to disk if file missing
config_path.write_text(
json.dumps(DEFAULT_CONFIG, ensure_ascii=False, indent=2),
encoding="utf-8-sig",
@@ -88,119 +124,246 @@ def _load_config() -> dict[str, Any]:
try:
return json.loads(config_path.read_text(encoding="utf-8-sig"))
except json.JSONDecodeError as e:
raise click.ClickException(f"配置文件解析失败: {str(e)}")
raise click.ClickException(f"Failed to parse config file: {e!s}") from e
def _save_config(config: dict[str, Any]) -> None:
"""保存配置文件"""
config_path = get_astrbot_root() / "data" / "cmd_config.json"
config_path = astrbot_paths.data / "cmd_config.json"
config_path.write_text(
json.dumps(config, ensure_ascii=False, indent=2), encoding="utf-8-sig"
json.dumps(config, ensure_ascii=False, indent=2),
encoding="utf-8-sig",
)
def ensure_config_file() -> dict[str, Any]:
return _load_config()
def _set_nested_item(obj: dict[str, Any], path: str, value: Any) -> None:
"""设置嵌套字典中的值"""
parts = path.split(".")
cur = obj
for part in parts[:-1]:
if part not in obj:
obj[part] = {}
elif not isinstance(obj[part], dict):
if part not in cur:
cur[part] = {}
elif not isinstance(cur[part], dict):
raise click.ClickException(
f"配置路径冲突: {'.'.join(parts[: parts.index(part) + 1])} 不是字典"
f"Config path conflict: {'.'.join(parts[: parts.index(part) + 1])} is not a dict",
)
obj = obj[part]
obj[parts[-1]] = value
cur = cur[part]
cur[parts[-1]] = value
def _get_nested_item(obj: dict[str, Any], path: str) -> Any:
"""获取嵌套字典中的值"""
parts = path.split(".")
cur = obj
for part in parts:
obj = obj[part]
return obj
cur = cur[part]
return cur
@click.group(name="conf")
def conf():
"""配置管理命令
# --- CLI commands ---
支持的配置项:
- timezone: 时区设置 (例如: Asia/Shanghai)
def prompt_dashboard_password(prompt: str = "Dashboard password") -> str:
# 显示密码规则提示
click.echo()
click.echo("密码规则:")
click.echo(" - 至少 12 个字符")
click.echo(" - 必须包含至少一个大写字母")
click.echo(" - 必须包含至少一个小写字母")
click.echo(" - 必须包含至少一个数字")
click.echo()
- log_level: 日志级别 (DEBUG/INFO/WARNING/ERROR/CRITICAL)
password = click.prompt(prompt, hide_input=True, confirmation_prompt=True, type=str)
click.echo(f"密码长度: {len(password)} 字符")
return _validate_dashboard_password(password)
- dashboard.port: Dashboard 端口
- dashboard.username: Dashboard 用户名
def set_dashboard_credentials(
config: dict[str, Any],
*,
username: str | None = None,
password_hash: str | None = None,
) -> None:
if username is not None:
_set_nested_item(
config,
"dashboard.username",
_validate_dashboard_username(username),
)
if password_hash is not None:
if isinstance(password_hash, str) and is_dashboard_password_hash(password_hash):
_set_nested_item(config, "dashboard.password", password_hash)
else:
if is_legacy_dashboard_password(password_hash):
raise click.ClickException(
"Storing legacy dashboard password hashes is no longer supported. "
"Please provide the plaintext password (it will be hashed securely), "
"or provide an Argon2-encoded hash string.",
)
validated = _validate_dashboard_password(password_hash)
_set_nested_item(
config,
"dashboard.pbkdf2_password",
hash_dashboard_password(validated),
)
_set_nested_item(
config,
"dashboard.password",
hash_legacy_dashboard_password(validated),
)
- dashboard.password: Dashboard 密码
- callback_api_base: 回调接口基址
def _set_dashboard_password(config: dict[str, Any], raw_password: str) -> None:
"""Set dashboard password hashes and clear password migration flags."""
_set_nested_item(
config,
"dashboard.pbkdf2_password",
hash_dashboard_password(raw_password),
)
_set_nested_item(
config,
"dashboard.password",
hash_legacy_dashboard_password(raw_password),
)
_set_nested_item(config, "dashboard.password_storage_upgraded", True)
_set_nested_item(config, "dashboard.password_change_required", False)
@click.group(name="config")
def conf() -> None:
"""Configuration management commands.
Supported config keys:
- timezone
- log_level
- dashboard.port
- dashboard.username
- dashboard.password
- callback_api_base
"""
pass
@conf.command(name="set")
@click.argument("key")
@click.argument("value")
def set_config(key: str, value: str):
"""设置配置项的值"""
if key not in CONFIG_VALIDATORS.keys():
raise click.ClickException(f"不支持的配置项: {key}")
def set_config(key: str, value: str) -> None:
if key not in CONFIG_VALIDATORS:
raise click.ClickException(f"Unsupported config key: {key}")
config = _load_config()
try:
old_value = _get_nested_item(config, key)
# Attempt to get old value (may raise KeyError)
try:
old_value = _get_nested_item(config, key)
except Exception:
old_value = "<not set>"
validated_value = CONFIG_VALIDATORS[key](value)
_set_nested_item(config, key, validated_value)
if key == "dashboard.password":
_set_dashboard_password(config, validated_value)
else:
_set_nested_item(config, key, validated_value)
_save_config(config)
click.echo(f"配置已更新: {key}")
if key == "dashboard.password":
click.echo(" 原值: ********")
click.echo(" 新值: ********")
else:
click.echo(f" 原值: {old_value}")
click.echo(f" 新值: {validated_value}")
except KeyError:
raise click.ClickException(f"未知的配置项: {key}")
click.echo(f"Config updated: {key}")
click.echo(f" Old value: {old_value}")
click.echo(f" New value: {validated_value}")
except KeyError as e:
raise click.ClickException(f"Unknown config key: {key}") from e
except click.ClickException:
raise
except Exception as e:
raise click.UsageError(f"设置配置失败: {str(e)}")
raise click.UsageError(f"Failed to set config: {e!s}") from e
@conf.command(name="get")
@click.argument("key", required=False)
def get_config(key: str = None):
"""获取配置项的值不提供key则显示所有可配置项"""
def get_config(key: str | None = None) -> None:
config = _load_config()
if key:
if key not in CONFIG_VALIDATORS.keys():
raise click.ClickException(f"不支持的配置项: {key}")
if key not in CONFIG_VALIDATORS:
raise click.ClickException(f"Unsupported config key: {key}")
try:
value = _get_nested_item(config, key)
if key == "dashboard.password":
value = "********"
click.echo(f"{key}: {value}")
except KeyError:
raise click.ClickException(f"未知的配置项: {key}")
except KeyError as e:
raise click.ClickException(f"Unknown config key: {key}") from e
except Exception as e:
raise click.UsageError(f"获取配置失败: {str(e)}")
raise click.UsageError(f"Failed to get config: {e!s}") from e
else:
click.echo("当前配置:")
for key in CONFIG_VALIDATORS.keys():
click.echo("Current config:")
for k in CONFIG_VALIDATORS:
try:
value = (
v = (
"********"
if key == "dashboard.password"
else _get_nested_item(config, key)
if k == "dashboard.password"
else _get_nested_item(config, k)
)
click.echo(f" {key}: {value}")
click.echo(f" {k}: {v}")
except (KeyError, TypeError):
# Missing or non-dict paths are simply skipped in listing
pass
def _check_astrbot_not_running() -> None:
"""Refuse to proceed if astrbot is currently running (lock file held)."""
lock_file = astrbot_paths.root / "astrbot.lock"
if not lock_file.exists():
return
lock = FileLock(lock_file, timeout=1)
try:
lock.acquire()
except Timeout:
raise click.ClickException(
"AstrBot is currently running. "
"Please stop it first before changing the password via CLI.",
) from None
else:
lock.release()
@conf.command(name="admin")
@click.option("-u", "--username", type=str, help="Update admain username as well")
@click.option(
"-p",
"--password",
type=str,
help="Set admain password directly without interactive prompt",
)
def set_dashboard_password(username: str | None, password: str | None) -> None:
"""Interactively set dashboard password (with confirmation) or set directly with -p.
Acceptable inputs:
- Plaintext password (recommended): it will be hashed securely before storage.
- Argon2 encoded hash (advanced): stored as-is.
"""
_check_astrbot_not_running()
config = _load_config()
if password is not None:
if isinstance(password, str) and is_dashboard_password_hash(password):
password_hash = password
else:
if is_legacy_dashboard_password(password):
raise click.ClickException(
"Providing legacy dashboard password hashes is no longer supported. "
"Please supply the plaintext password (it will be hashed securely), "
"or provide an Argon2-encoded hash string.",
)
password_hash = _validate_dashboard_password(password)
else:
password_hash = prompt_dashboard_password()
set_dashboard_credentials(
config,
username=username.strip() if username is not None else None,
password_hash=password_hash,
)
_save_config(config)
if username is not None:
click.echo(f"Dashboard username updated: {username.strip()}")
click.echo("Dashboard password updated.")

View File

@@ -1,55 +1,237 @@
import asyncio
import json
import os
import re
from pathlib import Path
import click
from filelock import FileLock, Timeout
from ..utils import check_dashboard, get_astrbot_root
from astrbot.cli.utils import DashboardManager
from astrbot.core.config.default import DEFAULT_CONFIG
from astrbot.core.utils.astrbot_path import astrbot_paths
from .cmd_conf import ensure_config_file, set_dashboard_credentials
DASHBOARD_INITIAL_PASSWORD_ENV = "ASTRBOT_DASHBOARD_INITIAL_PASSWORD"
async def initialize_astrbot(astrbot_root) -> None:
"""执行 AstrBot 初始化逻辑"""
def _initialize_config_from_env(astrbot_root: Path) -> None:
if DASHBOARD_INITIAL_PASSWORD_ENV not in os.environ:
return
from astrbot.core.config.astrbot_config import AstrBotConfig
AstrBotConfig(config_path=str(astrbot_root / "data" / "cmd_config.json"))
click.echo("Initialized data/cmd_config.json with dashboard initial password.")
async def initialize_astrbot(
astrbot_root: Path,
*,
yes: bool,
backend_only: bool,
admin_username: str | None,
admin_password: str | None,
) -> None:
"""Execute AstrBot initialization logic"""
from astrbot.cli.banner import print_logo
click.echo("=" * 60)
click.echo("AstrBot 初始化向导")
click.echo("=" * 60)
print_logo()
click.echo()
dot_astrbot = astrbot_root / ".astrbot"
if not dot_astrbot.exists():
click.echo(f"Current Directory: {astrbot_root}")
click.echo(
"如果你确认这是 Astrbot root directory, 你需要在当前目录下创建一个 .astrbot 文件标记该目录为 AstrBot 的数据目录。"
)
if click.confirm(
f"请检查当前目录是否正确,确认正确请回车: {astrbot_root}",
if yes or click.confirm(
f"确定要将 AstrBot 安装到以下目录吗?\n {astrbot_root}",
default=True,
abort=True,
):
dot_astrbot.touch()
click.echo(f"Created {dot_astrbot}")
click.echo(f"[OK] 已创建: {dot_astrbot}")
paths = {
"data": astrbot_root / "data",
"config": astrbot_root / "data" / "config",
"plugins": astrbot_root / "data" / "plugins",
"temp": astrbot_root / "data" / "temp",
"skills": astrbot_root / "data" / "skills",
}
for name, path in paths.items():
path.mkdir(parents=True, exist_ok=True)
click.echo(f"{'Created' if not path.exists() else 'Directory exists'}: {path}")
status = "Created" if not path.exists() else "Exists"
click.echo(f" [{status}] {name.title()}: {path}")
await check_dashboard(astrbot_root / "data")
_initialize_config_from_env(astrbot_root)
config_path = astrbot_root / "data" / "cmd_config.json"
if not config_path.exists():
config_path.write_text(
json.dumps(DEFAULT_CONFIG, ensure_ascii=False, indent=2),
encoding="utf-8-sig",
)
click.echo(f"[OK] 配置文件已创建: {config_path}")
ASTRBOT_ROOT = astrbot_root
env_file = ASTRBOT_ROOT / ".env"
if not env_file.exists():
tmpl_candidates = [
Path("/opt/astrbot/config.template"),
getattr(astrbot_paths, "project_root", Path.cwd()) / "config.template",
Path.cwd() / "config.template",
]
tmpl = None
for t in tmpl_candidates:
try:
if t.exists():
tmpl = t
break
except Exception:
continue
if tmpl is not None:
try:
txt = tmpl.read_text(encoding="utf-8")
instance_name = astrbot_root.name or "astrbot"
txt = re.sub("\\$\\{INSTANCE_NAME(:-[^}]*)?\\}", instance_name, txt)
port_val = (
os.environ.get("ASTRBOT_PORT") or os.environ.get("PORT") or "8000"
)
txt = re.sub("\\$\\{PORT(:-[^}]*)?\\}", str(port_val), txt)
txt = re.sub("\\$\\{ASTRBOT_ROOT(:-[^}]*)?\\}", str(ASTRBOT_ROOT), txt)
header = f"# Generated from config.template by astrbot init for instance: {instance_name}\n# This file will be auto-loaded by 'astrbot run'\n\n"
env_file.write_text(header + txt, encoding="utf-8")
env_file.chmod(420)
click.echo(f"[OK] 环境变量文件已创建: {env_file}")
except Exception as e:
click.echo(f"[警告] 无法从模板生成 .env 文件: {e!s}")
else:
click.echo("[提示] 未找到 config.template 文件,跳过 .env 生成")
if admin_password is not None:
raise click.ClickException(
"--admin-password is no longer supported during init. Run 'astrbot conf admin' after initialization.",
)
effective_admin_username = (
admin_username.strip()
if admin_username
else str(DEFAULT_CONFIG["dashboard"]["username"])
)
if admin_username:
config = ensure_config_file()
set_dashboard_credentials(
config,
username=effective_admin_username,
password_hash=None,
)
config_path.write_text(
json.dumps(config, ensure_ascii=False, indent=2),
encoding="utf-8-sig",
)
click.echo(f"[OK] Dashboard admin 用户名已设置为: {effective_admin_username}")
click.echo()
click.echo("!" * 60)
click.echo("重要提示:")
click.echo(" 1. Dashboard 密码尚未设置!首次登录前必须先设置密码")
click.echo(" 2. 设置命令: astrbot conf admin")
click.echo(" 3. 登录地址: http://localhost:6185 或 http://服务器IP:6185")
click.echo("!" * 60)
click.echo()
if not backend_only and (
yes
or click.confirm(
"是否需要集成式 WebUI个人电脑推荐服务器推荐使用后端模式",
default=True,
)
):
await DashboardManager().ensure_installed(astrbot_root)
else:
click.echo()
click.echo("[提示] 你选择了后端模式,可以使用以下方式管理 AstrBot")
click.echo(" - 使用在线 Dashboard: 在浏览器中访问远程服务器的 WebUI")
click.echo(" - 使用 CLI 命令: astrbot conf / astrbot plug 等")
click.echo()
click.echo("!" * 60)
click.echo("安全提示:")
click.echo(" HTTPS 前端只能安全连接 localhost 的 HTTP 后端")
click.echo(" 不支持远程 + HTTP 后端(不安全)")
click.echo(" 如需远程访问,请使用 HTTPS 后端或通过反向代理")
click.echo("!" * 60)
click.echo()
@click.command()
def init() -> None:
"""初始化 AstrBot"""
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation prompts")
@click.option("--backend-only", "-b", is_flag=True, help="Only initialize the backend")
@click.option("--backup", "-f", help="Initialize from backup file", type=str)
@click.option(
"-u",
"--admin-username",
type=str,
help="Set dashboard admin username during initialization",
)
@click.option(
"-p",
"--admin-password",
type=str,
help="Deprecated. Run `astrbot conf admin` after initialization.",
)
@click.option(
"--root",
help="ASTRBOT root directory to initialize (overrides ASTRBOT_ROOT env)",
type=str,
)
def init(
yes: bool,
backend_only: bool,
backup: str | None,
admin_username: str | None,
admin_password: str | None,
root: str | None = None,
) -> None:
"""Initialize AstrBot"""
click.echo("Initializing AstrBot...")
astrbot_root = get_astrbot_root()
if os.environ.get("ASTRBOT_SYSTEMD") == "1":
yes = True
from astrbot.core.utils.astrbot_path import astrbot_paths
astrbot_root = Path(root) if root else astrbot_paths.root
lock_file = astrbot_root / "astrbot.lock"
lock = FileLock(lock_file, timeout=5)
try:
with lock.acquire():
asyncio.run(initialize_astrbot(astrbot_root))
except Timeout:
raise click.ClickException("无法获取锁文件,请检查是否有其他实例正在运行")
asyncio.run(
initialize_astrbot(
astrbot_root,
yes=yes,
backend_only=backend_only,
admin_username=admin_username,
admin_password=admin_password,
),
)
if backup:
from .cmd_bk import import_data_command
click.echo(f"Restoring from backup: {backup}")
click.get_current_context().invoke(
import_data_command,
backup_file=backup,
yes=True,
)
click.echo()
click.echo("=" * 60)
click.echo("初始化完成!")
click.echo("=" * 60)
click.echo()
click.echo("启动 AstrBot")
click.echo(" 完整模式(含 Dashboard: astrbot run")
click.echo(" 仅后端模式: astrbot run --backend-only")
click.echo()
click.echo("首次使用前请先设置管理员密码:")
click.echo(" astrbot conf admin")
click.echo()
except Timeout as err:
raise click.ClickException(
"Cannot acquire lock file. Please check if another instance is running",
) from err
except Exception as e:
raise click.ClickException(f"初始化失败: {e!s}")
raise click.ClickException(f"Initialization failed: {e!s}") from e

View File

@@ -0,0 +1,38 @@
import click
from .cmd_conf import (
_load_config,
_save_config,
_set_dashboard_password,
_set_nested_item,
_validate_dashboard_password,
_validate_dashboard_username,
)
@click.command(name="password")
@click.option(
"--username",
help="Optional dashboard username to set together with the new password.",
)
def password(username: str | None) -> None:
"""Change the AstrBot dashboard password."""
config = _load_config()
new_password = click.prompt(
"New dashboard password",
hide_input=True,
confirmation_prompt=True,
)
validated_password = _validate_dashboard_password(new_password)
if username is not None:
validated_username = _validate_dashboard_username(username.strip())
_set_nested_item(config, "dashboard.username", validated_username)
_set_dashboard_password(config, validated_password)
_save_config(config)
click.echo("Dashboard password updated.")
if username is not None:
click.echo(f"Dashboard username updated: {validated_username}")

View File

@@ -1,92 +1,85 @@
import re
from pathlib import Path
import click
import shutil
import click
from ..utils import (
get_git_repo,
build_plug_list,
manage_plugin,
from astrbot.cli.i18n import t
from astrbot.cli.utils import (
PluginStatus,
check_astrbot_root,
get_astrbot_root,
build_plug_list,
get_git_repo,
manage_plugin,
)
@click.group()
def plug():
"""插件管理"""
pass
@click.group(name="plugin")
def plug() -> None:
"""Plugin management"""
def _get_data_path() -> Path:
base = get_astrbot_root()
if not check_astrbot_root(base):
raise click.ClickException(
f"{base}不是有效的 AstrBot 根目录,如需初始化请使用 astrbot init"
)
return (base / "data").resolve()
def display_plugins(plugins, title=None, color=None):
def display_plugins(plugins, title=None, color=None) -> None:
if title:
click.echo(click.style(title, fg=color, bold=True))
click.echo(f"{'名称':<20} {'版本':<10} {'状态':<10} {'作者':<15} {'描述':<30}")
click.echo(
f"{'Name':<20} {'Version':<10} {'Status':<10} {'Author':<15} {'Description':<30}",
)
click.echo("-" * 85)
for p in plugins:
desc = p["desc"][:30] + ("..." if len(p["desc"]) > 30 else "")
click.echo(
f"{p['name']:<20} {p['version']:<10} {p['status']:<10} "
f"{p['author']:<15} {desc:<30}"
f"{p['author']:<15} {desc:<30}",
)
@plug.command()
@click.argument("name")
def new(name: str):
"""创建新插件"""
base_path = _get_data_path()
def new(name: str) -> None:
"""Create a new plugin"""
from astrbot.core.utils.astrbot_path import astrbot_paths
base_path = astrbot_paths.data
plug_path = base_path / "plugins" / name
if plug_path.exists():
raise click.ClickException(f"插件 {name} 已存在")
raise click.ClickException(t("plugin_already_exists", name=name))
author = click.prompt("请输入插件作者", type=str)
desc = click.prompt("请输入插件描述", type=str)
version = click.prompt("请输入插件版本", type=str)
author = click.prompt("Enter plugin author", type=str)
desc = click.prompt("Enter plugin description", type=str)
version = click.prompt("Enter plugin version", type=str)
if not re.match(r"^\d+\.\d+(\.\d+)?$", version.lower().lstrip("v")):
raise click.ClickException("版本号必须为 x.y x.y.z 格式")
repo = click.prompt("请输入插件仓库:", type=str)
raise click.ClickException("Version must be in x.y or x.y.z format")
repo = click.prompt("Enter plugin repository URL:", type=str)
if not repo.startswith("http"):
raise click.ClickException("仓库地址必须以 http 开头")
raise click.ClickException("Repository URL must start with http")
click.echo("下载插件模板...")
click.echo("Downloading plugin template...")
get_git_repo(
"https://github.com/Soulter/helloworld",
plug_path,
)
click.echo("重写插件信息...")
# 重写 metadata.yaml
click.echo("Rewriting plugin metadata...")
# Rewrite metadata.yaml
with open(plug_path / "metadata.yaml", "w", encoding="utf-8") as f:
f.write(
f"name: {name}\n"
f"desc: {desc}\n"
f"version: {version}\n"
f"author: {author}\n"
f"repo: {repo}\n"
f"repo: {repo}\n",
)
# 重写 README.md
# Rewrite README.md
with open(plug_path / "README.md", "w", encoding="utf-8") as f:
f.write(f"# {name}\n\n{desc}\n\n# 支持\n\n[帮助文档](https://astrbot.app)\n")
f.write(
f"# {name}\n\n{desc}\n\n# Support\n\n[Documentation](https://docs.astrbot.app)\n",
)
# 重写 main.py
with open(plug_path / "main.py", "r", encoding="utf-8") as f:
# Rewrite main.py
with open(plug_path / "main.py", encoding="utf-8") as f:
content = f.read()
new_content = content.replace(
@@ -97,55 +90,59 @@ def new(name: str):
with open(plug_path / "main.py", "w", encoding="utf-8") as f:
f.write(new_content)
click.echo(f"插件 {name} 创建成功")
click.echo(f"Plugin {name} created successfully")
@plug.command()
@click.option("--all", "-a", is_flag=True, help="列出未安装的插件")
def list(all: bool):
"""列出插件"""
base_path = _get_data_path()
@click.option("--all", "-a", is_flag=True, help="List uninstalled plugins")
def list(all: bool) -> None:
"""List plugins"""
from astrbot.core.utils.astrbot_path import astrbot_paths
base_path = astrbot_paths.data
plugins = build_plug_list(base_path / "plugins")
# 未发布的插件
# Unpublished plugins
not_published_plugins = [
p for p in plugins if p["status"] == PluginStatus.NOT_PUBLISHED
]
if not_published_plugins:
display_plugins(not_published_plugins, "未发布的插件", "red")
display_plugins(not_published_plugins, "Unpublished Plugins", "red")
# 需要更新的插件
# Plugins needing update
need_update_plugins = [
p for p in plugins if p["status"] == PluginStatus.NEED_UPDATE
]
if need_update_plugins:
display_plugins(need_update_plugins, "需要更新的插件", "yellow")
display_plugins(need_update_plugins, "Plugins Needing Update", "yellow")
# 已安装的插件
# Installed plugins
installed_plugins = [p for p in plugins if p["status"] == PluginStatus.INSTALLED]
if installed_plugins:
display_plugins(installed_plugins, "已安装的插件", "green")
display_plugins(installed_plugins, "Installed Plugins", "green")
# 未安装的插件
# Uninstalled plugins
not_installed_plugins = [
p for p in plugins if p["status"] == PluginStatus.NOT_INSTALLED
]
if not_installed_plugins and all:
display_plugins(not_installed_plugins, "未安装的插件", "blue")
display_plugins(not_installed_plugins, "Uninstalled Plugins", "blue")
if (
not any([not_published_plugins, need_update_plugins, installed_plugins])
and not all
):
click.echo("未安装任何插件")
click.echo("No plugins installed")
@plug.command()
@click.argument("name")
@click.option("--proxy", help="代理服务器地址")
def install(name: str, proxy: str | None):
"""安装插件"""
base_path = _get_data_path()
@click.option("--proxy", help="Proxy server address")
def install(name: str, proxy: str | None) -> None:
"""Install a plugin"""
from astrbot.core.utils.astrbot_path import astrbot_paths
base_path = astrbot_paths.data
plug_path = base_path / "plugins"
plugins = build_plug_list(base_path / "plugins")
@@ -159,39 +156,45 @@ def install(name: str, proxy: str | None):
)
if not plugin:
raise click.ClickException(f"未找到可安装的插件 {name},可能是不存在或已安装")
raise click.ClickException(t("plugin_not_found_or_installed", name=name))
manage_plugin(plugin, plug_path, is_update=False, proxy=proxy)
@plug.command()
@click.argument("name")
def remove(name: str):
"""卸载插件"""
base_path = _get_data_path()
def remove(name: str) -> None:
"""Uninstall a plugin"""
from astrbot.core.utils.astrbot_path import astrbot_paths
base_path = astrbot_paths.data
plugins = build_plug_list(base_path / "plugins")
plugin = next((p for p in plugins if p["name"] == name), None)
if not plugin or not plugin.get("local_path"):
raise click.ClickException(f"插件 {name} 不存在或未安装")
raise click.ClickException(t("plugin_not_found_or_installed", name=name))
plugin_path = plugin["local_path"]
click.confirm(f"确定要卸载插件 {name} 吗?", default=False, abort=True)
click.confirm(t("plugin_uninstall_confirm", name=name), default=False, abort=True)
try:
shutil.rmtree(plugin_path)
click.echo(f"插件 {name} 已卸载")
click.echo(t("plugin_uninstall_success", name=name))
except Exception as e:
raise click.ClickException(f"卸载插件 {name} 失败: {e}")
raise click.ClickException(
t("plugin_uninstall_failed_ex", name=name, error=str(e)),
) from e
@plug.command()
@click.argument("name", required=False)
@click.option("--proxy", help="Github代理地址")
def update(name: str, proxy: str | None):
"""更新插件"""
base_path = _get_data_path()
@click.option("--proxy", help="GitHub proxy address")
def update(name: str, proxy: str | None) -> None:
"""Update plugins"""
from astrbot.core.utils.astrbot_path import astrbot_paths
base_path = astrbot_paths.data
plug_path = base_path / "plugins"
plugins = build_plug_list(base_path / "plugins")
@@ -206,7 +209,9 @@ def update(name: str, proxy: str | None):
)
if not plugin:
raise click.ClickException(f"插件 {name} 不需要更新或无法更新")
raise click.ClickException(
f"Plugin {name} does not need updating or cannot be updated",
)
manage_plugin(plugin, plug_path, is_update=True, proxy=proxy)
else:
@@ -215,21 +220,23 @@ def update(name: str, proxy: str | None):
]
if not need_update_plugins:
click.echo("没有需要更新的插件")
click.echo(t("plugin_no_update_needed"))
return
click.echo(f"发现 {len(need_update_plugins)} 个插件需要更新")
click.echo(t("plugin_found_update", count=str(len(need_update_plugins))))
for plugin in need_update_plugins:
plugin_name = plugin["name"]
click.echo(f"正在更新插件 {plugin_name}...")
click.echo(t("plugin_updating", name=plugin_name))
manage_plugin(plugin, plug_path, is_update=True, proxy=proxy)
@plug.command()
@click.argument("query")
def search(query: str):
"""搜索插件"""
base_path = _get_data_path()
def search(query: str) -> None:
"""Search for plugins"""
from astrbot.core.utils.astrbot_path import astrbot_paths
base_path = astrbot_paths.data
plugins = build_plug_list(base_path / "plugins")
matched_plugins = [
@@ -241,7 +248,7 @@ def search(query: str):
]
if not matched_plugins:
click.echo(f"未找到匹配 '{query}' 的插件")
click.echo(t("plugin_search_no_result", query=query))
return
display_plugins(matched_plugins, f"搜索结果: '{query}'", "cyan")
display_plugins(matched_plugins, t("plugin_search_results", query=query), "cyan")

View File

@@ -1,22 +1,104 @@
"""AstrBot Run
Environment Variables Used in Project:
Core:
- `ASTRBOT_ROOT`: AstrBot root directory path.
- `ASTRBOT_LOG_LEVEL`: Log level (e.g. INFO, DEBUG).
- `ASTRBOT_CLI`: Flag indicating execution via CLI.
- `ASTRBOT_DESKTOP_CLIENT`: Flag indicating execution via desktop client.
- `ASTRBOT_SYSTEMD`: Flag indicating execution via systemd service.
- `ASTRBOT_RELOAD`: Enable plugin auto-reload (set to "1").
- `ASTRBOT_DISABLE_METRICS`: Disable metrics upload (set to "1").
- `TESTING`: Enable testing mode.
- `DEMO_MODE`: Enable demo mode.
- `PYTHON`: Python executable path override (for local code execution).
Dashboard / Backend:
- `ASTRBOT_DASHBOARD_ENABLE`: Enable/Disable Dashboard.
- `ASTRBOT_HOST`: Dashboard bind host.
- `ASTRBOT_PORT`: Dashboard bind port.
SSL (AstrBot-standard names):
- `ASTRBOT_SSL_ENABLE`: Enable SSL for API.
- `ASTRBOT_SSL_CERT`: SSL Certificate path for backend.
- `ASTRBOT_SSL_KEY`: SSL Key path for backend.
- `ASTRBOT_SSL_CA_CERTS`: SSL CA Certs path for backend.
Network:
- `http_proxy` / `https_proxy`: Proxy URL.
- `no_proxy`: No proxy list.
Internationalization:
- `ASTRBOT_CLI_LANG`: CLI interface language (zh/en).
Integrations:
- `DASHSCOPE_API_KEY`: Alibaba DashScope API Key (for Rerank).
- `COZE_API_KEY` / `COZE_BOT_ID`: Coze integration.
- `BAY_DATA_DIR`: Computer Use data directory.
Platform Specific:
- `TEST_MODE`: Test mode for QQOfficial.
"""
from __future__ import annotations
import asyncio
import os
import re
import sys
import traceback
from pathlib import Path
import click
import asyncio
import traceback
from dotenv import load_dotenv
from filelock import FileLock, Timeout
from ..utils import check_dashboard, check_astrbot_root, get_astrbot_root
from astrbot.cli.utils import DashboardManager
from astrbot.runtime_bootstrap import initialize_runtime_bootstrap
# Python version check: require 3.12 or 3.13
if not (sys.version_info.major == 3 and sys.version_info.minor in (12, 13)):
sys.exit(1)
# Regular expression to find bash-like parameter expansions:
# ${VAR:-default} or ${VAR}
_PARAM_EXPAND_RE = re.compile(r"\$\{([^}:]+?)(:-([^}]*))?\}")
async def run_astrbot(astrbot_root: Path):
"""运行 AstrBot"""
from astrbot.core import logger, LogManager, LogBroker, db_helper
def _expand_parameter(
match: re.Match,
env: dict[str, str],
local: dict[str, str],
) -> str:
"""Helper to expand a single ${VAR:-default} or ${VAR} occurrence.
Precedence:
1. local dict (parsed from the same file, earlier entries)
2. environment variables
3. default provided in the expansion (if any)
4. empty string
"""
var = match.group(1)
default = match.group(3) if match.group(3) is not None else ""
# Prefer 'local' parsed values first
if var in local and local[var] != "":
return local[var]
val = env.get(var, "")
if val != "":
return val
return default
async def run_astrbot(astrbot_root: Path) -> None:
"""Run AstrBot"""
from astrbot.core import LogBroker, LogManager, db_helper, logger
from astrbot.core.initial_loader import InitialLoader
await check_dashboard(astrbot_root / "data")
if (
os.environ.get("ASTRBOT_DASHBOARD_ENABLE", os.environ.get("DASHBOARD_ENABLE"))
== "True"
):
await DashboardManager().ensure_installed(astrbot_root)
log_broker = LogBroker()
LogManager.set_queue_handler(logger, log_broker)
@@ -27,37 +109,317 @@ async def run_astrbot(astrbot_root: Path):
await core_lifecycle.start()
@click.option("--reload", "-r", is_flag=True, help="插件自动重载")
@click.option("--port", "-p", help="Astrbot Dashboard端口", required=False, type=str)
@click.option("--reload", "-r", is_flag=True, help="Auto-reload plugins")
@click.option("--host", "-H", help="AstrBot Dashboard Host", required=False, type=str)
@click.option("--port", "-p", help="AstrBot Dashboard port", required=False, type=str)
@click.option("--root", help="AstrBot root directory", required=False, type=str)
@click.option(
"--service-config",
"-c",
help="Service configuration file path (supports ${VAR:-default} style expansion)",
required=False,
type=str,
)
@click.option(
"--backend-only",
"-b",
is_flag=True,
default=False,
help="Disable WebUI, run backend only",
)
@click.option(
"--log-level",
"-l",
help="Log level",
required=False,
type=str,
default="INFO",
)
@click.option(
"--ssl-cert",
help="SSL certificate file path for backend (preferred env name: ASTRBOT_SSL_CERT)",
required=False,
type=str,
)
@click.option(
"--ssl-key",
help="SSL private key file path for backend (preferred env name: ASTRBOT_SSL_KEY)",
required=False,
type=str,
)
@click.option(
"--ssl-ca",
help="SSL CA certificates file path for backend (preferred env name: ASTRBOT_SSL_CA_CERTS)",
required=False,
type=str,
)
@click.option("--debug", is_flag=True, help="Enable debug mode")
@click.command()
def run(reload: bool, port: str) -> None:
"""运行 AstrBot"""
def run(
reload: bool,
host: str,
port: str,
root: str,
service_config: str,
backend_only: bool,
log_level: str,
ssl_cert: str,
ssl_key: str,
ssl_ca: str,
debug: bool,
) -> None:
"""Run AstrBot"""
initialize_runtime_bootstrap()
try:
os.environ["ASTRBOT_CLI"] = "1"
astrbot_root = get_astrbot_root()
if debug:
log_level = "DEBUG"
if not check_astrbot_root(astrbot_root):
# --- Step 1: Resolve service-config path (if provided). We'll treat it as a .env file later. ---
svc_path: Path | None = None
if service_config:
candidate = Path(service_config)
if not candidate.exists():
# Try to expand user and resolve
candidate = Path(os.path.expanduser(service_config))
if candidate.exists():
svc_path = candidate
# NOTE:
# Loading of common .env files (CWD/.env, packaged project .env, ASTRBOT_ROOT/.env)
# has been moved to astrbot.core.utils.astrbot_path during import-time to avoid
# early-initialization ordering issues. Those files are loaded there using
# `override=False` so they do not clobber environment variables provided by the
# systemd unit or the caller.
#
# Here we only load an explicit service-config file (if given). Service-config
# should be able to override the common .env files, but CLI-provided values must
# still win; the CLI will set/overwrite corresponding environment variables
# below after this load.
if svc_path and svc_path.exists():
# Load service-config as an env file and allow it to override previously-loaded
# .env values (those were loaded by astrbot_path). CLI variables are applied
# after this point and will take precedence.
load_dotenv(dotenv_path=str(svc_path), override=True)
# Mark CLI execution
os.environ["ASTRBOT_CLI"] = "1"
from astrbot.core.utils.astrbot_path import astrbot_paths
# Resolve astrbot_root with the following precedence:
# 1. CLI --root parameter (local variable `root`)
# 2. ASTRBOT_ROOT environment variable (possibly from .env or parsed service config)
# 3. packaged default astrbot_paths.root
if root:
os.environ["ASTRBOT_ROOT"] = root
astrbot_root = Path(root)
elif os.environ.get("ASTRBOT_ROOT"):
astrbot_root = Path(os.environ["ASTRBOT_ROOT"])
else:
astrbot_root = astrbot_paths.root
if not astrbot_paths.is_root:
raise click.ClickException(
f"{astrbot_root}不是有效的 AstrBot 根目录,如需初始化请使用 astrbot init"
f"{astrbot_root} is not a valid AstrBot root directory. Use 'astrbot init' to initialize",
)
# Ensure ASTRBOT_ROOT env var is set to the resolved root (without overriding a CLI-provided root value above)
os.environ["ASTRBOT_ROOT"] = str(astrbot_root)
sys.path.insert(0, str(astrbot_root))
if port:
os.environ["DASHBOARD_PORT"] = port
# Host/Port precedence: CLI args > parsed service config/env/.env > defaults.
if port is not None:
os.environ["ASTRBOT_PORT"] = port
if host is not None:
os.environ["ASTRBOT_HOST"] = host
# CLI-provided SSL paths should set backend-standard env names.
if ssl_cert is not None:
os.environ["ASTRBOT_SSL_CERT"] = ssl_cert
if ssl_key is not None:
os.environ["ASTRBOT_SSL_KEY"] = ssl_key
if ssl_ca is not None:
os.environ["ASTRBOT_SSL_CA_CERTS"] = ssl_ca
# Dashboard enable is derived from CLI flag (--backend-only). CLI decision should win.
os.environ["ASTRBOT_DASHBOARD_ENABLE"] = str(not backend_only)
os.environ["ASTRBOT_LOG_LEVEL"] = log_level
if reload:
click.echo("启用插件自动重载")
click.echo("Plugin auto-reload enabled")
os.environ["ASTRBOT_RELOAD"] = "1"
if debug:
keys_to_print = [
"ASTRBOT_ROOT",
"ASTRBOT_LOG_LEVEL",
"ASTRBOT_CLI",
"ASTRBOT_DESKTOP_CLIENT",
"ASTRBOT_SYSTEMD",
"ASTRBOT_RELOAD",
"ASTRBOT_DISABLE_METRICS",
"TESTING",
"DEMO_MODE",
"PYTHON",
"ASTRBOT_DASHBOARD_ENABLE",
"DASHBOARD_ENABLE",
"ASTRBOT_HOST",
"DASHBOARD_HOST",
"ASTRBOT_PORT",
"DASHBOARD_PORT",
# Dashboard SSL (legacy)
"ASTRBOT_SSL_ENABLE",
"DASHBOARD_SSL_ENABLE",
"ASTRBOT_SSL_CERT",
"DASHBOARD_SSL_CERT",
"ASTRBOT_SSL_KEY",
"DASHBOARD_SSL_KEY",
"ASTRBOT_SSL_CA_CERTS",
"DASHBOARD_SSL_CA_CERTS",
# Backend-standard SSL (preferred)
"ASTRBOT_SSL_ENABLE",
"ASTRBOT_SSL_CERT",
"ASTRBOT_SSL_KEY",
"ASTRBOT_SSL_CA_CERTS",
"http_proxy",
"https_proxy",
"no_proxy",
"DASHSCOPE_API_KEY",
"COZE_API_KEY",
"COZE_BOT_ID",
"BAY_DATA_DIR",
"TEST_MODE",
]
click.secho("\n[Debug Mode] Environment Variables:", fg="yellow", bold=True)
for key in keys_to_print:
if key in os.environ:
val = os.environ[key]
if "KEY" in key or "PASSWORD" in key or "SECRET" in key:
if len(val) > 8:
val = val[:4] + "****" + val[-4:]
else:
val = "****"
click.echo(f" {click.style(key, fg='cyan')}: {val}")
if svc_path:
click.echo(
f" {click.style('SERVICE_CONFIG', fg='cyan')}: {svc_path!s}",
)
click.echo("")
lock_file = astrbot_root / "astrbot.lock"
lock = FileLock(lock_file, timeout=5)
with lock.acquire():
asyncio.run(run_astrbot(astrbot_root))
async def run_with_logging() -> None:
from astrbot.core import LogBroker, LogManager, db_helper, logger
from astrbot.core.initial_loader import InitialLoader
if (
os.environ.get(
"ASTRBOT_DASHBOARD_ENABLE",
os.environ.get("DASHBOARD_ENABLE"),
)
== "True"
):
await DashboardManager().ensure_installed(astrbot_root)
log_broker = LogBroker()
LogManager.set_queue_handler(logger, log_broker)
# Register a stdout subscriber for real-time log streaming
log_queue = log_broker.register()
db = db_helper
initial_loader = InitialLoader(db, log_broker)
# Start a task to stream logs to stdout
async def stream_logs() -> None:
"""Stream logs from LogBroker to stdout."""
while True:
try:
log_entry = await asyncio.wait_for(
log_queue.get(),
timeout=0.5,
)
# Format: [LEVEL] message
level = log_entry.get("level_name", "INFO")
message = log_entry.get("message", "")
if message:
level_color = {
"DEBUG": "cyan",
"INFO": "green",
"WARNING": "yellow",
"ERROR": "red",
"CRITICAL": "red",
}.get(level, "white")
click.secho(
f"[{level}]",
fg=level_color,
bold=False,
nl=False,
)
click.echo(f" {message}")
except TimeoutError:
continue
except asyncio.CancelledError:
break
# Start streaming task
stream_task = asyncio.create_task(stream_logs())
try:
await initial_loader.start()
finally:
stream_task.cancel()
try:
await stream_task
except asyncio.CancelledError:
pass
click.echo()
click.echo("=" * 60)
click.echo("AstrBot 启动中...")
click.echo("=" * 60)
from astrbot.cli.banner import print_logo
print_logo()
click.echo()
if backend_only:
click.echo("[模式] 仅后端模式(无本地 Dashboard")
click.echo()
click.echo("[提示] 可以通过以下方式访问 WebUI")
click.echo(" - 使用远程服务器的在线 Dashboard")
click.echo(" - 地址: http://服务器IP:6185")
click.echo()
else:
dashboard_url = f"http://{host or 'localhost'}:{port or '6185'}"
click.echo("[模式] 完整模式(含本地 Dashboard")
click.echo()
click.echo(f"[Dashboard] 请访问: {dashboard_url}")
click.echo()
click.echo("!" * 60)
click.echo("安全提示:")
click.echo(" HTTPS 前端只能安全连接 localhost 的 HTTP 后端")
click.echo(" 不支持远程 + HTTP 后端(不安全)")
click.echo("!" * 60)
click.echo()
click.echo("正在启动服务...(日志输出中)")
click.echo()
asyncio.run(run_with_logging())
except KeyboardInterrupt:
click.echo("AstrBot 已关闭...")
click.echo("AstrBot has been shut down.")
except Timeout:
raise click.ClickException("无法获取锁文件,请检查是否有其他实例正在运行")
raise click.ClickException(
"Cannot acquire lock file. Please check if another instance is running",
) from None
except Exception as e:
raise click.ClickException(f"运行时出现错误: {e}\n{traceback.format_exc()}")
# Keep original traceback visible for diagnostics
raise click.ClickException(
f"Runtime error: {e}\n{traceback.format_exc()}",
) from e

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,69 @@
import os
import shutil
from pathlib import Path
import click
from astrbot.core.utils.astrbot_path import astrbot_paths
@click.command()
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation prompts")
@click.option(
"--keep-data",
is_flag=True,
help="Keep data directory (config, plugins, etc.)",
)
def uninstall(yes: bool, keep_data: bool) -> None:
"""Remove AstrBot files from the current root directory."""
if os.environ.get("ASTRBOT_SYSTEMD") == "1":
yes = True
dot_astrbot = astrbot_paths.root / ".astrbot"
lock_file = astrbot_paths.root / "astrbot.lock"
data_dir = astrbot_paths.data
removable_paths: list[Path] = [dot_astrbot, lock_file]
if not keep_data:
removable_paths.insert(0, data_dir)
# Check if this looks like an AstrBot root before blowing things up
if not dot_astrbot.exists() and not data_dir.exists():
click.echo("No AstrBot initialization found in current directory.")
return
if keep_data:
click.echo("Keeping data directory as requested.")
if yes or click.confirm(
f"Are you sure you want to remove AstrBot data at {astrbot_paths.root}? \n"
f"This will delete:\n"
f" - {data_dir} (Config, Plugins, Database)\n"
f" - {dot_astrbot}\n"
f" - {lock_file}",
default=False,
abort=True,
):
removed_any = False
for path in removable_paths:
if not path.exists():
continue
removed_any = True
if path.is_dir():
click.echo(f"Removing directory: {path}")
shutil.rmtree(path)
else:
click.echo(f"Removing file: {path}")
path.unlink()
if removed_any:
click.echo("AstrBot files removed successfully.")
else:
click.echo("No removable AstrBot files were found.")
# TODO: Consider adding an explicit `--service` cleanup mode instead of
# touching systemd or other service managers during normal uninstall.
# TODO: Consider adding package-manager-specific uninstall helpers once
# the CLI can reliably detect the installation source.
click.echo("uv: uv tool uninstall astrbot")
click.echo("paru/yay: paru -R astrbot")

278
astrbot/cli/i18n.py Normal file
View File

@@ -0,0 +1,278 @@
"""Internationalization support for AstrBot CLI.
This module provides i18n support with Chinese and English languages.
Language is auto-detected from environment or can be set manually.
"""
from __future__ import annotations
import os
from enum import Enum
from functools import lru_cache
class Language(Enum):
"""Supported languages."""
ZH = "zh"
EN = "en"
# Translation dictionaries
_TRANSLATIONS: dict[Language, dict[str, str]] = {
Language.ZH: {
# CLI welcome and general
"cli_welcome": "欢迎使用 AstrBot CLI!",
"cli_version": "AstrBot CLI 版本: {version}",
"cli_unknown_command": "未知命令: {command}",
"cli_help_available": "使用 astrbot help --all 查看所有命令",
# Dashboard commands
"dashboard_bundled": "Dashboard 已打包在安装包中 - 跳过下载",
"dashboard_not_installed": "Dashboard 未安装",
"dashboard_install_confirm": "是否安装 Dashboard?",
"dashboard_installing": "正在安装 Dashboard...",
"dashboard_install_success": "Dashboard 安装成功",
"dashboard_install_failed": "Dashboard 安装失败: {error}",
"dashboard_not_needed": "Dashboard 不需要安装",
"dashboard_declined": "Dashboard 安装已取消",
"dashboard_already_up_to_date": "Dashboard 已是最新版本",
"dashboard_version": "Dashboard 版本: {version}",
"dashboard_download_failed": "Dashboard 下载失败: {error}",
"dashboard_init_dir": "正在初始化 Dashboard 目录...",
"dashboard_init_success": "Dashboard 初始化成功",
# Plugin commands
"plugin_installing": "正在安装插件: {name}",
"plugin_install_success": "插件安装成功: {name}",
"plugin_install_failed": "插件安装失败: {name}",
"plugin_uninstall_confirm": "确定要卸载插件 {name} 吗?",
"plugin_uninstall_success": "插件卸载成功: {name}",
"plugin_uninstall_failed": "插件卸载失败: {name}",
"plugin_list_empty": "未安装任何插件",
"plugin_already_installed": "插件已安装: {name}",
"plugin_not_found": "插件未找到: {name}",
"plugin_already_exists": "插件已存在: {name}",
"plugin_not_found_or_installed": "插件未找到或已安装: {name}",
"plugin_uninstall_failed_ex": "插件卸载失败 {name}: {error}",
"plugin_no_update_needed": "没有需要更新的插件",
"plugin_found_update": "发现 {count} 个插件需要更新",
"plugin_updating": "正在更新插件 {name}...",
"plugin_search_no_result": "未找到匹配 '{query}' 的插件",
"plugin_search_results": "搜索结果: '{query}'",
# Config commands
"config_show": "显示配置",
"config_set_success": "配置项已更新: {key} = {value}",
"config_set_failed": "配置项更新失败: {key}",
"config_set_failed_ex": "设置配置失败: {error}",
"config_get_success": "{key} = {value}",
"config_get_not_found": "配置项未找到: {key}",
"config_reset_confirm": "确定要重置所有配置吗?",
"config_reset_success": "配置已重置",
# Config validators
"config_log_level_invalid": "日志级别必须是 DEBUG/INFO/WARNING/ERROR/CRITICAL 之一",
"config_port_must_be_number": "端口必须是数字",
"config_port_range_invalid": "端口必须在 1-65535 范围内",
"config_username_empty": "用户名不能为空",
"config_password_empty": "密码不能为空",
"config_timezone_invalid": "无效的时区: {value}。请使用有效的 IANA 时区名称",
"config_callback_invalid": "回调 API 基础路径必须以 http:// 或 https:// 开头",
"config_key_unsupported": "不支持的配置项: {key}",
"config_key_unknown": "未知的配置项: {key}",
"config_updated": "配置已更新: {key}",
# Init command
"init_creating": "正在创建配置目录...",
"init_created": "配置目录已创建: {path}",
"init_copying": "正在复制配置文件...",
"init_copied": "配置文件已复制",
"init_success": "AstrBot 初始化完成!",
"init_failed": "初始化失败: {error}",
# Run command
"run_starting": "正在启动 AstrBot...",
"run_started": "AstrBot 已启动!",
"run_backend_only": "以无界面模式启动",
"run_failed": "启动失败: {error}",
"run_stopped": "AstrBot 已停止",
# Common
"yes": "",
"no": "",
"cancel": "取消",
"confirm": "确认",
"error": "错误",
"success": "成功",
"warning": "警告",
"info": "信息",
"loading": "加载中...",
"done": "完成",
"failed": "失败",
"retry": "重试",
"exit": "退出",
"continue": "继续",
},
Language.EN: {
# CLI welcome and general
"cli_welcome": "Welcome to AstrBot CLI!",
"cli_version": "AstrBot CLI version: {version}",
"cli_unknown_command": "Unknown command: {command}",
"cli_help_available": "Use astrbot help --all to see all commands",
# Dashboard commands
"dashboard_bundled": "Dashboard is bundled with the package - skipping download",
"dashboard_not_installed": "Dashboard is not installed",
"dashboard_install_confirm": "Install Dashboard?",
"dashboard_installing": "Installing Dashboard...",
"dashboard_install_success": "Dashboard installed successfully",
"dashboard_install_failed": "Failed to install dashboard: {error}",
"dashboard_not_needed": "Dashboard not needed",
"dashboard_declined": "Dashboard installation declined.",
"dashboard_already_up_to_date": "Dashboard is already up to date",
"dashboard_version": "Dashboard version: {version}",
"dashboard_download_failed": "Failed to download dashboard: {error}",
"dashboard_init_dir": "Initializing dashboard directory...",
"dashboard_init_success": "Dashboard initialized successfully",
# Plugin commands
"plugin_installing": "Installing plugin: {name}",
"plugin_install_success": "Plugin installed successfully: {name}",
"plugin_install_failed": "Failed to install plugin: {name}",
"plugin_uninstall_confirm": "Uninstall plugin {name}?",
"plugin_uninstall_success": "Plugin uninstalled successfully: {name}",
"plugin_uninstall_failed": "Failed to uninstall plugin: {name}",
"plugin_list_empty": "No plugins installed",
"plugin_already_installed": "Plugin already installed: {name}",
"plugin_not_found": "Plugin not found: {name}",
"plugin_already_exists": "Plugin {name} already exists",
"plugin_not_found_or_installed": "Plugin {name} not found or already installed",
"plugin_uninstall_failed_ex": "Failed to uninstall plugin {name}: {error}",
"plugin_no_update_needed": "No plugins need updating",
"plugin_found_update": "Found {count} plugin(s) needing update",
"plugin_updating": "Updating plugin {name}...",
"plugin_search_no_result": "No plugins matching '{query}' found",
"plugin_search_results": "Search results: '{query}'",
# Config commands
"config_show": "Show configuration",
"config_set_success": "Configuration updated: {key} = {value}",
"config_set_failed": "Failed to update configuration: {key}",
"config_set_failed_ex": "Failed to set config: {error}",
"config_get_success": "{key} = {value}",
"config_get_not_found": "Configuration key not found: {key}",
"config_reset_confirm": "Reset all configuration?",
"config_reset_success": "Configuration reset",
# Config validators
"config_log_level_invalid": "Log level must be one of DEBUG/INFO/WARNING/ERROR/CRITICAL",
"config_port_must_be_number": "Port must be a number",
"config_port_range_invalid": "Port must be in range 1-65535",
"config_username_empty": "Username cannot be empty",
"config_password_empty": "Password cannot be empty",
"config_timezone_invalid": "Invalid timezone: {value}. Please use a valid IANA timezone name",
"config_callback_invalid": "Callback API base must start with http:// or https://",
"config_key_unsupported": "Unsupported config key: {key}",
"config_key_unknown": "Unknown config key: {key}",
"config_updated": "Config updated: {key}",
# Init command
"init_creating": "Creating config directory...",
"init_created": "Config directory created: {path}",
"init_copying": "Copying config files...",
"init_copied": "Config files copied",
"init_success": "AstrBot initialized successfully!",
"init_failed": "Initialization failed: {error}",
# Run command
"run_starting": "Starting AstrBot...",
"run_started": "AstrBot started!",
"run_backend_only": "Starting in backend-only mode",
"run_failed": "Failed to start: {error}",
"run_stopped": "AstrBot stopped",
# Common
"yes": "Yes",
"no": "No",
"cancel": "Cancel",
"confirm": "Confirm",
"error": "Error",
"success": "Success",
"warning": "Warning",
"info": "Info",
"loading": "Loading...",
"done": "Done",
"failed": "Failed",
"retry": "Retry",
"exit": "Exit",
"continue": "Continue",
},
}
@lru_cache(maxsize=1)
def get_current_language() -> Language:
"""Get the current language based on environment or default.
Detection order:
1. ASTRBOT_CLI_LANG environment variable (zh/en)
2. LANG environment variable (if contains zh/cn)
3. LC_ALL environment variable (if contains zh/cn)
4. Default to Chinese (most users are Chinese)
"""
# Check explicit override first
explicit = os.environ.get("ASTRBOT_CLI_LANG", "").lower()
if explicit in ("zh", "en"):
return Language.ZH if explicit == "zh" else Language.EN
# Check LANG/LC_ALL for Chinese
for env_var in ("LANG", "LC_ALL"):
lang = os.environ.get(env_var, "").lower()
if "zh" in lang or "cn" in lang:
return Language.ZH
# Default to Chinese for broader appeal
return Language.ZH
def set_language(lang: Language) -> None:
"""Set the current language (clears all translation caches)."""
get_current_language.cache_clear()
_t_cached.cache_clear()
# Set environment variable for persistence
os.environ["ASTRBOT_CLI_LANG"] = lang.value
@lru_cache(maxsize=128)
def _t_cached(key: str, lang: Language) -> str:
"""Cached translation lookup."""
return _TRANSLATIONS.get(lang, {}).get(key, key)
def t(translation_key: str, **kwargs: str) -> str:
"""Get translation for the given key in the current language.
Args:
translation_key: Translation key (e.g., "cli_welcome", "plugin_installing")
**kwargs: Format arguments for the translation string
Returns:
Translated string, or the key itself if not found
"""
result = _t_cached(translation_key, get_current_language())
if kwargs:
result = result.format(**kwargs)
return result
def tr(key: str, **kwargs: str) -> str:
"""Get translation (alias for t())."""
return t(key, **kwargs)
class CLITranslations:
"""Translation accessor class for CLI contexts.
Usage:
translations = CLITranslations()
print(translations.cli_welcome)
print(translations.plugin_installing(name="my_plugin"))
"""
def __getattr__(self, key: str) -> str:
return t(key)
def __call__(self, key: str, **kwargs: str) -> str:
return t(key, **kwargs)
# Convenience instance
translations = CLITranslations()

View File

@@ -1,18 +1,12 @@
from .basic import (
get_astrbot_root,
check_astrbot_root,
check_dashboard,
)
from .plugin import get_git_repo, manage_plugin, build_plug_list, PluginStatus
from .dashboard import DashboardManager
from .plugin import PluginStatus, build_plug_list, get_git_repo, manage_plugin
from .version_comparator import VersionComparator
__all__ = [
"get_astrbot_root",
"check_astrbot_root",
"check_dashboard",
"DashboardManager",
"PluginStatus",
"VersionComparator",
"build_plug_list",
"get_git_repo",
"manage_plugin",
"build_plug_list",
"VersionComparator",
"PluginStatus",
]

View File

@@ -2,9 +2,12 @@ from pathlib import Path
import click
# Static assets bundled inside the installed wheel (built by hatch_build.py).
_BUNDLED_DIST = Path(__file__).parent.parent.parent / "dashboard" / "dist"
def check_astrbot_root(path: str | Path) -> bool:
"""检查路径是否为 AstrBot 根目录"""
"""Check if the path is an AstrBot root directory"""
if not isinstance(path, Path):
path = Path(path)
if not path.exists() or not path.is_dir():
@@ -15,54 +18,58 @@ def check_astrbot_root(path: str | Path) -> bool:
def get_astrbot_root() -> Path:
"""获取Astrbot根目录路径"""
"""Get the AstrBot root directory path"""
return Path.cwd()
async def check_dashboard(astrbot_root: Path) -> None:
"""检查是否安装了dashboard"""
from astrbot.core.utils.io import get_dashboard_version, download_dashboard
"""Check if the dashboard is installed"""
from astrbot.core.config.default import VERSION
from astrbot.core.utils.io import download_dashboard, get_dashboard_version
from .version_comparator import VersionComparator
# If the wheel ships bundled dashboard assets, no network download is needed.
if _BUNDLED_DIST.exists():
click.echo("Dashboard is bundled with the package skipping download.")
return
try:
dashboard_version = await get_dashboard_version()
match dashboard_version:
case None:
click.echo("未安装管理面板")
click.echo("Dashboard is not installed")
if click.confirm(
"是否安装管理面板?",
"Install dashboard?",
default=True,
abort=True,
):
click.echo("正在安装管理面板...")
click.echo("Installing dashboard...")
await download_dashboard(
path="data/dashboard.zip",
extract_path=str(astrbot_root),
version=f"v{VERSION}",
latest=False,
)
click.echo("管理面板安装完成")
click.echo("Dashboard installed successfully")
case str():
if VersionComparator.compare_version(VERSION, dashboard_version) <= 0:
click.echo("管理面板已是最新版本")
click.echo("Dashboard is already up to date")
return
try:
version = dashboard_version.split("v")[1]
click.echo(f"Dashboard version: {version}")
await download_dashboard(
path="data/dashboard.zip",
extract_path=str(astrbot_root),
version=f"v{VERSION}",
latest=False,
)
except Exception as e:
click.echo(f"Failed to download dashboard: {e}")
return
else:
try:
version = dashboard_version.split("v")[1]
click.echo(f"管理面板版本: {version}")
await download_dashboard(
path="data/dashboard.zip",
extract_path=str(astrbot_root),
version=f"v{VERSION}",
latest=False,
)
except Exception as e:
click.echo(f"下载管理面板失败: {e}")
return
except FileNotFoundError:
click.echo("初始化管理面板目录...")
click.echo("Initializing dashboard directory...")
try:
await download_dashboard(
path=str(astrbot_root / "dashboard.zip"),
@@ -70,7 +77,7 @@ async def check_dashboard(astrbot_root: Path) -> None:
version=f"v{VERSION}",
latest=False,
)
click.echo("管理面板初始化完成")
click.echo("Dashboard initialized successfully")
except Exception as e:
click.echo(f"下载管理面板失败: {e}")
click.echo(f"Failed to download dashboard: {e}")
return

Some files were not shown because too many files have changed in this diff Show More