feat(toolset): 工具系统重构为 toolset 统一管理,新增系统预置工具集
将工具管理从"agent 挂单个 tool"改为"agent 挂 toolset"模式: - 三个系统预置工具集(system_basic/system_chat/system_workflow)入 DB - 新增 send_file 工具(系统对话工具集)、修复 approval actor 调用 bug - 后端 agent 加载全部走 toolset 链路,移除 load_tools_from_list - 前端工具集中心卡片展示 + agent 配置改为 toolset 多选 - resource API 增加 category 过滤与系统 toolset 保护 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -35,7 +35,7 @@ class AgentRegister(BaseModel):
|
||||
provider_title: str
|
||||
model_id: str
|
||||
individual_name: str
|
||||
tools: Optional[List[str]] = None
|
||||
toolsets: Optional[List[str]] = None
|
||||
persona_id: Optional[str] = None
|
||||
display_name: Optional[str] = None
|
||||
|
||||
@@ -45,7 +45,7 @@ class AgentLocalRegister(BaseModel):
|
||||
|
||||
path: str
|
||||
individual_name: str
|
||||
tools: Optional[List[str]] = None
|
||||
toolsets: Optional[List[str]] = None
|
||||
|
||||
|
||||
@agent_router.get("")
|
||||
@@ -78,13 +78,15 @@ async def load_agent(
|
||||
agent_register.individual_name,
|
||||
agent_register.provider_title,
|
||||
agent_register.model_id,
|
||||
agent_register.tools,
|
||||
agent_register.toolsets,
|
||||
agent_register.persona_id,
|
||||
agent_register.display_name,
|
||||
)
|
||||
|
||||
scope = agent_register.individual_name
|
||||
toolsets = await get_all_toolsets_for_scope(scope)
|
||||
toolsets = await get_all_toolsets_for_scope(
|
||||
scope, toolset_ids=agent_register.toolsets
|
||||
)
|
||||
|
||||
# Resolve persona system_prompt from DB
|
||||
persona_prompt = None
|
||||
@@ -100,7 +102,6 @@ async def load_agent(
|
||||
global_state_machine,
|
||||
agent_register.provider_title,
|
||||
agent_register.model_id,
|
||||
agent_register.tools,
|
||||
toolsets,
|
||||
accept_lang,
|
||||
persona_prompt,
|
||||
@@ -111,7 +112,6 @@ async def load_agent(
|
||||
global_state_machine,
|
||||
agent_register.provider_title,
|
||||
agent_register.model_id,
|
||||
agent_register.tools,
|
||||
toolsets,
|
||||
accept_lang,
|
||||
persona_prompt,
|
||||
@@ -140,7 +140,7 @@ class WorkerIndividualCreate(BaseModel):
|
||||
output_template: dict
|
||||
bound_skill: Dict[str, List[str]]
|
||||
workspace: List[str]
|
||||
tools: Optional[List[str]] = None
|
||||
toolsets: Optional[List[str]] = None
|
||||
node_affinity: str = "cpu"
|
||||
|
||||
@field_validator("node_affinity")
|
||||
@@ -163,7 +163,7 @@ class WorkerIndividualUpdate(BaseModel):
|
||||
output_template: Optional[dict] = None
|
||||
bound_skill: Optional[Dict[str, List[str]]] = None
|
||||
workspace: Optional[List[str]] = None
|
||||
tools: Optional[List[str]] = None
|
||||
toolsets: Optional[List[str]] = None
|
||||
node_affinity: Optional[str] = None
|
||||
|
||||
@field_validator("node_affinity")
|
||||
|
||||
@@ -290,16 +290,22 @@ async def create_custom_toolset(
|
||||
|
||||
@resource_router.get("/custom-toolset")
|
||||
async def list_custom_toolsets(
|
||||
category: Optional[str] = None,
|
||||
token_data: TokenData = Depends(RoleChecker(allowed_roles=UserAuthority.USER)),
|
||||
):
|
||||
"""列出工具组:USER 只能看到自己的;ADMIN 及以上可看全部。"""
|
||||
"""列出工具组:支持按 category 过滤。USER 只能看到自己的+系统的;ADMIN 看全部。"""
|
||||
from kilostar.utils.check_user.role_check import get_authority
|
||||
|
||||
global_state_machine = ray_actor_hook("global_state_machine").global_state_machine
|
||||
toolsets = await global_state_machine.list_custom_toolsets.remote()
|
||||
authority = await get_authority(token_data.user_id)
|
||||
if authority < UserAuthority.ADMINISTRATOR:
|
||||
toolsets = [t for t in toolsets if t.get("owner_id") == token_data.user_id]
|
||||
toolsets = [
|
||||
t for t in toolsets
|
||||
if t.get("is_system") or t.get("owner_id") == token_data.user_id
|
||||
]
|
||||
if category:
|
||||
toolsets = [t for t in toolsets if t.get("category") == category]
|
||||
return {"toolsets": toolsets}
|
||||
|
||||
|
||||
@@ -326,6 +332,8 @@ async def update_custom_toolset(
|
||||
existing = await global_state_machine.get_custom_toolset.remote(toolset_id)
|
||||
if not existing:
|
||||
raise HTTPException(status_code=404, detail="Custom toolset not found")
|
||||
if existing.get("is_system"):
|
||||
raise HTTPException(status_code=403, detail="系统预置工具集不可修改")
|
||||
await _assert_toolset_owner_or_admin(existing, token_data)
|
||||
name = body.name if body.name is not None else existing["name"]
|
||||
tools = body.tools if body.tools is not None else existing["tools"]
|
||||
@@ -348,11 +356,13 @@ async def delete_custom_toolset(
|
||||
toolset_id: str,
|
||||
token_data: TokenData = Depends(RoleChecker(allowed_roles=UserAuthority.USER)),
|
||||
):
|
||||
"""删除工具组:USER 只能删自己的;ADMIN 及以上可删任意。"""
|
||||
"""删除工具组:系统预置不可删;USER 只能删自己的;ADMIN 及以上可删任意用户的。"""
|
||||
global_state_machine = ray_actor_hook("global_state_machine").global_state_machine
|
||||
existing = await global_state_machine.get_custom_toolset.remote(toolset_id)
|
||||
if not existing:
|
||||
raise HTTPException(status_code=404, detail="Custom toolset not found")
|
||||
if existing.get("is_system"):
|
||||
raise HTTPException(status_code=403, detail="系统预置工具集不可删除")
|
||||
await _assert_toolset_owner_or_admin(existing, token_data)
|
||||
ok = await global_state_machine.delete_custom_toolset.remote(toolset_id)
|
||||
if not ok:
|
||||
|
||||
Reference in New Issue
Block a user