debug和superagent提交的数据保持一致

This commit is contained in:
andy
2026-07-13 17:03:27 +08:00
parent c55090bc2e
commit 9a2812fe74
11 changed files with 191 additions and 86 deletions

View File

@@ -14,7 +14,7 @@ import java.time.LocalDateTime;
* @param originalFileName 原始 EML 安全文件名
* @param originalEmlOssUrl 原始 EML OSS URL
* @param originalEmlSha256 原始 EML SHA-256
* @param payloadJson 发送给 SuperAgent 的 AgentBus-like payload
* @param payloadJson 发送给 SuperAgent 的 AgentBus Outlook-like payload
* @param superagentSessionId SuperAgent session ID
* @param superagentRunId SuperAgent run ID
* @param superagentProfileId SuperAgent profile ID

View File

@@ -12,7 +12,7 @@ import java.time.LocalDateTime;
* @param originalFileName 原始上传文件安全文件名
* @param originalEmlOssUrl 原始 .eml OSS URL
* @param originalEmlSha256 原始 .eml SHA-256
* @param payloadJson AgentBus-like payload JSON
* @param payloadJson AgentBus Outlook-like payload JSON
* @param superagentSessionId SuperAgent session ID
* @param superagentRunId SuperAgent run ID
* @param superagentProfileId SuperAgent profile ID

View File

@@ -21,7 +21,7 @@ import java.util.Map;
* @param htmlBodySanitized 后端清洗后的 HTML前端调试展示应优先使用
* @param htmlSanitizeRequired 是否要求前端按安全 HTML 规则展示
* @param htmlRenderMode HTML 渲染建议模式
* @param agentbusLikePayload 发送给 SuperAgent 的结构化 payload
* @param agentbusLikePayload 发送给 SuperAgent 的 AgentBus Outlook-like 主 payload
* @param superagentSessionId SuperAgent session ID
* @param superagentRunId SuperAgent run ID
* @param superagentRawAnswer SuperAgent 原始最终回答

View File

