feat: organize tools and enable qwen realtime calls

This commit is contained in:
Xin Wang
2026-08-14 00:15:00 +08:00
parent eb111a3890
commit 5be21f5ccc
71 changed files with 5771 additions and 2026 deletions
+25 -9
View File
@@ -19,6 +19,7 @@ from models import (
RuntimeMcpServer,
RuntimeModelResource,
RuntimeTool,
RuntimeToolBinding,
)
from services.node_specs import graph_references, normalize_graph
from sqlalchemy import select
@@ -90,15 +91,21 @@ def _secret(resource: ModelResource | None, key: str, default: str = "") -> str:
return str((resource.secrets or {}).get(key) or default)
async def _bound_tool_ids(session: AsyncSession, assistant_id: str) -> list[str]:
async def _bound_tools(
session: AsyncSession,
assistant_id: str,
) -> list[RuntimeToolBinding]:
rows = (
await session.execute(
select(AssistantToolBinding.tool_id)
select(AssistantToolBinding)
.where(AssistantToolBinding.assistant_id == assistant_id)
.order_by(AssistantToolBinding.created_at, AssistantToolBinding.tool_id)
)
).scalars().all()
return [str(tool_id) for tool_id in rows]
return [
RuntimeToolBinding(tool_id=row.tool_id, **(row.config or {}))
for row in rows
]
def _startup_tool_ids(startup: dict | None) -> list[str]:
@@ -108,16 +115,24 @@ def _startup_tool_ids(startup: dict | None) -> list[str]:
for action in (startup or {}).get("actions") or []:
if not isinstance(action, dict):
continue
tool_id = str(action.get("tool_id") or action.get("toolId") or "").strip()
binding = action.get("tool_binding") or action.get("toolBinding") or {}
tool_id = str(binding.get("tool_id") or binding.get("toolId") or "").strip()
if tool_id and tool_id not in result:
result.append(tool_id)
return result
def _runtime_tool_ids(llm_tool_ids: list[str], startup: dict | None) -> list[str]:
def _runtime_tool_ids(
bindings: list[RuntimeToolBinding],
startup: dict | None,
) -> list[str]:
"""Merge both tool scopes without changing either scope's meaning."""
return list(dict.fromkeys([*llm_tool_ids, *_startup_tool_ids(startup)]))
return list(
dict.fromkeys(
[*(binding.tool_id for binding in bindings), *_startup_tool_ids(startup)]
)
)
async def _tools_for(
@@ -251,8 +266,8 @@ async def resolve_runtime_config(
if kb.status == "active"
}
llm_tool_ids = await _bound_tool_ids(session, assistant.id)
runtime_tool_ids = _runtime_tool_ids(llm_tool_ids, assistant.startup or {})
prompt_tool_bindings = await _bound_tools(session, assistant.id)
runtime_tool_ids = _runtime_tool_ids(prompt_tool_bindings, assistant.startup or {})
runtime_tools = await _tools_for(session, assistant, runtime_tool_ids)
return AssistantConfig(
@@ -267,8 +282,9 @@ async def resolve_runtime_config(
turnConfig=assistant.turn_config or {},
startup=assistant.startup or {},
analysis_config=assistant.analysis_config or {},
built_in_tools=assistant.built_in_tools or {},
tools=runtime_tools,
llm_tool_ids=llm_tool_ids,
tool_bindings=prompt_tool_bindings,
knowledge_base_id=assistant.knowledge_base_id,
knowledge_base_name=knowledge_base.name if knowledge_base else "",
knowledge_base_description=knowledge_base.description if knowledge_base else "",