feat: 添加视觉设计语言系统并重构认证页面UI

- 新增 visual_design_language.md 设计规范文档
- 新增 auth 设计 tokens (authBackground, authCard, authInput, feedback 系列等)
- 重构登录/注册/验证码/重置密码页面为新设计系统
- 新增 AuthHeroHeader, AuthSurfaceCard, AuthSection, AuthField, PasswordField 组件
- 重构 AppBanner 和 Toast 支持多类型配置 (info/success/warning/error)
- 后端 AgentScope: 重整 schemas/prompts/tools 作用域, 新增协议文档
- 更新 AGENTS.md 集成视觉设计语言约束
This commit is contained in:
qzl
2026-03-13 14:10:13 +08:00
parent fb3c649db7
commit a10a2db27a
100 changed files with 6333 additions and 4800 deletions
+71 -115
View File
@@ -1,142 +1,95 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, cast
from uuid import UUID
from sqlalchemy.ext.asyncio import AsyncSession
from agentscope.tool import Toolkit
from agentscope.types import JSONSerializableObject
from core.agentscope.tools.custom.calendar import (
calendar_share,
calendar_read,
calendar_share,
calendar_write,
)
from core.agentscope.tools.custom.user_lookup import (
user_lookup,
from core.agentscope.tools.custom.user_lookup import user_lookup
from core.agentscope.tools.tool_config import (
TOOL_CONFIGS,
ToolGroup,
resolve_tool_names_by_groups,
)
from core.agentscope.tools.hitl_middleware import register_tool_middlewares
from core.agentscope.tools.tool_meta import TOOL_META
from core.agentscope.tools.tool_middleware import register_tool_middlewares
from sqlalchemy.ext.asyncio import AsyncSession
@dataclass(frozen=True)
class CustomToolBinding:
name: str
func: Any
preset_kwargs: dict[str, object]
@dataclass(frozen=True)
class ToolGroup:
stage: str
tool_names: frozenset[str]
TOOL_GROUPS: dict[str, ToolGroup] = {
"intent": ToolGroup(stage="intent", tool_names=frozenset({"calendar_read"})),
"execution": ToolGroup(
stage="execution",
tool_names=frozenset(
{
"calendar_read",
"calendar_write",
"calendar_share",
"user_lookup",
}
),
),
"report": ToolGroup(stage="report", tool_names=frozenset()),
TOOL_FUNCTIONS: dict[str, Any] = {
"calendar_read": calendar_read,
"calendar_write": calendar_write,
"calendar_share": calendar_share,
"user_lookup": user_lookup,
}
def get_tool_group(stage: str) -> ToolGroup:
group = TOOL_GROUPS.get(stage)
if group is None:
raise ValueError(f"unknown tool group stage: {stage}")
return group
STAGE_TO_GROUPS: dict[str, set[ToolGroup]] = {
"intent": {ToolGroup.READ},
"execution": {ToolGroup.READ, ToolGroup.WRITE},
"report": set(),
}
def _load_custom_tool_bindings(
def _resolve_enabled_tools(
*,
session: AsyncSession,
owner_id: UUID,
user_token: str | None,
) -> list[CustomToolBinding]:
return [
CustomToolBinding(
name="calendar_read",
func=calendar_read,
preset_kwargs={
"session": session,
"owner_id": owner_id,
"user_token": user_token or "",
},
),
CustomToolBinding(
name="calendar_write",
func=calendar_write,
preset_kwargs={
"session": session,
"owner_id": owner_id,
"user_token": user_token or "",
},
),
CustomToolBinding(
name="calendar_share",
func=calendar_share,
preset_kwargs={
"session": session,
"owner_id": owner_id,
"user_token": user_token or "",
},
),
CustomToolBinding(
name="user_lookup",
func=user_lookup,
preset_kwargs={
"session": session,
"owner_id": owner_id,
"user_token": user_token or "",
},
),
]
groups: set[ToolGroup] | None,
enabled_tool_names: set[str] | None,
) -> set[str]:
if enabled_tool_names is not None:
unknown = enabled_tool_names - set(TOOL_FUNCTIONS)
if unknown:
raise ValueError(f"unknown tools in enabled_tool_names: {sorted(unknown)}")
return set(enabled_tool_names)
if groups is None:
return set(TOOL_FUNCTIONS)
resolved = resolve_tool_names_by_groups(groups)
unknown = resolved - set(TOOL_FUNCTIONS)
if unknown:
raise ValueError(f"tool config contains unknown tools: {sorted(unknown)}")
return resolved
def build_toolkit(
*,
session: AsyncSession,
owner_id: UUID,
user_token: str | None = None,
enable_hitl: bool = True,
groups: set[ToolGroup] | None = None,
enabled_tool_names: set[str] | None = None,
enable_hitl: bool | None = None,
enable_approval_layer: bool = True,
):
from agentscope.tool import Toolkit
from agentscope.types import JSONSerializableObject
toolkit = Toolkit()
bindings = _load_custom_tool_bindings(
session=session,
owner_id=owner_id,
user_token=user_token,
enabled_names = _resolve_enabled_tools(
groups=groups,
enabled_tool_names=enabled_tool_names,
)
registered_tool_names: set[str] = set()
for binding in bindings:
if enabled_tool_names is not None and binding.name not in enabled_tool_names:
continue
registered_tool_names.add(binding.name)
preset_kwargs = cast(
dict[str, JSONSerializableObject],
{
"session": session,
"owner_id": owner_id,
},
)
for tool_name in sorted(enabled_names):
tool_func = TOOL_FUNCTIONS[tool_name]
toolkit.register_tool_function(
binding.func,
func_name=binding.name,
preset_kwargs=cast(
dict[str, JSONSerializableObject],
binding.preset_kwargs,
),
tool_func,
func_name=tool_name,
preset_kwargs=preset_kwargs,
)
if enabled_tool_names is not None:
missing = enabled_tool_names - registered_tool_names
if missing:
raise ValueError(f"unknown tools in enabled_tool_names: {sorted(missing)}")
if enable_hitl:
register_tool_middlewares(toolkit=toolkit, meta_by_name=TOOL_META)
approval_enabled = enable_approval_layer if enable_hitl is None else enable_hitl
if approval_enabled:
register_tool_middlewares(toolkit=toolkit, config_by_name=TOOL_CONFIGS)
return toolkit
@@ -145,14 +98,17 @@ def build_stage_toolkit(
stage: str,
session: AsyncSession,
owner_id: UUID,
user_token: str | None = None,
enable_hitl: bool = True,
enable_hitl: bool | None = None,
enable_approval_layer: bool = True,
):
group = get_tool_group(stage)
groups = STAGE_TO_GROUPS.get(stage)
if groups is None:
raise ValueError(f"unknown stage: {stage}")
return build_toolkit(
session=session,
owner_id=owner_id,
user_token=user_token,
groups=set(groups),
enable_hitl=enable_hitl,
enabled_tool_names=set(group.tool_names),
enable_approval_layer=enable_approval_layer,
)