Fix Feishu sheet data writes

This commit is contained in:
wuyang6
2026-05-11 18:05:35 +08:00
parent 3a4da782ec
commit a68302659d
2 changed files with 94 additions and 19 deletions
+54 -11
View File
@@ -2634,10 +2634,10 @@ def _create_feishu_online_spreadsheet(
create_params: dict[str, Any] = {'title': title}
if folder_token and folder_token.strip():
create_params['folder_token'] = folder_token.strip()
rendered, metadata = runtime.call_tool(
rendered, metadata = _call_feishu_mcp_tool_checked(
runtime,
'sheet_ops',
arguments={'action': 'create', 'params': create_params},
server_name=FEISHU_MCP_SERVER_NAME,
max_chars=API_TOOL_CONTENT_MAX_CHARS,
timeout_seconds=60.0,
)
@@ -2645,13 +2645,14 @@ def _create_feishu_online_spreadsheet(
if not spreadsheet_token:
raise DataAgentInputError('飞书表格已创建,但没有解析到 spreadsheet token')
sheet_refs = _discover_feishu_sheet_refs(runtime, spreadsheet_token)
for index, sheet_data in enumerate(sheets):
rows = sheet_data['rows']
if not rows:
continue
if index == 0:
sheet_ref = sheet_refs[0] if sheet_refs else 'Sheet1'
# 新建飞书表格默认会带一个名为 Sheet1 的工作表。
# 不从 spreadsheet meta 里取顶层 title,避免把文件名误当成工作表名。
sheet_ref = 'Sheet1'
else:
sheet_ref = _create_feishu_worksheet(
runtime,
@@ -2663,6 +2664,44 @@ def _create_feishu_online_spreadsheet(
return rendered, metadata
def _call_feishu_mcp_tool_checked(
runtime: MCPRuntime,
tool_name: str,
*,
arguments: dict[str, Any],
max_chars: int,
timeout_seconds: float,
) -> tuple[str, dict[str, Any]]:
rendered, metadata = runtime.call_tool(
tool_name,
arguments=arguments,
server_name=FEISHU_MCP_SERVER_NAME,
max_chars=max_chars,
timeout_seconds=timeout_seconds,
)
error_message = _extract_feishu_mcp_error(rendered)
if metadata.get('is_error') or error_message:
raise DataAgentInputError(error_message or f'飞书 MCP 工具 {tool_name} 调用失败')
return rendered, metadata
def _extract_feishu_mcp_error(text: str) -> str | None:
payload = _parse_first_json_object(text)
if not isinstance(payload, dict):
return None
error_value = payload.get('error')
if not error_value:
return None
suggestion = payload.get('suggestion')
code = payload.get('code')
parts = [str(error_value)]
if code is not None:
parts.append(f'code={code}')
if suggestion:
parts.append(str(suggestion))
return ''.join(parts)
def _load_file_as_feishu_sheets(file_path: Path) -> list[dict[str, Any]]:
suffix = file_path.suffix.lower()
if suffix == '.csv':
@@ -2762,10 +2801,10 @@ def _extract_feishu_spreadsheet_token(text: str) -> str | None:
def _discover_feishu_sheet_refs(runtime: MCPRuntime, spreadsheet_token: str) -> list[str]:
try:
rendered, _metadata = runtime.call_tool(
rendered, _metadata = _call_feishu_mcp_tool_checked(
runtime,
'sheet_ops',
arguments={'action': 'meta', 'params': {'url_or_token': spreadsheet_token}},
server_name=FEISHU_MCP_SERVER_NAME,
max_chars=API_TOOL_CONTENT_MAX_CHARS,
timeout_seconds=60.0,
)
@@ -2785,7 +2824,11 @@ def _extract_feishu_sheet_refs(text: str) -> list[str]:
raw_title = value.get('title') or value.get('name')
if isinstance(raw_id, str) and raw_id.strip():
refs.append(raw_id.strip())
elif isinstance(raw_title, str) and raw_title.strip():
elif (
isinstance(raw_title, str)
and raw_title.strip()
and ('index' in value or 'row_count' in value or 'col_count' in value)
):
refs.append(raw_title.strip())
for child in value.values():
visit(child)
@@ -2816,7 +2859,8 @@ def _create_feishu_worksheet(
index: int,
) -> str:
sheet_title = _clean_feishu_sheet_title(title) or f'Sheet{index + 1}'
rendered, _metadata = runtime.call_tool(
rendered, _metadata = _call_feishu_mcp_tool_checked(
runtime,
'sheet_ops',
arguments={
'action': 'add_sheet',
@@ -2826,7 +2870,6 @@ def _create_feishu_worksheet(
'index': index,
},
},
server_name=FEISHU_MCP_SERVER_NAME,
max_chars=API_TOOL_CONTENT_MAX_CHARS,
timeout_seconds=60.0,
)
@@ -2848,7 +2891,8 @@ def _write_feishu_sheet_rows(
chunk = rows[start : start + FEISHU_SPREADSHEET_WRITE_BATCH_ROWS]
start_row = start + 1
end_row = start + len(chunk)
runtime.call_tool(
_call_feishu_mcp_tool_checked(
runtime,
'sheet_ops',
arguments={
'action': 'write',
@@ -2858,7 +2902,6 @@ def _write_feishu_sheet_rows(
'values': json.dumps(chunk, ensure_ascii=False),
},
},
server_name=FEISHU_MCP_SERVER_NAME,
max_chars=API_TOOL_CONTENT_MAX_CHARS,
timeout_seconds=60.0,
)