Compare commits

...

6 Commits

Author SHA1 Message Date
Cooper
12f2f5a09c fix: Added Try Except to Filter Handling (#9183)
* Added Try Except to Filter Handling

* Avoid Redundant Error Processing
2026-07-09 15:48:52 +08:00
SpencerFang0617
afb898e61f fix(line): remove unexpected force argument from get_json (#9187) 2026-07-09 15:47:57 +08:00
Soulter
0be821afc6 chore: update readme 2026-07-08 00:39:31 +08:00
VectorPeak
dcc40ede1d fix: validate dashboard account username updates (#9175)
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
2026-07-08 00:27:52 +08:00
Soulter
adebd2958e chore: refine README
SengokuCola 必定女装
2026-07-07 22:00:19 +08:00
Soulter
331444b41f docs: update v4.26.5 changelog format 2026-07-07 10:12:25 +08:00
6 changed files with 179 additions and 76 deletions

View File

@@ -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 ☁️:
[![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)
### 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 ☁️:
[![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)
### 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

View File

@@ -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))

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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,