mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-09 22:40:13 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12f2f5a09c | ||
|
|
afb898e61f | ||
|
|
0be821afc6 | ||
|
|
dcc40ede1d | ||
|
|
adebd2958e | ||
|
|
331444b41f |
62
README.md
62
README.md
@@ -75,6 +75,10 @@ AstrBot is an open-source all-in-one Agent chatbot platform that integrates with
|
||||
|
||||
### One-Click Deployment
|
||||
|
||||
> [!NOTE]
|
||||
> Requires [uv](https://docs.astral.sh/uv/) to be installed.
|
||||
> For macOS users: due to macOS security checks, the first run of the `astrbot` command may take longer (about 10-20s).
|
||||
|
||||
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
|
||||
@@ -83,20 +87,17 @@ astrbot init # Only execute this command for the first time to initialize the en
|
||||
astrbot run
|
||||
```
|
||||
|
||||
> 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.
|
||||
### One-Click Cloud Deployment (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 ☁️:
|
||||
|
||||
[](https://app.rainyun.com/apps/rca/store/5994?ref=NjU1ODg0)
|
||||
|
||||
### Docker Deployment
|
||||
|
||||
@@ -104,12 +105,6 @@ For users familiar with containers and looking for a more stable, production-rea
|
||||
|
||||
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 ☁️:
|
||||
|
||||
[](https://app.rainyun.com/apps/rca/store/5994?ref=NjU1ODg0)
|
||||
|
||||
### Desktop Application Deployment
|
||||
|
||||
For users who want to use AstrBot on desktop and mainly use ChatUI, we recommend AstrBot App.
|
||||
@@ -142,6 +137,18 @@ yay -S astrbot-git
|
||||
|
||||
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`.
|
||||
|
||||
|
||||
## ❤️ Sponsors
|
||||
|
||||
Welcome to sponsor us via [Afdian](https://afdian.com/a/astrbot_team) or [contact us](mailto:community@astrbot.app).
|
||||
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://astrbot.app/#/sponsors">
|
||||
<img alt="sponsors" src="https://sponsors.astrbot.app/?v=1">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
## Supported Messaging Platforms
|
||||
|
||||
Connect AstrBot to your favorite chat platform.
|
||||
@@ -205,13 +212,6 @@ Connect AstrBot to your favorite chat platform.
|
||||
| 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 :)
|
||||
@@ -235,22 +235,7 @@ pre-commit install
|
||||
|
||||
### 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
|
||||
We have 15+ chat groups, please see: [Community](https://docs.astrbot.app/community.html) for details.
|
||||
|
||||
### Discord Server
|
||||
|
||||
@@ -264,9 +249,10 @@ Special thanks to all Contributors and plugin developers for their contributions
|
||||
<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:
|
||||
Open Source Friends ❤️
|
||||
|
||||
- [NapNeko/NapCatQQ](https://github.com/NapNeko/NapCatQQ) - The amazing cat framework
|
||||
- [Mai-with-u/MaiBot](https://github.com/Mai-with-u/MaiBot) - The powerful "digital life" in your QQ!
|
||||
|
||||
## ⭐ Star History
|
||||
|
||||
|
||||
@@ -243,7 +243,13 @@ class ResultDecorateStage(Stage):
|
||||
continue
|
||||
for seg in split_response:
|
||||
if self.content_cleanup_rule:
|
||||
seg = re.sub(self.content_cleanup_rule, "", seg)
|
||||
try:
|
||||
seg = re.sub(self.content_cleanup_rule, "", seg)
|
||||
except re.error:
|
||||
logger.error(
|
||||
f"分段回复过滤表达式失败,无法成功过滤:{traceback.format_exc()}"
|
||||
)
|
||||
self.content_cleanup_rule = None
|
||||
seg = seg.strip()
|
||||
if seg:
|
||||
new_chain.append(Plain(seg))
|
||||
|
||||
@@ -133,7 +133,7 @@ class LinePlatformAdapter(Platform):
|
||||
return "invalid signature", 400
|
||||
|
||||
try:
|
||||
payload = await request.get_json(force=True, silent=False)
|
||||
payload = await request.get_json(silent=False)
|
||||
except Exception as e:
|
||||
logger.warning("[LINE] invalid webhook body: %s", e)
|
||||
return "bad request", 400
|
||||
|
||||
@@ -369,6 +369,12 @@ class AuthService:
|
||||
if not new_pwd and not new_username:
|
||||
return self.error("新用户名和新密码不能同时为空")
|
||||
|
||||
username_to_save = None
|
||||
if new_username is not None and new_username != "":
|
||||
if not isinstance(new_username, str) or len(new_username.strip()) < 3:
|
||||
return self.error("用户名长度至少3位")
|
||||
username_to_save = new_username.strip()
|
||||
|
||||
if new_pwd:
|
||||
if not isinstance(new_pwd, str):
|
||||
return self.error("新密码无效")
|
||||
@@ -384,8 +390,8 @@ class AuthService:
|
||||
await set_password_change_required(self.db, self.config, False)
|
||||
if is_totp_enabled(self.config):
|
||||
await revoke_user_trusted_devices(self.db)
|
||||
if new_username:
|
||||
self.config["dashboard"]["username"] = new_username
|
||||
if username_to_save:
|
||||
self.config["dashboard"]["username"] = username_to_save
|
||||
|
||||
self.config.save_config()
|
||||
|
||||
|
||||
@@ -1,35 +1,41 @@
|
||||
## What's Changed
|
||||
## [4.26.5] - 2026-07-07
|
||||
|
||||
- feat(platform): 支持扫码创建时自定义机器人ID (#9067) (9f50c900b)
|
||||
- fix: enable only synced ModelScope MCP servers (#9084) (89b80a6ca)
|
||||
- feat: add ChatUI project workspaces (#9066) (e7d5be632)
|
||||
- fix: Improve MCP client startup and shutdown handling to prevent idle spinning when a server is disabled and ensure proper cleanup on errors, timeouts, and cancellation (#9070) (3ce66576f)
|
||||
- fix(kb): replace fragile error string matching with pre-check for duplicate kb_name (#9121) (aecee6fc9)
|
||||
- fix(kb): improve retrieval resilience on per-KB failure and rerank selection (#9122) (468eea99c)
|
||||
- fix(kb): clean up KBMedia records on document delete, fix update_kb_stats (#9120) (e2f3b0008)
|
||||
- fix: align knowledge base CRUD API contract with kb_name, canonical payload fields, and matching OpenAPI types (#9000) (ea9e3421d)
|
||||
- fix: constrain custom workspace paths (6d798908a)
|
||||
- fix(core): improve web search API key failover (8a31cf01f)
|
||||
- fix: preserve absolute custom workspace paths (20008f179)
|
||||
- feat: improve ChatUI attachment display (#9134) (b43cc6dee)
|
||||
- fix: enforce ownership when reading ChatUI sessions (#9141) (041fba4df)
|
||||
- fix: secure project update temp staging (#9083) (30426c4f6)
|
||||
- fix: qq_official websocket适配器发送消息收到None时现在会重试了 (#8977) (#8979) (cc0b34750)
|
||||
- fix: adapt MiMo STT to V2.5 models and reject non-WAV audio payloads (#9118) (c9eed7b65)
|
||||
- feat: add note on cross-platform compatibility and Python version support (85b653b6f)
|
||||
- test: cover POSIX file URI root preservation (#8906) (3b8caf37e)
|
||||
- feat: add sanitation for malformed tool call names in ToolLoopAgentRunner (#9144) (25cbd41e0)
|
||||
- feat: show model metadata in selectors (6627fd53c)
|
||||
- fix: keep model metadata separate from providers (#9161) (18e067fab)
|
||||
- fix: serialize webchat history timestamps as UTC-aware ISO strings (#9159) (56326c755)
|
||||
- feat: add chat token usage indicator (ab2502c17)
|
||||
- fix(webui): sync plugin activation status on enable (#9156) (ba7f8ebfb)
|
||||
- fix: preserve qq official quoted message context (#9164) (4166d9ab5)
|
||||
- fix: exit MCP anyio contexts in the lifecycle task on disable (#9132) (afb007911)
|
||||
- fix(mcp): attempt to fix epoll busy-wait caused by leaked SSE exit stack (#8307) (56f253395)
|
||||
- fix: remove qq official reply id on proactive fallback so oversized passive replies can succeed via proactive sending (#9169) (2a7c02af8)
|
||||
- feat: add event loop diagnostics (#9168) (0dee40bd9)
|
||||
- docs: add diagnostics guide (0a5d6485a)
|
||||
- chore: log event loop watchdog startup at info (510e83369)
|
||||
- docs: broaden diagnostics guide (1124dfe29)
|
||||
- style: polish snackbar appearance (#9173) (bf18fadbe)
|
||||
### Added
|
||||
|
||||
- Added support for setting a custom bot ID while creating a platform by scanning a QR code. (#9067)
|
||||
- Added ChatUI project workspaces. (#9066)
|
||||
- Added improved ChatUI attachment display. (#9134)
|
||||
- Added malformed tool-call name sanitation in `ToolLoopAgentRunner`. (#9144)
|
||||
- Added model metadata in selectors and a chat token usage indicator. (#9161)
|
||||
- Added event-loop diagnostics and expanded diagnostics documentation. (#9168)
|
||||
- Added documentation for cross-platform compatibility and Python version support.
|
||||
- Added test coverage for POSIX file URI root preservation. (#8906)
|
||||
|
||||
### Changed
|
||||
|
||||
- Log event-loop watchdog startup at the info level.
|
||||
- Keep model metadata separate from providers. (#9161)
|
||||
- Polish snackbar styling in the WebUI. (#9173)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Enabled only synced ModelScope MCP servers. (#9084)
|
||||
- Improved MCP client startup and shutdown handling to avoid idle spinning and clean up on errors, timeouts, and cancellation. (#9070)
|
||||
- Replaced fragile knowledge-base duplicate-name error matching with a pre-check. (#9121)
|
||||
- Improved knowledge-base retrieval resilience on per-knowledge-base failures and rerank selection. (#9122)
|
||||
- Cleaned up `KBMedia` records on document deletion and fixed knowledge-base stats updates. (#9120)
|
||||
- Aligned the knowledge-base CRUD API contract with `kb_name`, canonical payload fields, and OpenAPI types. (#9000)
|
||||
- Constrained custom workspace paths and preserved absolute custom workspace paths.
|
||||
- Improved web search API key failover.
|
||||
- Enforced ownership when reading ChatUI sessions. (#9141)
|
||||
- Secured project update temporary staging. (#9083)
|
||||
- Improved QQ Official retry behavior when websocket send returns `None`. (#8977)
|
||||
- Preserved QQ Official quoted message context. (#9164)
|
||||
- Removed QQ Official reply IDs on proactive fallback so oversized passive replies can succeed via proactive sending. (#9169)
|
||||
- Adapted MiMo STT to V2.5 models and rejected non-WAV audio payloads. (#9118)
|
||||
- Serialized webchat history timestamps as UTC-aware ISO strings. (#9159)
|
||||
- Synced plugin activation status on enable in the WebUI. (#9156)
|
||||
- Exited MCP `anyio` contexts in the lifecycle task on disable. (#9132)
|
||||
- Fixed leaked SSE exit stack handling that could cause MCP epoll busy-wait. (#8307)
|
||||
|
||||
[4.26.5]: https://github.com/AstrBotDevs/AstrBot/compare/v4.26.4...v4.26.5
|
||||
|
||||
@@ -1360,6 +1360,105 @@ async def test_generated_password_requires_password_change_until_changed(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
("endpoint", "method"),
|
||||
[
|
||||
("/api/auth/account/edit", "post"),
|
||||
("/api/v1/auth/account", "patch"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("new_username", ["ab", " "])
|
||||
async def test_account_edit_rejects_invalid_username(
|
||||
app: FastAPIAppAdapter,
|
||||
core_lifecycle_td: AstrBotCoreLifecycle,
|
||||
endpoint: str,
|
||||
method: str,
|
||||
new_username: str,
|
||||
):
|
||||
original_dashboard_config = copy.deepcopy(
|
||||
core_lifecycle_td.astrbot_config["dashboard"]
|
||||
)
|
||||
test_client = app.test_client()
|
||||
current_username = core_lifecycle_td.astrbot_config["dashboard"]["username"]
|
||||
current_password = _resolve_dashboard_password(core_lifecycle_td)
|
||||
|
||||
try:
|
||||
login_response = await test_client.post(
|
||||
"/api/auth/login",
|
||||
json={"username": current_username, "password": current_password},
|
||||
)
|
||||
login_data = await login_response.get_json()
|
||||
assert login_data["status"] == "ok"
|
||||
headers = {"Authorization": f"Bearer {login_data['data']['token']}"}
|
||||
|
||||
payload = {
|
||||
"password": current_password,
|
||||
"new_password": "",
|
||||
"confirm_password": "",
|
||||
"new_username": new_username,
|
||||
}
|
||||
request = getattr(test_client, method)
|
||||
response = await request(endpoint, headers=headers, json=payload)
|
||||
data = await response.get_json()
|
||||
|
||||
assert data["status"] == "error"
|
||||
assert data["message"] == "用户名长度至少3位"
|
||||
assert (
|
||||
core_lifecycle_td.astrbot_config["dashboard"]["username"]
|
||||
== (original_dashboard_config["username"])
|
||||
)
|
||||
finally:
|
||||
await _restore_dashboard_password_state(
|
||||
core_lifecycle_td,
|
||||
original_dashboard_config,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_account_edit_trims_valid_username(
|
||||
app: FastAPIAppAdapter,
|
||||
core_lifecycle_td: AstrBotCoreLifecycle,
|
||||
):
|
||||
original_dashboard_config = copy.deepcopy(
|
||||
core_lifecycle_td.astrbot_config["dashboard"]
|
||||
)
|
||||
test_client = app.test_client()
|
||||
current_username = core_lifecycle_td.astrbot_config["dashboard"]["username"]
|
||||
current_password = _resolve_dashboard_password(core_lifecycle_td)
|
||||
|
||||
try:
|
||||
login_response = await test_client.post(
|
||||
"/api/auth/login",
|
||||
json={"username": current_username, "password": current_password},
|
||||
)
|
||||
login_data = await login_response.get_json()
|
||||
assert login_data["status"] == "ok"
|
||||
headers = {"Authorization": f"Bearer {login_data['data']['token']}"}
|
||||
|
||||
response = await test_client.post(
|
||||
"/api/auth/account/edit",
|
||||
headers=headers,
|
||||
json={
|
||||
"password": current_password,
|
||||
"new_password": "",
|
||||
"confirm_password": "",
|
||||
"new_username": " astrbot-admin ",
|
||||
},
|
||||
)
|
||||
data = await response.get_json()
|
||||
|
||||
assert data["status"] == "ok"
|
||||
assert core_lifecycle_td.astrbot_config["dashboard"]["username"] == (
|
||||
"astrbot-admin"
|
||||
)
|
||||
finally:
|
||||
await _restore_dashboard_password_state(
|
||||
core_lifecycle_td,
|
||||
original_dashboard_config,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_local_setup_can_skip_default_password_auth(
|
||||
app: FastAPIAppAdapter,
|
||||
|
||||
Reference in New Issue
Block a user