update pay function
This commit is contained in:
Binary file not shown.
@@ -2168,10 +2168,37 @@ class MCPAgentIntegrated:
|
||||
if not successful_results:
|
||||
return "很抱歉,所有步骤都执行失败,无法生成分析报告。"
|
||||
|
||||
# 构建结果文本(精简版)
|
||||
def safe_truncate_result(result, max_length=600):
|
||||
"""安全截取结果,避免截断 JSON 到不完整状态"""
|
||||
result_str = str(result)
|
||||
if len(result_str) <= max_length:
|
||||
return result_str
|
||||
|
||||
# 截取到 max_length
|
||||
truncated = result_str[:max_length]
|
||||
|
||||
# 尝试找到最后一个完整的 JSON 边界(}, ] 或 ,)
|
||||
# 从后往前找一个安全的截断点
|
||||
safe_endings = ['},', '},\n', '}\n', '],', '],\n', ']\n', '",', '",\n', '"\n']
|
||||
best_pos = -1
|
||||
for ending in safe_endings:
|
||||
pos = truncated.rfind(ending)
|
||||
if pos > best_pos:
|
||||
best_pos = pos
|
||||
|
||||
if best_pos > max_length // 2: # 只有找到的位置超过一半时才使用
|
||||
truncated = truncated[:best_pos + 1]
|
||||
|
||||
# 如果结果看起来像 JSON,添加省略提示
|
||||
if truncated.strip().startswith('{') or truncated.strip().startswith('['):
|
||||
return truncated + "\n...(数据已截断)"
|
||||
else:
|
||||
return truncated + "..."
|
||||
|
||||
# 构建结果文本(精简版,安全截取)
|
||||
results_text = "\n\n".join([
|
||||
f"**步骤 {r.step_index + 1}: {r.tool}**\n"
|
||||
f"结果: {str(r.result)[:800]}..."
|
||||
f"结果: {safe_truncate_result(r.result)}"
|
||||
for r in successful_results[:3] # 只取前3个,避免超长
|
||||
])
|
||||
|
||||
|
||||
@@ -8,6 +8,35 @@ import remarkGfm from 'remark-gfm';
|
||||
import { EChartsRenderer } from './EChartsRenderer';
|
||||
import { logger } from '@utils/logger';
|
||||
|
||||
/**
|
||||
* 清理消息中可能存在的残缺 JSON 片段
|
||||
* 这种情况通常是模型生成时意外混入的工具返回数据
|
||||
* @param {string} text - 原始文本
|
||||
* @returns {string} - 清理后的文本
|
||||
*/
|
||||
const cleanBrokenJson = (text) => {
|
||||
if (!text) return text;
|
||||
|
||||
// 移除可能的残缺 JSON 对象片段(没有开头的 { 但有结尾的 })
|
||||
// 例如: "...一些文字itemStyle": {"color": "#ee6666"}, "smooth": true}]\n}"
|
||||
let cleaned = text;
|
||||
|
||||
// 模式1: 移除以 JSON 属性开始的残缺片段 (如 itemStyle": {...})
|
||||
cleaned = cleaned.replace(/[a-zA-Z_][a-zA-Z0-9_]*"\s*:\s*\{[^{}]*\}(\s*,\s*"[a-zA-Z_][a-zA-Z0-9_]*"\s*:\s*[^,}\]]+)*\s*\}\s*\]\s*\}/g, '');
|
||||
|
||||
// 模式2: 移除孤立的 JSON 数组/对象结尾 (如 ]\n})
|
||||
cleaned = cleaned.replace(/\s*\]\s*\}\s*```\s*$/g, '');
|
||||
|
||||
// 模式3: 移除不完整的 echarts 代码块残留
|
||||
// 匹配没有开始标记的残缺内容
|
||||
cleaned = cleaned.replace(/[a-zA-Z_][a-zA-Z0-9_]*"\s*:\s*\[[^\]]*\]\s*\}\s*```/g, '');
|
||||
|
||||
// 模式4: 清理残留的属性片段
|
||||
cleaned = cleaned.replace(/,?\s*"[a-zA-Z_][a-zA-Z0-9_]*"\s*:\s*(?:true|false|null|\d+|"[^"]*")\s*\}\s*\]\s*\}\s*$/g, '');
|
||||
|
||||
return cleaned.trim();
|
||||
};
|
||||
|
||||
/**
|
||||
* 解析 Markdown 内容,提取 ECharts 代码块
|
||||
* @param {string} markdown - Markdown 文本
|
||||
@@ -16,15 +45,18 @@ import { logger } from '@utils/logger';
|
||||
const parseMarkdownWithCharts = (markdown) => {
|
||||
if (!markdown) return [];
|
||||
|
||||
// 先清理可能的残缺 JSON
|
||||
const cleanedMarkdown = cleanBrokenJson(markdown);
|
||||
|
||||
const parts = [];
|
||||
const echartsRegex = /```echarts\s*\n([\s\S]*?)```/g;
|
||||
let lastIndex = 0;
|
||||
let match;
|
||||
|
||||
while ((match = echartsRegex.exec(markdown)) !== null) {
|
||||
while ((match = echartsRegex.exec(cleanedMarkdown)) !== null) {
|
||||
// 添加代码块前的文本
|
||||
if (match.index > lastIndex) {
|
||||
const textBefore = markdown.substring(lastIndex, match.index).trim();
|
||||
const textBefore = cleanedMarkdown.substring(lastIndex, match.index).trim();
|
||||
if (textBefore) {
|
||||
parts.push({ type: 'text', content: textBefore });
|
||||
}
|
||||
@@ -38,8 +70,8 @@ const parseMarkdownWithCharts = (markdown) => {
|
||||
}
|
||||
|
||||
// 添加剩余文本
|
||||
if (lastIndex < markdown.length) {
|
||||
const textAfter = markdown.substring(lastIndex).trim();
|
||||
if (lastIndex < cleanedMarkdown.length) {
|
||||
const textAfter = cleanedMarkdown.substring(lastIndex).trim();
|
||||
if (textAfter) {
|
||||
parts.push({ type: 'text', content: textAfter });
|
||||
}
|
||||
@@ -47,7 +79,7 @@ const parseMarkdownWithCharts = (markdown) => {
|
||||
|
||||
// 如果没有找到图表,返回整个 markdown 作为文本
|
||||
if (parts.length === 0) {
|
||||
parts.push({ type: 'text', content: markdown });
|
||||
parts.push({ type: 'text', content: cleanedMarkdown });
|
||||
}
|
||||
|
||||
return parts;
|
||||
|
||||
Reference in New Issue
Block a user