Fix Feishu wiki child node retrieval
This commit is contained in:
@@ -80,9 +80,17 @@ def _feishu_get(path: str, params: dict | None = None, config: FeishuRetrievalCo
|
||||
url = f"{FEISHU_OPEN_API}{path}"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
resp = httpx.get(url, headers=headers, params=params, timeout=config.timeout_seconds)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
try:
|
||||
resp = httpx.get(url, headers=headers, params=params, timeout=config.timeout_seconds)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
except httpx.HTTPStatusError as exc:
|
||||
raise ExternalServiceError(
|
||||
f"飞书HTTP请求失败 [{path}]:{exc.response.status_code} {_response_error_detail(exc.response)}",
|
||||
provider="feishu",
|
||||
) from exc
|
||||
except httpx.HTTPError as exc:
|
||||
raise ExternalServiceError(f"飞书网络请求失败 [{path}]:{exc}", provider="feishu") from exc
|
||||
|
||||
if data.get("code") != 0:
|
||||
raise ExternalServiceError(
|
||||
@@ -100,9 +108,17 @@ def _feishu_post(path: str, payload: dict | None = None, config: FeishuRetrieval
|
||||
url = f"{FEISHU_OPEN_API}{path}"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
resp = httpx.post(url, headers=headers, json=payload, timeout=config.timeout_seconds)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
try:
|
||||
resp = httpx.post(url, headers=headers, json=payload, timeout=config.timeout_seconds)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
except httpx.HTTPStatusError as exc:
|
||||
raise ExternalServiceError(
|
||||
f"飞书HTTP请求失败 [{path}]:{exc.response.status_code} {_response_error_detail(exc.response)}",
|
||||
provider="feishu",
|
||||
) from exc
|
||||
except httpx.HTTPError as exc:
|
||||
raise ExternalServiceError(f"飞书网络请求失败 [{path}]:{exc}", provider="feishu") from exc
|
||||
|
||||
if data.get("code") != 0:
|
||||
raise ExternalServiceError(
|
||||
@@ -112,6 +128,15 @@ def _feishu_post(path: str, payload: dict | None = None, config: FeishuRetrieval
|
||||
return data
|
||||
|
||||
|
||||
def _response_error_detail(response: httpx.Response) -> str:
|
||||
try:
|
||||
body = response.json()
|
||||
except ValueError:
|
||||
return response.text[:200]
|
||||
message = body.get("msg") or body.get("message") or body.get("error") or body
|
||||
return str(message)[:300]
|
||||
|
||||
|
||||
def _extract_text(elements: list[dict]) -> str:
|
||||
"""从 elements 列表中提取纯文本"""
|
||||
texts = []
|
||||
@@ -208,8 +233,16 @@ def _get_wiki_node_info(node_token: str, config: FeishuRetrievalConfig) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _get_wiki_children(node_token: str, config: FeishuRetrievalConfig, page_size: int = 50) -> list[dict]:
|
||||
def _get_wiki_children(
|
||||
space_id: str,
|
||||
node_token: str,
|
||||
config: FeishuRetrievalConfig,
|
||||
page_size: int = 50,
|
||||
) -> list[dict]:
|
||||
"""获取 Wiki 节点的子节点列表"""
|
||||
if not space_id:
|
||||
raise ExternalServiceError("飞书知识库缺少 SpaceID,无法读取子节点", provider="feishu")
|
||||
|
||||
all_children = []
|
||||
page_token = ""
|
||||
while True:
|
||||
@@ -220,7 +253,7 @@ def _get_wiki_children(node_token: str, config: FeishuRetrievalConfig, page_size
|
||||
if page_token:
|
||||
params["page_token"] = page_token
|
||||
|
||||
data = _feishu_get("/open-apis/wiki/v2/spaces/nodes/get_child_nodes", params=params, config=config)
|
||||
data = _feishu_get(f"/open-apis/wiki/v2/spaces/{space_id}/nodes", params=params, config=config)
|
||||
children = data.get("data", {}).get("items", [])
|
||||
all_children.extend(children)
|
||||
|
||||
@@ -231,7 +264,7 @@ def _get_wiki_children(node_token: str, config: FeishuRetrievalConfig, page_size
|
||||
return all_children
|
||||
|
||||
|
||||
def _get_space_node_tree(space_id: str) -> list[dict]:
|
||||
def _get_space_node_tree(space_id: str, config: FeishuRetrievalConfig | None = None) -> list[dict]:
|
||||
"""获取知识空间下所有根节点"""
|
||||
all_nodes = []
|
||||
page_token = ""
|
||||
@@ -243,7 +276,7 @@ def _get_space_node_tree(space_id: str) -> list[dict]:
|
||||
if page_token:
|
||||
params["page_token"] = page_token
|
||||
|
||||
data = _feishu_get("/open-apis/wiki/v2/spaces/nodes", params=params)
|
||||
data = _feishu_get(f"/open-apis/wiki/v2/spaces/{space_id}/nodes", params=params, config=config)
|
||||
items = data.get("data", {}).get("items", [])
|
||||
all_nodes.extend(items)
|
||||
|
||||
@@ -398,7 +431,7 @@ class FeishuKnowledgeService:
|
||||
return [(title, content, source_url)]
|
||||
|
||||
# 如果节点是文件夹,获取子节点
|
||||
children = cls._get_wiki_children_with_cache(node_id, config)
|
||||
children = cls._get_wiki_children_with_cache(space_id, node_id, config)
|
||||
|
||||
documents = []
|
||||
for child in children:
|
||||
@@ -457,9 +490,14 @@ class FeishuKnowledgeService:
|
||||
return content
|
||||
|
||||
@classmethod
|
||||
def _get_wiki_children_with_cache(cls, node_token: str, config: FeishuRetrievalConfig) -> list[dict]:
|
||||
def _get_wiki_children_with_cache(
|
||||
cls,
|
||||
space_id: str,
|
||||
node_token: str,
|
||||
config: FeishuRetrievalConfig,
|
||||
) -> list[dict]:
|
||||
"""带缓存获取子节点"""
|
||||
cache_key = f"{config.app_id}:children:{node_token}"
|
||||
cache_key = f"{config.app_id}:children:{space_id}:{node_token}"
|
||||
now = time.time()
|
||||
|
||||
if cache_key in cls._content_cache:
|
||||
@@ -467,7 +505,7 @@ class FeishuKnowledgeService:
|
||||
if now - ts < cls._CACHE_TTL:
|
||||
return eval(cached_data) # noqa: S307
|
||||
|
||||
children = _get_wiki_children(node_token, config)
|
||||
children = _get_wiki_children(space_id, node_token, config)
|
||||
cls._content_cache[cache_key] = (str(children), now)
|
||||
return children
|
||||
|
||||
|
||||
Reference in New Issue
Block a user