mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 06:58:14 +02:00
feat(mcp): outils MCP dans la boucle agent (dispatch async + notices)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
e09af9c9bb
commit
91e0a9f0b2
2 files changed
+34
-2
No files matched your search
+25
-1
@@ -81,15 +81,20 @@ async def run_agent(
|
|||||||
confirm_shell: bool = True,
|
confirm_shell: bool = True,
|
||||||
think: bool = True,
|
think: bool = True,
|
||||||
keep_alive: str | None = None,
|
keep_alive: str | None = None,
|
||||||
|
mcp_tools: list[dict] | None = None,
|
||||||
) -> AsyncIterator[dict]:
|
) -> AsyncIterator[dict]:
|
||||||
# enabled_tools=None -> tous les outils ; liste vide -> aucun outil.
|
# enabled_tools=None -> tous les outils ; liste vide -> aucun outil.
|
||||||
if enabled_tools is None:
|
if enabled_tools is None:
|
||||||
tools = TOOL_DEFINITIONS
|
tools = list(TOOL_DEFINITIONS)
|
||||||
elif enabled_tools:
|
elif enabled_tools:
|
||||||
tools = [
|
tools = [
|
||||||
t for t in TOOL_DEFINITIONS if t["function"]["name"] in enabled_tools
|
t for t in TOOL_DEFINITIONS if t["function"]["name"] in enabled_tools
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
|
tools = []
|
||||||
|
# Outils MCP des serveurs activés (déjà résolus par l'appelant).
|
||||||
|
tools.extend(mcp_tools or [])
|
||||||
|
if not tools:
|
||||||
tools = None
|
tools = None
|
||||||
collected: list[dict] = []
|
collected: list[dict] = []
|
||||||
text_parts: list[str] = []
|
text_parts: list[str] = []
|
||||||
@@ -289,6 +294,25 @@ async def run_agent(
|
|||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Outils MCP : dispatch asynchrone vers le serveur concerné.
|
||||||
|
if name.startswith("mcp_"):
|
||||||
|
from .mcp_client import manager as mcp_manager
|
||||||
|
mcp_res = await mcp_manager.call_tool(name, args)
|
||||||
|
status = "ok" if mcp_res["ok"] else "error"
|
||||||
|
record = {"name": name, "args": args,
|
||||||
|
"summary": mcp_res["summary"], "status": status}
|
||||||
|
collected.append(record)
|
||||||
|
yield {"type": "tool_result", **record}
|
||||||
|
convo.append({
|
||||||
|
"role": "tool",
|
||||||
|
"tool_name": name,
|
||||||
|
"content": json.dumps(
|
||||||
|
{"ok": mcp_res["ok"], "content": mcp_res["content"]},
|
||||||
|
ensure_ascii=False,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = run_tool(name, args)
|
result = run_tool(name, args)
|
||||||
summary = result.get("summary", "terminé")
|
summary = result.get("summary", "terminé")
|
||||||
|
|||||||
@@ -214,15 +214,22 @@ async def chat(req: ChatRequest) -> StreamingResponse:
|
|||||||
if want_rag or want_plan or use_code:
|
if want_rag or want_plan or use_code:
|
||||||
yield _sse("status", {"message": "Préparation du contexte…"})
|
yield _sse("status", {"message": "Préparation du contexte…"})
|
||||||
|
|
||||||
memories, plan, code_model = await asyncio.gather(
|
from ..mcp_client import manager as mcp_manager
|
||||||
|
|
||||||
|
memories, plan, code_model, mcp_tools = await asyncio.gather(
|
||||||
rag.recall(req.session_id, req.content, embed_model=cfg.get("embed_model"))
|
rag.recall(req.session_id, req.content, embed_model=cfg.get("embed_model"))
|
||||||
if want_rag else asyncio.sleep(0, result=[]),
|
if want_rag else asyncio.sleep(0, result=[]),
|
||||||
enhance.make_plan(model, req.content, options=run_opts, keep_alive=keep)
|
enhance.make_plan(model, req.content, options=run_opts, keep_alive=keep)
|
||||||
if want_plan else asyncio.sleep(0, result=[]),
|
if want_plan else asyncio.sleep(0, result=[]),
|
||||||
coder.pick_code_model(model, cfg.get("code_model"))
|
coder.pick_code_model(model, cfg.get("code_model"))
|
||||||
if use_code else asyncio.sleep(0, result=model),
|
if use_code else asyncio.sleep(0, result=model),
|
||||||
|
mcp_manager.tool_definitions(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Pannes MCP éventuelles : notice non bloquante dans le fil.
|
||||||
|
for mcp_notice in mcp_manager.notices():
|
||||||
|
yield _sse("notice", {"message": mcp_notice})
|
||||||
|
|
||||||
if memories:
|
if memories:
|
||||||
convo.insert(1, {
|
convo.insert(1, {
|
||||||
"role": "system",
|
"role": "system",
|
||||||
@@ -279,6 +286,7 @@ async def chat(req: ChatRequest) -> StreamingResponse:
|
|||||||
confirm_shell=cfg.get("confirm_shell", True),
|
confirm_shell=cfg.get("confirm_shell", True),
|
||||||
think=cfg.get("think", True),
|
think=cfg.get("think", True),
|
||||||
keep_alive=cfg.get("keep_alive", "30m"),
|
keep_alive=cfg.get("keep_alive", "30m"),
|
||||||
|
mcp_tools=mcp_tools,
|
||||||
):
|
):
|
||||||
await queue.put(event)
|
await queue.put(event)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
Reference in new issue
Block a user