@@ -30,7 +30,7 @@ public class DebugEmlSuperAgentRunEntity {
private String originalEmlOssUrl;
/** 原始 .eml 文件 SHA-256。 */
private String originalEmlSha256;
/** AgentBus-like payload JSON。 */
/** 发送给 SuperAgent 的 AgentBus Outlook-like payload JSON。 */
private String payloadJson;
/** SuperAgent Open API session ID。 */
private String superagentSessionId;

View File

@@ -82,6 +82,7 @@ public class DebugEmlSuperAgentRunServiceImpl implements DebugEmlSuperAgentRunSe
private static final Logger log = LoggerFactory.getLogger(DebugEmlSuperAgentRunServiceImpl.class);
private static final String SOURCE_PROVIDER = "DEBUG_EML_UPLOAD";
private static final String SOURCE_CHANNEL = "EMAIL";
private static final String REPLY_POLICY_MODE = "manual";
private static final String SCHEMA_VERSION = "debug-eml-upload-v1";
private static final DateTimeFormatter DATE_FOLDER_FORMATTER = DateTimeFormatter.BASIC_ISO_DATE;
private static final Pattern CID_REFERENCE_PATTERN = Pattern.compile(
@@ -479,12 +480,9 @@ public class DebugEmlSuperAgentRunServiceImpl implements DebugEmlSuperAgentRunSe
String htmlBodySanitized = htmlSanitizerService.sanitizeHtml(htmlWithOssUrls);
String htmlRenderMode = htmlSanitizerService.htmlRenderMode(htmlWithOssUrls);
Map<String, Object> payload = buildAgentBusLikePayload(
runId,
runLabel,
createdAt,
externalMessageId,
externalConversationId,
originalMessageId,
originalConversationId,
parsed,
htmlWithOssUrls,
uploadedMedia);
@@ -528,11 +526,15 @@ public class DebugEmlSuperAgentRunServiceImpl implements DebugEmlSuperAgentRunSe
SuperAgentMailDebugRequest superAgentRequest = new SuperAgentMailDebugRequest(
buildSuperAgentMessage(payloadJson),
"debug-eml-" + runId,
Map.of(
"source", "th-hotel-debug-eml-upload",
"debug_run_id", runId.toString(),
"source_message_id", captureResult.inboxId().toString(),
"hotel_id", hotelId));
buildSuperAgentMetadata(
runId,
runLabel,
captureResult.inboxId(),
hotelId,
externalMessageId,
externalConversationId,
originalMessageId,
originalConversationId));
List<SuperAgentOpenApiTraceEvent> streamedTraceEvents = new ArrayList<>();
Consumer<SuperAgentOpenApiTraceEvent> traceConsumer = traceEvent -> {
streamedTraceEvents.add(traceEvent);
@@ -919,28 +921,24 @@ public class DebugEmlSuperAgentRunServiceImpl implements DebugEmlSuperAgentRunSe
}
/**
* 组装接近 AgentBus 邮件输入的 payload。
* 组装发给 SuperAgent 的 AgentBus Outlook 邮件 payload。调试来源信息放入 Open API metadata
* 避免 DEBUG_EML_UPLOAD 等调试语义影响 SuperAgent 对实时 AgentBus 邮件的判断。
*/
private Map<String, Object> buildAgentBusLikePayload(
Long runId,
String runLabel,
LocalDateTime createdAt,
String externalMessageId,
String externalConversationId,
String originalMessageId,
String originalConversationId,
ParsedEmlMessage parsed,
String htmlWithOssUrls,
List<UploadedMedia> uploadedMedia) {
Map<String, Object> source = new LinkedHashMap<>();
source.put("channel", SOURCE_CHANNEL);
source.put("provider", SOURCE_PROVIDER);
source.put("external_message_id", externalMessageId);
source.put("external_conversation_id", externalConversationId);
source.put("original_message_id", originalMessageId);
source.put("original_conversation_id", originalConversationId);
source.put("sender", parsed.sender());
source.put("subject", parsed.subject());
source.put("sent_at", parsed.sentAt() == null ? null : parsed.sentAt().toString());
source.put("received_at", utcInstantText(createdAt));
Map<String, Object> body = new LinkedHashMap<>();
body.put("content_type", contentType(parsed, htmlWithOssUrls));
@@ -950,26 +948,56 @@ public class DebugEmlSuperAgentRunServiceImpl implements DebugEmlSuperAgentRunSe
List<Map<String, Object>> inlineImages = mediaPayload(uploadedMedia, SourceMessageMediaType.INLINE_IMAGE.code());
List<Map<String, Object>> attachments = mediaPayload(uploadedMedia, SourceMessageMediaType.ATTACHMENT.code());
Map<String, Object> replyPolicy = new LinkedHashMap<>();
replyPolicy.put("mode", "debug_only");
replyPolicy.put("final_only", true);
Map<String, Object> debugContext = new LinkedHashMap<>();
debugContext.put("debug_run_id", runId.toString());
debugContext.put("run_label", runLabel);
debugContext.put("original_eml_oss_url", uploadedMedia.get(0).result().externalUrl());
Map<String, Object> payload = new LinkedHashMap<>();
payload.put("schema_version", SCHEMA_VERSION);
payload.put("text", parsed.textBody());
payload.put("received_at", utcInstantText(createdAt));
payload.put("source", source);
payload.put("body", body);
payload.put("inline_images", inlineImages);
payload.put("attachments", attachments);
payload.put("reply_policy", replyPolicy);
payload.put("debug_context", debugContext);
payload.put("reply_policy", replyPolicy());
return payload;
}
/**
* 构造 AgentBus Outlook 关键字段中的回复策略。Debug 链路第一版不自动回复客户,使用非 Debug 专属的人工处理语义。
*/
private Map<String, Object> replyPolicy() {
Map<String, Object> replyPolicy = new LinkedHashMap<>();
replyPolicy.put("mode", REPLY_POLICY_MODE);
replyPolicy.put("final_only", true);
return replyPolicy;
}
/**
* 构造 Debug EML 调用 SuperAgent 的 metadata。这里保存调试来源和原始 EML 标识,不混入邮件主 payload。
*/
private Map<String, Object> buildSuperAgentMetadata(
Long runId,
String runLabel,
Long sourceMessageId,
String hotelId,
String externalMessageId,
String externalConversationId,
String originalMessageId,
String originalConversationId) {
Map<String, Object> debugContext = new LinkedHashMap<>();
putIfNotNull(debugContext, "debug_run_id", runId == null ? null : runId.toString());
putIfNotNull(debugContext, "run_label", runLabel);
putIfNotNull(debugContext, "original_message_id", originalMessageId);
putIfNotNull(debugContext, "original_conversation_id", originalConversationId);
Map<String, Object> metadata = new LinkedHashMap<>();
metadata.put("source", "th-hotel-debug-eml-upload");
putIfNotNull(metadata, "debug_run_id", runId == null ? null : runId.toString());
putIfNotNull(metadata, "source_message_id", sourceMessageId == null ? null : sourceMessageId.toString());
putIfNotNull(metadata, "hotel_id", hotelId);
putIfNotNull(metadata, "external_message_id", externalMessageId);
putIfNotNull(metadata, "external_conversation_id", externalConversationId);
metadata.put("debug_context", debugContext);
return metadata;
}
/**
* 构造媒体 payload 数组。
*/
@@ -978,13 +1006,12 @@ public class DebugEmlSuperAgentRunServiceImpl implements DebugEmlSuperAgentRunSe
.filter(item -> mediaType.equals(item.result().mediaType()))
.map(item -> {
Map<String, Object> media = new LinkedHashMap<>();
media.put("id", item.result().externalMediaId());
media.put("media_type", item.result().mediaType());
media.put("file_name", item.result().fileName());
media.put("content_type", item.result().contentType());
media.put("size_bytes", item.result().sizeBytes());
media.put("external_url", item.result().externalUrl());
media.put("external_media_id", item.result().externalMediaId());
media.put("object_key", item.result().objectKey());
if (item.contentId() != null) {
media.put("content_id", item.contentId());
}
@@ -1000,16 +1027,21 @@ public class DebugEmlSuperAgentRunServiceImpl implements DebugEmlSuperAgentRunSe
boolean hasText = parsed.textBody() != null && !parsed.textBody().isBlank();
boolean hasHtml = htmlWithOssUrls != null && !htmlWithOssUrls.isBlank();
if (hasText && hasHtml) {
return "MIXED";
return "mixed";
}
return hasHtml ? "HTML" : "TEXT";
return hasHtml ? "html" : "text";
}
/**
* 构造发送给 SuperAgent 的消息文本。
*/
private String buildSuperAgentMessage(String payloadJson) {
return "请基于以下 Debug 邮件 JSON 输出结构化任务抽取结果,只返回 JSON不要创建订单或任务\n" + payloadJson;
return """
请基于以下 AgentBus Outlook 邮件 JSON 输出结构化任务抽取结果。
只返回 SuperAgent 当前约定的 JSON 或 S10/S99 特殊结果不要创建订单、任务、OPERA 操作或客户回复。
AgentBus Outlook 邮件 JSON
""" + payloadJson;
}
/**
@@ -1282,6 +1314,25 @@ public class DebugEmlSuperAgentRunServiceImpl implements DebugEmlSuperAgentRunSe
return trimmed.isEmpty() ? null : trimmed;
}
/**
* 向 metadata 写入非空字段,避免 Map.of 不能容纳 null也避免输出无意义空值。
*/
private void putIfNotNull(Map<String, Object> target, String key, Object value) {
if (value != null) {
target.put(key, value);
}
}
/**
* 将数据库 UTC LocalDateTime 转为带 Z 的 ISO-8601 时间点。
*/
private String utcInstantText(LocalDateTime value) {
if (value == null) {
return null;
}
return value.atOffset(ZoneOffset.UTC).toInstant().toString();
}
/**
* 去掉 URL 末尾斜杠,便于用公开基础 URL 还原对象路径。
*/