refactor: 移除前端 Mock API,新增共享组件,优化认证流程
- 删除 mock_api_client、mock_calendar_service、mock_history_service - 新增 fixed_length_code_input、link_button、message_composer 共享组件 - 优化登录/注册/密码重置页面使用新组件 - 简化 injection.dart 移除 mock 分支 - 更新 env.dart 配置(BACKEND_URL 替换 API_URL) - 后端 agentscope 工具和测试更新 - 重构 AGENTS.md 文档结构 - 新增 deploy/ 目录和 protocol 文档
This commit is contained in:
@@ -16,13 +16,9 @@ async def test_calendar_read_returns_list_payload(
|
||||
) -> None:
|
||||
async def _fake_execute(**kwargs: Any) -> dict[str, object]:
|
||||
del kwargs
|
||||
return {"type": "calendar_event_list.v1", "version": "v1", "data": {}}
|
||||
return {"type": "calendar_event_list.v1", "version": "v1", "data": {"ok": True}}
|
||||
|
||||
monkeypatch.setattr(
|
||||
calendar_module,
|
||||
"_execute_list_calendar_events",
|
||||
_fake_execute,
|
||||
)
|
||||
monkeypatch.setattr(calendar_module, "_execute_list_calendar_events", _fake_execute)
|
||||
monkeypatch.setattr(calendar_module, "_verify_user_token", lambda **_: True)
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
|
||||
@@ -62,9 +58,7 @@ async def test_calendar_write_maps_event_id_for_update(
|
||||
return {"type": "calendar_card.v1", "version": "v1", "data": {"ok": True}}
|
||||
|
||||
monkeypatch.setattr(
|
||||
calendar_module,
|
||||
"_execute_mutate_calendar_event",
|
||||
_fake_execute,
|
||||
calendar_module, "_execute_mutate_calendar_event", _fake_execute
|
||||
)
|
||||
monkeypatch.setattr(calendar_module, "_verify_user_token", lambda **_: True)
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
@@ -82,57 +76,6 @@ async def test_calendar_write_maps_event_id_for_update(
|
||||
assert "eventId" in captured
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_write_requires_preset_user_token(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
monkeypatch.setattr(calendar_module, "_verify_user_token", lambda **_: False)
|
||||
result = await calendar_module.calendar_write(
|
||||
session=cast(AsyncSession, SimpleNamespace()),
|
||||
owner_id=uuid4(),
|
||||
user_token="bad-token",
|
||||
operation="create",
|
||||
)
|
||||
assert result["data"]["ok"] is False
|
||||
assert result["data"]["code"] == "UNAUTHORIZED"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_write_rejects_missing_event_id_for_update(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
|
||||
result = await calendar_module.calendar_write(
|
||||
session=cast(AsyncSession, SimpleNamespace()),
|
||||
owner_id=uuid4(),
|
||||
user_token="token-abc",
|
||||
operation="update",
|
||||
)
|
||||
|
||||
assert result["data"]["ok"] is False
|
||||
assert result["data"]["code"] == "INVALID_ARGUMENT"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_write_rejects_event_id_for_create(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
|
||||
result = await calendar_module.calendar_write(
|
||||
session=cast(AsyncSession, SimpleNamespace()),
|
||||
owner_id=uuid4(),
|
||||
user_token="token-abc",
|
||||
operation="create",
|
||||
event_id=str(uuid4()),
|
||||
)
|
||||
|
||||
assert result["data"]["ok"] is False
|
||||
assert result["data"]["code"] == "INVALID_ARGUMENT"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_write_maps_reminder_minutes(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
@@ -144,9 +87,7 @@ async def test_calendar_write_maps_reminder_minutes(
|
||||
return {"type": "calendar_card.v1", "version": "v1", "data": {"ok": True}}
|
||||
|
||||
monkeypatch.setattr(
|
||||
calendar_module,
|
||||
"_execute_mutate_calendar_event",
|
||||
_fake_execute,
|
||||
calendar_module, "_execute_mutate_calendar_event", _fake_execute
|
||||
)
|
||||
monkeypatch.setattr(calendar_module, "_verify_user_token", lambda **_: True)
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
@@ -163,46 +104,54 @@ async def test_calendar_write_maps_reminder_minutes(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_write_rejects_invalid_reminder_minutes(
|
||||
async def test_calendar_write_returns_failed_tool_response_on_error(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
async def _fake_execute(**kwargs: Any) -> dict[str, object]:
|
||||
del kwargs
|
||||
raise ValueError("eventId is required")
|
||||
|
||||
monkeypatch.setattr(
|
||||
calendar_module, "_execute_mutate_calendar_event", _fake_execute
|
||||
)
|
||||
monkeypatch.setattr(calendar_module, "_verify_user_token", lambda **_: True)
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
|
||||
result = await calendar_module.calendar_write(
|
||||
session=cast(AsyncSession, SimpleNamespace()),
|
||||
owner_id=uuid4(),
|
||||
user_token="token-abc",
|
||||
operation="create",
|
||||
reminder_minutes=10081,
|
||||
operation="update",
|
||||
)
|
||||
|
||||
assert result["type"] == "calendar_operation.v1"
|
||||
assert result["data"]["ok"] is False
|
||||
assert result["data"]["code"] == "INVALID_ARGUMENT"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_calendar_write_maps_invite_arguments(
|
||||
async def test_calendar_share_maps_arguments(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
captured: dict[str, object] = {}
|
||||
|
||||
async def _fake_execute(**kwargs: Any) -> dict[str, object]:
|
||||
captured.update(cast(dict[str, object], kwargs["tool_args"]))
|
||||
return {"type": "calendar_card.v1", "version": "v1", "data": {"ok": True}}
|
||||
return {
|
||||
"type": "calendar_operation.v1",
|
||||
"version": "v1",
|
||||
"data": {"operation": "share", "ok": True},
|
||||
}
|
||||
|
||||
monkeypatch.setattr(
|
||||
calendar_module,
|
||||
"_execute_mutate_calendar_event",
|
||||
_fake_execute,
|
||||
)
|
||||
monkeypatch.setattr(calendar_module, "_execute_share_calendar_event", _fake_execute)
|
||||
monkeypatch.setattr(calendar_module, "_verify_user_token", lambda **_: True)
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
|
||||
await calendar_module.calendar_write(
|
||||
result = await calendar_module.calendar_share(
|
||||
session=cast(AsyncSession, SimpleNamespace()),
|
||||
owner_id=uuid4(),
|
||||
user_token="token-abc",
|
||||
operation="create",
|
||||
event_id=str(uuid4()),
|
||||
invite_user_emails=["a@example.com"],
|
||||
invite_user_names=["alice"],
|
||||
invite_user_ids=[str(uuid4())],
|
||||
@@ -211,6 +160,8 @@ async def test_calendar_write_maps_invite_arguments(
|
||||
invite_permission_invite=True,
|
||||
)
|
||||
|
||||
assert result["type"] == "calendar_operation.v1"
|
||||
assert captured["eventId"]
|
||||
assert captured["inviteUserEmails"] == ["a@example.com"]
|
||||
assert captured["inviteUserNames"] == ["alice"]
|
||||
assert isinstance(captured["inviteUserIds"], list)
|
||||
@@ -220,46 +171,18 @@ async def test_calendar_write_maps_invite_arguments(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_user_resolve_maps_identity_arguments(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
captured: dict[str, object] = {}
|
||||
|
||||
async def _fake_execute(**kwargs: Any) -> dict[str, object]:
|
||||
captured.update(cast(dict[str, object], kwargs["tool_args"]))
|
||||
return {"type": "user_lookup.v1", "version": "v1", "data": {"ok": True}}
|
||||
|
||||
monkeypatch.setattr(
|
||||
calendar_module,
|
||||
"_execute_resolve_user_identity",
|
||||
_fake_execute,
|
||||
)
|
||||
monkeypatch.setattr(calendar_module, "_verify_user_token", lambda **_: True)
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
|
||||
result = await calendar_module.user_resolve(
|
||||
session=cast(AsyncSession, SimpleNamespace()),
|
||||
owner_id=uuid4(),
|
||||
user_token="token-abc",
|
||||
user_email="a@example.com",
|
||||
)
|
||||
|
||||
assert result["type"] == "user_lookup.v1"
|
||||
assert captured == {"userEmail": "a@example.com", "userName": None}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_user_resolve_requires_valid_user_token(
|
||||
async def test_calendar_share_requires_valid_user_token(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.setattr(calendar_module, "_verify_user_token", lambda **_: False)
|
||||
monkeypatch.setattr(calendar_module, "build_tool_response", lambda payload: payload)
|
||||
|
||||
result = await calendar_module.user_resolve(
|
||||
result = await calendar_module.calendar_share(
|
||||
session=cast(AsyncSession, SimpleNamespace()),
|
||||
owner_id=uuid4(),
|
||||
user_token="bad-token",
|
||||
user_name="alice",
|
||||
event_id=str(uuid4()),
|
||||
invite_user_emails=["a@example.com"],
|
||||
)
|
||||
|
||||
assert result["data"]["ok"] is False
|
||||
|
||||
@@ -22,7 +22,7 @@ async def test_build_toolkit_registers_calendar_tools() -> None:
|
||||
names = {item["function"]["name"] for item in schemas}
|
||||
assert "calendar_read" in names
|
||||
assert "calendar_write" in names
|
||||
assert "user_resolve" in names
|
||||
assert "calendar_share" in names
|
||||
|
||||
write_schema = next(
|
||||
item for item in schemas if item["function"]["name"] == "calendar_write"
|
||||
|
||||
Reference in New Issue
Block a user