实现 M002 V3 入站解析与路由基线
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档版本 | 0.5 |
|
||||
| 日期 | 2026-07-10 |
|
||||
| 状态 | 已增加 S000/S999 特殊入口结果处理,并完成单酒店阶段 hotel_id 后端解析收口 |
|
||||
| 文档版本 | 0.7 |
|
||||
| 日期 | 2026-07-11 |
|
||||
| 状态 | 当前代码契约已支持 V2 `ai_task_results[]` 兼容、结构化 S10/S99、V3 业务根基础解析、旧 S000/S999 兼容和单酒店 hotel_id 后端解析 |
|
||||
| 适用范围 | SuperAgent 调用本系统查询上下文、查询邮件会话、提交 AI 任务结果 |
|
||||
| 主要读者 | SuperAgent 对接方、后端、测试、运维 |
|
||||
|
||||
@@ -88,7 +88,7 @@ X-TH-Hotel-SuperAgent-Signature: sha256=<lowercase-hex-signature>
|
||||
6. 使用共享 secret 重新计算 HMAC。
|
||||
7. 常量时间比较签名。
|
||||
8. 校验并记录 `client_id + nonce`,防止重放。
|
||||
9. 鉴权和协议校验通过后再解析业务 JSON 或 S000/S999 文本结果。
|
||||
9. 鉴权和协议校验通过后再解析业务 JSON、结构化 S10/S99、V3 业务根或 S000/S999 文本结果。
|
||||
|
||||
## 3. SourceMessage ID 口径
|
||||
|
||||
@@ -105,6 +105,25 @@ SuperAgent 不应知道或依赖内部 SourceMessage Inbox ID。任务结果通
|
||||
|
||||
查询接口 3、4 面向已经入库的邮件会话:缺省酒店由后端解析,`external_conversation_id` 最终仍按 `hotel_id + source_provider + source_channel + external_conversation_id` 查询;`source_message_id` 表示外部来源消息 ID,可作为锚点反查该邮件所属会话。
|
||||
|
||||
## 3.1 M002 V3 迁移提醒
|
||||
|
||||
2026-07-11 起,项目需求基线已确认采用 `docs/project/requirements/M002-order-task-workflow-v3.md`:
|
||||
|
||||
- 新入口结果将从旧文本 `S000/S999` 迁移为结构化 `S10/S99`。
|
||||
- 新业务输出将从旧 `ai_task_results[]` 迁移为 `source_message + message_events[] + case_candidates[] + extraction_warnings[] + unhandled_current_intents[]`。
|
||||
- 后端会完整保存 AI 三元组、`route_code` 和系统处理分类;`S10/S99` 仍以只读源邮件通知卡展示,任务列表可见,订单列表不可见。
|
||||
- 旧 `S000/S999` 数据继续兼容展示,语义上分别映射到 `S10/S99`。
|
||||
|
||||
当前后端已完成 M002 V3 CP1-CP2:
|
||||
|
||||
- 已建立 42 条 P0 路由枚举 / 稳定配置。
|
||||
- 已支持结构化 `S10/S99` 入站,创建只读 `SOURCE_MESSAGE_ONLY` 任务。
|
||||
- 已支持 V3 业务根 `source_message + message_events[]` 的基础解析;可派生到现有任务模型的 event 会创建业务任务,无法派生、显式契约错误或基础 manual_review / parent split 结构不完整的 event 只落 `adapter_contract_error` transition,不创建业务任务。
|
||||
- 已支持 `unhandled_current_intents[]` 最小落库:只写 `UNHANDLED_CURRENT_INTENT` transition,不创建业务任务,也不按 adapter 契约错误返回。
|
||||
- 已在 `workflow_reservation_ai_transition` 保存 `route_code`、`system_process_category`、`adapter_error_code` 和 `adapter_error_message`。
|
||||
|
||||
尚未完成:type-known manual review 同卡解阻、`manual_review.missing_fields[]` 到任务卡可编辑字段白名单的完整映射校验、typed `infrastructure_input_error` 响应、复核场景订单归属确认、真实 OPERA / OHIP、普通任务切换订单、任务列表 / 详情接口完整透出所有 V3 路由字段。
|
||||
|
||||
## 4. 接口 1:查询订单上下文
|
||||
|
||||
### 4.1 请求
|
||||
@@ -433,9 +452,100 @@ SuperAgent 不应知道或依赖内部 SourceMessage Inbox ID。任务结果通
|
||||
| URL | `{TH_HOTEL_API_BASE_URL}/api/integrations/superagent/task-results` |
|
||||
| request_path | `/api/integrations/superagent/task-results` |
|
||||
| Content-Type | `application/json` 或 `text/plain` |
|
||||
| 业务动作 | 接收 AI 任务结果;JSON 写入业务订单和任务,S000/S999 创建只读特殊任务 |
|
||||
| 业务动作 | 接收 AI 任务结果;V3 JSON 支持结构化 S10/S99 和业务根,V2 JSON 继续兼容,旧 S000/S999 文本创建只读特殊任务 |
|
||||
|
||||
### 8.2 JSON 请求体
|
||||
### 8.2 V3 S10/S99 结构化请求体
|
||||
|
||||
S10 示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"source_message": {
|
||||
"source_message_id": "mail-20260708-0001",
|
||||
"subject": null,
|
||||
"from": null,
|
||||
"cc": [],
|
||||
"received_at": null,
|
||||
"source_channel": "Email"
|
||||
},
|
||||
"route_code": "S10",
|
||||
"handler_type": "main_agent_outcome",
|
||||
"result_type": "source_message_review_notification",
|
||||
"current_or_history": "current",
|
||||
"agent_assessment": {
|
||||
"status": "no_booking_action_detected",
|
||||
"reason_code": "no_booking_action_detected",
|
||||
"automation_action": "none"
|
||||
},
|
||||
"notification": {
|
||||
"required": true,
|
||||
"notification_type": "source_message_review",
|
||||
"show_source_message": true,
|
||||
"requires_user_decision": true
|
||||
},
|
||||
"manual_review": null
|
||||
}
|
||||
```
|
||||
|
||||
S99 与 S10 使用相同结构,但 `route_code=S99`,`agent_assessment.status=material_package_unavailable`,且 `manual_review` 必须是完整入口复核对象。
|
||||
|
||||
### 8.3 V3 业务根请求体
|
||||
|
||||
```json
|
||||
{
|
||||
"source_message": {
|
||||
"source_message_id": "mail-20260708-0002",
|
||||
"subject": "New booking",
|
||||
"from": null,
|
||||
"cc": [],
|
||||
"received_at": null,
|
||||
"source_channel": "Email"
|
||||
},
|
||||
"message_events": [
|
||||
{
|
||||
"event_type": "New Booking",
|
||||
"source_event_index": "E1",
|
||||
"current_or_history": "current",
|
||||
"case_keys": {
|
||||
"group_code": null,
|
||||
"confirmation_number": "CNF-001"
|
||||
},
|
||||
"extracted_fields": {
|
||||
"booking_object_type": "FIT Reservation"
|
||||
},
|
||||
"manual_review": null
|
||||
}
|
||||
],
|
||||
"case_candidates": [],
|
||||
"extraction_warnings": [],
|
||||
"unhandled_current_intents": []
|
||||
}
|
||||
```
|
||||
|
||||
V3 字段说明:
|
||||
|
||||
| 字段 | 是否必填 | 中文说明 |
|
||||
| --- | --- | --- |
|
||||
| `source_message.source_message_id` | 是 | 外部来源消息 ID,对应 SourceMessage Inbox 的 `external_message_id`;缺失时返回技术错误且不落库 |
|
||||
| `route_code` | S10/S99 必填 | 只允许 `S10` 或 `S99`,用于区分入口通知结果 |
|
||||
| `result_type` | S10/S99 必填 | 固定为 `source_message_review_notification` |
|
||||
| `message_events[]` | 业务根必填 | SuperAgent 最终业务事件列表,本系统逐 event 派生路由 |
|
||||
| `message_events[].event_type` | 是 | V3 active event 或 `Need Manual Review` |
|
||||
| `message_events[].source_event_index` | 建议必填 | 可为 `E1` 或数字;后端会归一为数字序号 |
|
||||
| `message_events[].case_keys` | 否 | 订单关联候选键 |
|
||||
| `message_events[].extracted_fields` | 否 | 业务字段主体和 subtype 判别字段 |
|
||||
| `message_events[].manual_review` | 否 | `null` 表示普通任务;对象表示 type-known manual review |
|
||||
| `unhandled_current_intents[]` | 否 | 第一版只保存 `UNHANDLED_CURRENT_INTENT` transition,不自动创建业务任务 |
|
||||
|
||||
当前已支持的 V3 行为:
|
||||
|
||||
- 42 条 P0 路由进入后端枚举 / 稳定配置。
|
||||
- 结构化 `S10/S99` 创建只读 `SOURCE_MESSAGE_ONLY` 任务,任务列表可见,订单列表不可见。
|
||||
- 业务 event 能派生到稳定路由时,复用现有订单 / 任务 / 任务卡创建链路。
|
||||
- event 判别字段不完整、显式携带 `contract_errors`、根 `missing_fields`、不完整 `manual_review` 或不完整 parent split 候选时,写入 `adapter_contract_error` transition,不创建订单和任务;同一邮件其他 sibling event 继续处理。
|
||||
- `unhandled_current_intents[]` 写入 `UNHANDLED_CURRENT_INTENT` transition,不返回 `adapter_error_code`。
|
||||
|
||||
### 8.4 V2 JSON 兼容请求体
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -481,7 +591,7 @@ SuperAgent 不应知道或依赖内部 SourceMessage Inbox ID。任务结果通
|
||||
| `ai_task_results[].source_event_index` | 是 | AI current 事件序号 |
|
||||
| `ai_task_results[].catalog_code` | 是 | Skill 目录代码 |
|
||||
| `ai_task_results[].skill_id` | 是 | Skill 标识 |
|
||||
| `ai_task_results[].result_type` | 是 | 新入口只接受 `normal_task`、`manual_review`;`informational_message` 仅历史兼容 |
|
||||
| `ai_task_results[].result_type` | 是 | 当前代码契约只接受 `normal_task`、`manual_review`;`informational_message` 仅历史兼容 |
|
||||
| `ai_task_results[].task_type` | 是 | AI 原始任务类型 |
|
||||
| `ai_task_results[].task_subtype` | 否 | 业务动作 subtype |
|
||||
| `ai_task_results[].case_keys` | 否 | 订单关联候选键 |
|
||||
@@ -489,9 +599,9 @@ SuperAgent 不应知道或依赖内部 SourceMessage Inbox ID。任务结果通
|
||||
|
||||
正式联调时,SuperAgent 不需要传 `hotel_id`。后端通过系统酒店 `hotel_id + source_provider(默认 AGENTBUS) + source_channel(默认 EMAIL) + source_message_id` 查找 `platform_source_message_inbox.external_message_id`。如果没有找到,返回 `SOURCE_MESSAGE_NOT_FOUND`。本地旧夹具允许在缺少 `hotel_id` 时使用内部数字 SourceMessage ID,但该兼容路径不作为 SuperAgent 正式契约。
|
||||
|
||||
`informational_message` 结构化任务仅用于历史兼容。新入口如果是纯信息类邮件或无法形成业务素材包,不要提交空数组,也不要生成 `informational_message`;应使用下面的 S000/S999 文本请求体。
|
||||
`informational_message` 结构化任务仅用于历史兼容。新数据如果是纯信息类邮件或无法形成业务素材包,应优先使用 V3 结构化 `S10/S99`;旧联调或兼容场景仍可使用下面的 `S000/S999` 文本请求体。
|
||||
|
||||
### 8.3 S000/S999 文本请求体
|
||||
### 8.5 S000/S999 文本请求体
|
||||
|
||||
纯信息类邮件:
|
||||
|
||||
@@ -513,9 +623,9 @@ S999,mail-20260708-0001
|
||||
| `S999` | 入口阶段无法形成业务素材包,不需要进入业务执行。 |
|
||||
| `mail-20260708-0001` | 外部来源消息 ID,对应 SourceMessage Inbox 的 `external_message_id`。 |
|
||||
|
||||
第一版 S000/S999 不在 body 里传 `hotel_id`,后端使用平台酒店表唯一 `ACTIVE` 酒店查询 SourceMessage Inbox。命中后创建 `SOURCE_MESSAGE_ONLY` 只读特殊任务:任务列表可见,订单列表不可见,不允许编辑、确认、转换订单、执行 OPERA 或重试 OPERA,也不参与同订单任务执行顺序阻塞。
|
||||
S000/S999 不在 body 里传 `hotel_id`,后端使用平台酒店表唯一 `ACTIVE` 酒店查询 SourceMessage Inbox。命中后创建 `SOURCE_MESSAGE_ONLY` 只读特殊任务:任务列表可见,订单列表不可见,不允许编辑、确认、转换订单、执行 OPERA 或重试 OPERA,也不参与同订单任务执行顺序阻塞。该文本格式仅为兼容路径,新数据优先使用结构化 `S10/S99`。
|
||||
|
||||
### 8.4 成功响应
|
||||
### 8.6 成功响应
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -529,6 +639,9 @@ S999,mail-20260708-0001
|
||||
"source_event_index": 1,
|
||||
"array_index": 1,
|
||||
"ai_transition_id": "1900000000000000250",
|
||||
"route_code": "R01_NEW_FIT_RESERVATION_NORMAL",
|
||||
"system_process_category": "BUSINESS_TASK",
|
||||
"adapter_error_code": null,
|
||||
"order_id": "1900000000000000300",
|
||||
"task_id": "1900000000000000400",
|
||||
"system_task_type": "NEW_BOOKING",
|
||||
@@ -556,6 +669,9 @@ S000/S999 成功响应示例:
|
||||
"source_event_index": 1,
|
||||
"array_index": 1,
|
||||
"ai_transition_id": "1900000000000000550",
|
||||
"route_code": "S10",
|
||||
"system_process_category": "SOURCE_MESSAGE_NOTIFICATION",
|
||||
"adapter_error_code": null,
|
||||
"order_id": "1900000000000000600",
|
||||
"task_id": "1900000000000000700",
|
||||
"system_task_type": "SOURCE_MESSAGE_ONLY",
|
||||
@@ -569,6 +685,26 @@ S000/S999 成功响应示例:
|
||||
}
|
||||
```
|
||||
|
||||
V3 `adapter_contract_error` 响应中的 `items[]` 不会包含 `order_id` / `task_id`:
|
||||
|
||||
```json
|
||||
{
|
||||
"source_event_index": 2,
|
||||
"array_index": 1,
|
||||
"ai_transition_id": "1900000000000000800",
|
||||
"route_code": null,
|
||||
"system_process_category": "ADAPTER_CONTRACT_ERROR",
|
||||
"adapter_error_code": "EVENT_ROUTE_UNSUPPORTED",
|
||||
"order_id": null,
|
||||
"task_id": null,
|
||||
"system_task_type": "ADAPTER_CONTRACT_ERROR",
|
||||
"task_card_type": "ADAPTER_CONTRACT_ERROR",
|
||||
"task_status": null,
|
||||
"order_status": null,
|
||||
"execution_order": null
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 错误响应
|
||||
|
||||
### 9.1 查询接口错误响应
|
||||
|
||||
Reference in New Issue
Block a user