wx-agent/tools/wiki_tools.py

140 lines
4.7 KiB
Python

from typing import Any, Dict, Optional
from langchain_core.tools import tool
from wiki_engine.service import (
delete_by_file,
delete_by_kb,
diff_kb,
evidence_search,
get_stats,
reconcile_kb,
resolve_kb_reference,
search_wiki,
sync_file,
sync_kb,
)
async def wiki_pointer_search(
query: str,
kb_id: Optional[str] = None,
limit: int = 5,
) -> Dict[str, Any]:
"""Search local Wiki pointer pages and return related 11000 slice ids."""
if not query or not query.strip():
return {"success": False, "error": "query is empty", "items": []}
return await search_wiki(query=query.strip(), kb_id=kb_id, limit=limit, include_slices=True)
async def wiki_evidence_search(
query: str,
kb_id: Optional[str] = None,
limit: int = 5,
) -> Dict[str, Any]:
"""Return Wiki results in the unified evidence-like format."""
if not query or not query.strip():
return {"success": False, "error": "query is empty", "items": []}
return await evidence_search(query=query.strip(), kb_id=kb_id, limit=limit)
async def wiki_admin_stats() -> Dict[str, Any]:
return {"success": True, "stats": await get_stats()}
async def wiki_admin_sync_file(file_id: str, kb_id: Optional[str] = None, use_llm: bool = False) -> Dict[str, Any]:
return await sync_file(file_id=file_id, kb_id=kb_id, use_llm=use_llm)
async def wiki_admin_sync_kb(
kb_id: Optional[str] = None,
kb_name: Optional[str] = None,
limit: int = 20,
use_llm: bool = False,
) -> Dict[str, Any]:
target = await _resolve_kb_target(kb_id=kb_id, kb_name=kb_name)
if not target.get("success"):
return target
result = await sync_kb(kb_id=target["kb_id"], limit=limit, use_llm=use_llm)
result.update({"kb_name": target.get("kb_name", ""), "kb_path": target.get("kb_path", "")})
return result
async def wiki_admin_diff_kb(
kb_id: Optional[str] = None,
kb_name: Optional[str] = None,
include_children: bool = False,
limit: int = 200,
) -> Dict[str, Any]:
target = await _resolve_kb_target(kb_id=kb_id, kb_name=kb_name)
if not target.get("success"):
return target
result = await diff_kb(kb_id=target["kb_id"], include_children=include_children, limit=limit)
result.update({"kb_name": target.get("kb_name", ""), "kb_path": target.get("kb_path", "")})
return result
async def wiki_admin_reconcile_kb(
kb_id: Optional[str] = None,
kb_name: Optional[str] = None,
include_children: bool = False,
limit: int = 200,
sync_missing: bool = True,
rebuild_stale: bool = True,
delete_orphan: bool = False,
use_llm: bool = False,
dry_run: bool = True,
) -> Dict[str, Any]:
target = await _resolve_kb_target(kb_id=kb_id, kb_name=kb_name)
if not target.get("success"):
return target
result = await reconcile_kb(
kb_id=target["kb_id"],
include_children=include_children,
limit=limit,
sync_missing=sync_missing,
rebuild_stale=rebuild_stale,
delete_orphan=delete_orphan,
use_llm=use_llm,
dry_run=dry_run,
)
result.update({"kb_name": target.get("kb_name", ""), "kb_path": target.get("kb_path", "")})
return result
async def wiki_admin_delete_file(file_id: str) -> Dict[str, Any]:
return await delete_by_file(file_id)
async def wiki_admin_delete_kb(kb_id: Optional[str] = None, kb_name: Optional[str] = None) -> Dict[str, Any]:
target = await _resolve_kb_target(kb_id=kb_id, kb_name=kb_name)
if not target.get("success"):
return target
result = await delete_by_kb(target["kb_id"])
result.update({"kb_name": target.get("kb_name", ""), "kb_path": target.get("kb_path", "")})
return result
async def _resolve_kb_target(kb_id: Optional[str] = None, kb_name: Optional[str] = None) -> Dict[str, Any]:
if kb_id and str(kb_id).strip():
return {"success": True, "kb_id": str(kb_id).strip(), "kb_name": "", "kb_path": ""}
if kb_name and str(kb_name).strip():
return await resolve_kb_reference(str(kb_name).strip())
return {"success": False, "error": "kb_name is required", "matches": []}
@tool
async def wiki_pointer_search_tool(query: str, limit: int = 5) -> str:
"""Search Wiki pointer pages and format them for workflow prompts."""
result = await wiki_pointer_search(query=query, limit=limit)
if not result.get("success"):
return ""
parts = []
for item in result.get("items", []):
title = item.get("title", "")
summary = item.get("summary", "")
slice_ids = ", ".join(item.get("related_slice_ids", [])[:8])
if title or summary:
parts.append(f"[Wiki] {title}\n{summary}\nrelated_slice_ids: {slice_ids}")
return "\n\n".join(parts)