feat: 添加MinIO文件系统支持并优化外部连接器功能

- 添加MinIO用户文件系统配置选项(BEAVER_MINIO_ROOT_USER等)
- 更新外部连接器配置结构,包括BASE_URL和认证令牌设置
- 改进connector provider支持更多类型(official, feishu_bot等)
- 实现Mistral模型推理模式支持reasoning_effort参数
- 增强外部连接器策略配置和运行时配置管理
- 添加connector bridge事件验证和安全保护机制
- 优化任务路由逻辑,区分simple_chat和new_task场景
- 更新初始技能工具提示配置,分离authoring admin功能
This commit is contained in:
2026-06-05 11:46:40 +08:00
parent 236ac19789
commit 2c5205b06e
120 changed files with 8321 additions and 1865 deletions

View File

@ -1,6 +1,7 @@
from __future__ import annotations
import json
import subprocess
from urllib.parse import parse_qs
from external_connector.app import create_app
@ -12,6 +13,17 @@ from external_connector.state import SidecarStateStore
from fastapi.testclient import TestClient
def test_feishu_node_event_utils() -> None:
result = subprocess.run(
["node", "--test", "tests/node/feishu_event_utils.test.js"],
check=False,
capture_output=True,
text=True,
)
assert result.returncode == 0, result.stdout + result.stderr
class FakeResponse:
def __init__(self, payload: dict[str, object]) -> None:
self.payload = payload
@ -169,6 +181,36 @@ def test_feishu_bot_provider_connects_with_app_credentials(tmp_path) -> None:
assert receiver_starts == ["conn_1"]
def test_feishu_bot_provider_stores_runtime_policy_options(tmp_path) -> None:
receiver_starts: list[str] = []
provider = _provider(tmp_path, receiver_starts=receiver_starts)
session = provider.start_session(
{
"kind": "feishu",
"connectionId": "conn_1",
"channelId": "feishu-main",
"displayName": "Feishu Main",
"callbackBaseUrl": "http://beaver:8080",
"options": {
"appId": "cli_xxx",
"appSecret": "secret",
"verificationToken": "verify-token",
"requireMentionInGroups": True,
"allowFrom": ["ou_1"],
"groupAllowFrom": ["oc_1"],
"maxMessageChars": 1234,
},
}
)
stored = provider.store.get_session(session["sessionId"])
assert stored.metadata["requireMentionInGroups"] is True
assert stored.metadata["allowFrom"] == ["ou_1"]
assert stored.metadata["groupAllowFrom"] == ["oc_1"]
assert stored.metadata["maxMessageChars"] == 1234
def test_feishu_bot_provider_send_uses_tenant_token_and_dedupes(tmp_path) -> None:
provider = _provider(tmp_path)
session = provider.start_session(
@ -205,13 +247,96 @@ def test_feishu_bot_provider_send_uses_tenant_token_and_dedupes(tmp_path) -> Non
assert send_posts[0][1]["msg_type"] == "text"
def test_feishu_event_route_returns_challenge(tmp_path) -> None:
def test_feishu_bot_provider_send_uses_chat_id_for_group_targets(tmp_path) -> None:
provider = _provider(tmp_path)
provider.start_session(
{
"kind": "feishu",
"connectionId": "conn_1",
"channelId": "feishu-main",
"displayName": "Feishu Main",
"callbackBaseUrl": "http://beaver:8080",
"options": {"appId": "cli_xxx", "appSecret": "secret"},
}
)
result = provider.send(
{
"requestId": "out_group_1",
"connectionId": "conn_1",
"channelId": "feishu-main",
"kind": "feishu",
"target": {"peerId": "oc_group", "peerType": "group", "threadId": "oc_group"},
"content": "hello group",
"metadata": {},
}
)
send_posts = [item for item in provider.http.posts if "/open-apis/im/v1/messages" in item[0]]
assert result["ok"] is True
assert send_posts[-1][0].endswith("?receive_id_type=chat_id")
assert send_posts[-1][1]["receive_id"] == "oc_group"
def test_feishu_bot_provider_send_chunks_oversized_text(tmp_path) -> None:
provider = _provider(tmp_path)
session = provider.start_session(
{
"kind": "feishu",
"connectionId": "conn_1",
"channelId": "feishu-main",
"displayName": "Feishu Main",
"callbackBaseUrl": "http://beaver:8080",
"options": {"appId": "cli_xxx", "appSecret": "secret", "maxMessageChars": 5},
}
)
result = provider.send(
{
"requestId": "out_chunked",
"connectionId": "conn_1",
"channelId": "feishu-main",
"kind": "feishu",
"target": {"peerId": "ou_user", "peerType": "dm", "threadId": None},
"content": "helloworld!",
"metadata": {},
}
)
send_posts = [item for item in provider.http.posts if "/open-apis/im/v1/messages" in item[0]]
contents = [json.loads(item[1]["content"])["text"] for item in send_posts]
assert session["status"] == "connected"
assert result["ok"] is True
assert contents == ["hello", "world", "!"]
def test_feishu_event_route_requires_known_verification_token_for_challenge(tmp_path) -> None:
provider = _provider(tmp_path)
app = create_app(provider=provider, api_token="sidecar-token")
with TestClient(app) as client:
response = client.post("/feishu/events", json={"challenge": "abc"})
assert response.status_code == 401
def test_feishu_event_route_returns_challenge_for_matching_token(tmp_path) -> None:
provider = _provider(tmp_path)
provider.start_session(
{
"kind": "feishu",
"connectionId": "conn_1",
"channelId": "feishu-main",
"displayName": "Feishu Main",
"callbackBaseUrl": "http://beaver:8080",
"options": {"appId": "cli_xxx", "appSecret": "secret", "verificationToken": "verify-token"},
}
)
app = create_app(provider=provider, api_token="sidecar-token")
with TestClient(app) as client:
response = client.post("/feishu/events", json={"challenge": "abc", "token": "verify-token"})
assert response.status_code == 200
assert response.json() == {"challenge": "abc"}
@ -259,6 +384,62 @@ def test_feishu_event_route_forwards_message_to_bridge(tmp_path) -> None:
assert bridge_posts[0][1]["peerId"] == "ou_user"
def test_feishu_event_route_ignores_bot_sender_and_platform_commands(tmp_path) -> None:
bridge_posts: list[tuple[str, dict[str, object], dict[str, str]]] = []
provider = _provider(tmp_path, bridge_posts=bridge_posts)
provider.start_session(
{
"kind": "feishu",
"connectionId": "conn_1",
"channelId": "feishu-main",
"displayName": "Feishu Main",
"callbackBaseUrl": "http://beaver:8080",
"options": {"appId": "cli_xxx", "appSecret": "secret", "verificationToken": "verify-token"},
}
)
app = create_app(provider=provider, api_token="sidecar-token")
with TestClient(app) as client:
bot = client.post(
"/feishu/events",
json={
"header": {"event_id": "evt_bot", "token": "verify-token", "app_id": "cli_xxx"},
"event": {
"sender": {"sender_type": "bot", "sender_id": {"open_id": "ou_bot"}},
"message": {
"message_id": "om_bot",
"chat_id": "oc_chat",
"chat_type": "p2p",
"message_type": "text",
"content": "{\"text\":\"hello\"}",
},
},
},
)
command = client.post(
"/feishu/events",
json={
"header": {"event_id": "evt_command", "token": "verify-token", "app_id": "cli_xxx"},
"event": {
"sender": {"sender_type": "user", "sender_id": {"open_id": "ou_user"}},
"message": {
"message_id": "om_command",
"chat_id": "oc_chat",
"chat_type": "p2p",
"message_type": "text",
"content": "{\"text\":\"/feishu start\"}",
},
},
},
)
assert bot.status_code == 200
assert command.status_code == 200
assert bot.json() == {"ok": True, "ignored": "sender_type:bot"}
assert command.json() == {"ok": True, "ignored": "feishu_command"}
assert bridge_posts == []
def test_composite_provider_routes_feishu_and_weixin_descriptors(tmp_path) -> None:
store = SidecarStateStore(tmp_path / "state.json")
provider = CompositeProvider([FakeProvider(store), _provider(tmp_path)])