from __future__ import annotations import logging from yuxi.channel.extensions.feishu.client import get_client logger = logging.getLogger(__name__) FEISHU_WIKI_TOOLS = [ { "name": "feishu_wiki_spaces", "description": "列出飞书知识库空间", "parameters": {}, }, { "name": "feishu_wiki_nodes", "description": "列出知识库节点", "parameters": {"space_id": "知识空间 ID", "parent_node_token": "父节点 token(可选)"}, }, { "name": "feishu_wiki_get_node", "description": "获取知识库节点详情", "parameters": {"node_token": "节点 token"}, }, { "name": "feishu_wiki_create_node", "description": "创建知识库节点", "parameters": {"space_id": "空间 ID", "parent_node_token": "父节点 token", "title": "节点标题", "obj_type": "类型(docx/sheet/bitable)"}, }, { "name": "feishu_wiki_update_node", "description": "更新知识库节点", "parameters": {"space_id": "空间 ID", "node_token": "节点 token", "title": "新标题"}, }, { "name": "feishu_wiki_move_node", "description": "移动知识库节点", "parameters": {"space_id": "空间 ID", "node_token": "节点 token", "target_parent_token": "目标父节点 token"}, }, { "name": "feishu_wiki_delete_node", "description": "删除知识库节点", "parameters": {"node_token": "节点 token"}, }, ] async def list_wiki_spaces( app_id: str, app_secret: str, domain: str, http_timeout_ms: int = 30000, ) -> dict: try: client = get_client(app_id, app_secret, domain, http_timeout_ms) import lark_oapi req = lark_oapi.wiki.v2.ListSpaceRequest(page_size=50) resp = await client.wiki.v2.space.list_async(req) if resp.success() and resp.data: items = getattr(resp.data, "items", []) or [] return { "success": True, "spaces": [ { "space_id": getattr(s, "space_id", ""), "name": getattr(s, "name", ""), "description": getattr(s, "description", ""), } for s in items ], } else: return {"success": False, "error": getattr(resp, "msg", "")} except ImportError: return {"success": False, "error": "lark-oapi SDK not installed"} except Exception: logger.exception("Feishu list_wiki_spaces error") return {"success": False, "error": "Internal error"} async def list_wiki_nodes( app_id: str, app_secret: str, domain: str, space_id: str, parent_node_token: str = "", http_timeout_ms: int = 30000, ) -> dict: try: client = get_client(app_id, app_secret, domain, http_timeout_ms) import lark_oapi req = lark_oapi.wiki.v2.ListSpaceNodeRequest( space_id=space_id, parent_node_token=parent_node_token if parent_node_token else None, page_size=50, ) resp = await client.wiki.v2.space_node.list_async(req) if resp.success() and resp.data: items = getattr(resp.data, "items", []) or [] return { "success": True, "nodes": [ { "node_token": getattr(n, "node_token", ""), "title": getattr(n, "title", ""), "obj_type": getattr(n, "obj_type", ""), "obj_token": getattr(n, "obj_token", ""), "has_child": getattr(n, "has_child", False), } for n in items ], } else: return {"success": False, "error": getattr(resp, "msg", "")} except ImportError: return {"success": False, "error": "lark-oapi SDK not installed"} except Exception: logger.exception("Feishu list_wiki_nodes error") return {"success": False, "error": "Internal error"} async def get_wiki_node( app_id: str, app_secret: str, domain: str, node_token: str, http_timeout_ms: int = 30000, ) -> dict: try: client = get_client(app_id, app_secret, domain, http_timeout_ms) import lark_oapi req = lark_oapi.wiki.v2.GetNodeRequest(token=node_token) resp = await client.wiki.v2.node.get_async(req) if resp.success() and resp.data: node = resp.data.node return { "success": True, "node": { "node_token": getattr(node, "node_token", ""), "title": getattr(node, "title", ""), "obj_type": getattr(node, "obj_type", ""), "obj_token": getattr(node, "obj_token", ""), "space_id": getattr(node, "space_id", ""), }, } else: return {"success": False, "error": getattr(resp, "msg", "")} except ImportError: return {"success": False, "error": "lark-oapi SDK not installed"} except Exception: logger.exception("Feishu get_wiki_node error") return {"success": False, "error": "Internal error"} async def create_wiki_node( app_id: str, app_secret: str, domain: str, space_id: str, parent_node_token: str, title: str, obj_type: str = "docx", http_timeout_ms: int = 30000, ) -> dict: try: from yuxi.channel.extensions.feishu.tools.doc import create_doc doc_result = await create_doc(app_id, app_secret, domain, title, "", http_timeout_ms) if not doc_result.get("success"): return doc_result doc_token = doc_result.get("document_id", "") if not doc_token: return {"success": False, "error": "Failed to get document_id from created doc"} client = get_client(app_id, app_secret, domain, http_timeout_ms) import lark_oapi req = lark_oapi.wiki.v2.CreateSpaceNodeRequest( space_id=space_id, request_body=lark_oapi.wiki.v2.CreateSpaceNodeRequestBody( parent_node_token=parent_node_token, node_type="origin", origin_node_token=doc_token, title=title, ), ) resp = await client.wiki.v2.space_node.create_async(req) if resp.success() and resp.data: node = getattr(resp.data, "node", None) return { "success": True, "node_token": getattr(node, "node_token", "") if node else "", } else: return {"success": False, "error": getattr(resp, "msg", "")} except ImportError: return {"success": False, "error": "lark-oapi SDK not installed"} except Exception: logger.exception("Feishu create_wiki_node error") return {"success": False, "error": "Internal error"} async def update_wiki_node( app_id: str, app_secret: str, domain: str, space_id: str, node_token: str, title: str = "", http_timeout_ms: int = 30000, ) -> dict: try: client = get_client(app_id, app_secret, domain, http_timeout_ms) import lark_oapi req = lark_oapi.wiki.v2.UpdateSpaceNodeRequest( space_id=space_id, node_token=node_token, request_body=lark_oapi.wiki.v2.UpdateSpaceNodeRequestBody( title=title if title else None, ), ) resp = await client.wiki.v2.space_node.update_async(req) if resp.success(): return {"success": True} else: return {"success": False, "error": getattr(resp, "msg", "")} except ImportError: return {"success": False, "error": "lark-oapi SDK not installed"} except Exception: logger.exception("Feishu update_wiki_node error") return {"success": False, "error": "Internal error"} async def move_wiki_node( app_id: str, app_secret: str, domain: str, space_id: str, node_token: str, target_parent_token: str, http_timeout_ms: int = 30000, ) -> dict: try: client = get_client(app_id, app_secret, domain, http_timeout_ms) import lark_oapi req = lark_oapi.wiki.v2.MoveSpaceNodeRequest( space_id=space_id, node_token=node_token, request_body=lark_oapi.wiki.v2.MoveSpaceNodeRequestBody( target_parent_token=target_parent_token, ), ) resp = await client.wiki.v2.space_node.move_async(req) if resp.success(): return {"success": True} else: return {"success": False, "error": getattr(resp, "msg", "")} except ImportError: return {"success": False, "error": "lark-oapi SDK not installed"} except Exception: logger.exception("Feishu move_wiki_node error") return {"success": False, "error": "Internal error"} async def delete_wiki_node( app_id: str, app_secret: str, domain: str, node_token: str, http_timeout_ms: int = 30000, ) -> dict: try: client = get_client(app_id, app_secret, domain, http_timeout_ms) import lark_oapi req = lark_oapi.wiki.v2.DeleteSpaceNodeRequest(token=node_token) resp = await client.wiki.v2.space_node.delete_async(req) if resp.success(): return {"success": True} else: return {"success": False, "error": getattr(resp, "msg", "")} except ImportError: return {"success": False, "error": "lark-oapi SDK not installed"} except Exception: logger.exception("Feishu delete_wiki_node error") return {"success": False, "error": "Internal error"}