修正SuperAgent任务结果来源消息定位

This commit is contained in:
andy
2026-07-12 14:53:54 +08:00
parent bf796946f9
commit eee37315a0
18 changed files with 789 additions and 86 deletions

View File

@@ -70,13 +70,13 @@ V3 以以下资料和决策为输入:
后端处理时按以下路径反查:
```text
系统酒店 + source_provider + source_channel + source_message.source_message_id
系统酒店 + source_message.source_message_id
→ platform_source_message_inbox.external_message_id
→ platform_source_message_inbox.id
→ workflow / task / transition 表内部 source_message_id 外键
```
V3 第一版继续使用单酒店阶段的系统默认酒店;后续多酒店或权限收口时再扩展显式酒店上下文。
V3 第一版继续使用单酒店阶段的系统默认酒店;后续多酒店或权限收口时再扩展显式酒店上下文。SuperAgent 不需要传数据库层 provider/channel`source_message.source_channel=Email` 只是上游消息渠道语义;后端以 SourceMessage Inbox 的真实入库 provider/channel 为准。同一系统酒店下如果出现多条相同 `external_message_id`,后端返回 `SOURCE_MESSAGE_AMBIGUOUS`,不随机选择。
### 4.2 缺少 source_message_id
@@ -181,7 +181,9 @@ V3 第一版必须保存并支持以下路由类别:
- `Note``Allotment Maintenance``update_allotment_control_block` 仅历史兼容,不允许新数据生成。
- 当前 producer 不允许再生成 `normal_task/manual_review + Cancel Booking + linked_parent_release_after_child_split`
- `relationship_type=linked_parent_release_after_child_split` 只用于 Parent / Child 关联和 Preflight不再决定 `task_subtype`
- 旧 V2 兼容 `ai_task_results[]` 若继续提交 `Cancel Booking + linked_parent_release_after_child_split`也按当前 producer 契约错误处理
- 旧 V2 兼容 `ai_task_results[]` 若继续提交 `Cancel Booking + linked_parent_release_after_child_split`按请求级 `ADAPTER_CONTRACT_ERROR` 拒绝,不创建业务任务,也不创建 AI transition
- Parent 只提供 `group_code` 或只提供 `block_code`adapter 可以在派生副本中补齐另一边用于路由和落库;原始 payload 不回写。
- Parent 的 `group_code``block_code` 原始候选冲突时不猜测。若 SuperAgent 已输出 `manual_review.reason_code=target_object_unclear``context_used.parent_identity_candidates[]` 非空,创建同卡 type-known manual review否则写入 adapter contract error。
P0.1 Parent Group 路由规则:
@@ -189,8 +191,11 @@ P0.1 Parent Group 路由规则:
| --- | --- | --- |
| Child Group 创建 | `normal_task/manual_review + New Booking + new_group_block` | 创建 New Booking 业务任务 |
| Parent Group 完整释放 / 取消 | `normal_task/manual_review + Cancel Allotment + cancel_allotment_control_block` | 创建 Cancel Allotment 业务任务卡 |
| 旧 Parent split 新入站 | `Cancel Booking + linked_parent_release_after_child_split` | `adapter_contract_error`,不创建业务任务 |
| 旧 Parent split 新入站 | V3 `Cancel Booking + linked_parent_release_after_child_split` | 按 event 写入 `adapter_contract_error`,不创建业务任务 |
| 旧 Parent split V2 兼容入口 | V2 `ai_task_results[]` 中的 `Cancel Booking + linked_parent_release_after_child_split` | 请求级 `ADAPTER_CONTRACT_ERROR` 拒绝,不创建业务任务 / AI transition |
| 重复 Parent 候选 | 同一 Parent Group 再次输出合法 Parent 候选 | 第二个及后续 Parent 写入 `adapter_contract_error` |
| Parent key 单边缺失 | `group_code``block_code` 仅有一边 | 在派生副本中补齐另一边,继续创建 Cancel Allotment 业务任务卡 |
| Parent key 候选冲突 | 双 key 无法安全归一,且 `target_object_unclear + parent_identity_candidates[]` 完整 | 创建 Cancel Allotment 同卡人工复核任务 |
| 历史旧 payload 只读展示 | `Cancel Booking + linked_parent_release_after_child_split` | reader / adapter 展示层可归一为 Cancel Allotment不改写原 payload |
### 7.2 方案 CAI 三元组和系统处理分类分离
@@ -422,6 +427,7 @@ V3 P0.1 不做以下事项:
- 结构化 `S10/S99` 入站处理,复用 `SOURCE_MESSAGE_ONLY` 只读特殊任务。
- 40 条 P0.1 路由枚举 / 稳定配置。
- V3 业务根 `source_message + message_events[]` 基础解析;能派生到稳定路由的 event 创建业务任务,无法派生的 event、显式 `contract_errors`、根 `missing_fields`、不完整 `manual_review`、当前 producer 旧 Parent Cancel Booking 和不完整 parent split 候选只落 `adapter_contract_error` transition。
- P0.1 Parent split 已支持单边 Parent key 归一Parent key 候选冲突且符合 `target_object_unclear + parent_identity_candidates[]` 时进入同卡 type-known manual review不再误判为 adapter contract error。
- `unhandled_current_intents[]` 只落 `UNHANDLED_CURRENT_INTENT` transition不创建订单和任务也不伪装成 adapter 契约错误。
- AI transition 最小保存 `route_code``system_process_category``adapter_error_code``adapter_error_message`
- 任务列表、订单任务时间线和任务详情顶层透出 `result_type``ai_task_type``task_subtype``route_code``system_process_category`

View File

@@ -41,7 +41,7 @@
- 本接口只做技术校验和系统接收,不替代用户确认和 OPERA 模拟操作。
- `application/json` 用于 V3 结构化 `S10/S99`、V3 业务根或 V2 `normal_task` / `manual_review` 兼容结构化任务。
- `text/plain` 用于旧 `S000,source_message_id` / `S999,source_message_id` 特殊入口结果兼容。
- P0.1 后V3 业务根中的完整 Parent split 父事件必须使用 `event_type=Cancel Allotment``task_subtype=cancel_allotment_control_block`;当前新入站不接受 `Cancel Booking + linked_parent_release_after_child_split` 作为合法业务任务旧 V2 `ai_task_results[]` 兼容入口也不能继续提交该三元组。
- P0.1 后V3 业务根中的完整 Parent split 父事件必须使用 `event_type=Cancel Allotment``task_subtype=cancel_allotment_control_block`;当前新入站不接受 `Cancel Booking + linked_parent_release_after_child_split` 作为合法业务任务。V3 `message_events[]` 中的旧三元组按 event 写入 adapter contract error旧 V2 `ai_task_results[]` 兼容入口提交该三元组时按请求级 `ADAPTER_CONTRACT_ERROR` 拒绝
### 2.1 SourceMessage ID 口径
@@ -50,13 +50,13 @@
后端正式处理路径:
```text
hotel_id + source_provider(默认 AGENTBUS) + source_channel(默认 EMAIL) + source_message_id
系统酒店 + source_message_id
→ platform_source_message_inbox.external_message_id
→ platform_source_message_inbox.id
→ workflow_* 表 source_message_id 内部外键
```
数据库 `workflow_*` 表中的 `source_message_id` 仍然保存内部 SourceMessage Inbox ID。只有对外接口的 `source_message_id` 使用外部来源消息 ID。无 `hotel_id` 时仅兼容本地旧夹具使用内部数字 ID正式 SuperAgent 调用不得依赖该兼容路径。
数据库 `workflow_*` 表中的 `source_message_id` 仍然保存内部 SourceMessage Inbox ID。只有对外接口的 `source_message_id` 使用外部来源消息 ID。任务结果通知不要求 SuperAgent 传数据库层 `source_provider` / `source_channel`;后端按系统酒店和外部消息 ID 查唯一 Inbox 记录,真实 provider/channel 以 SourceMessage Inbox 入库值为准。`hotel_id` 时仅兼容本地旧夹具使用内部数字 ID正式 SuperAgent 调用不得依赖该兼容路径。
## 3. 鉴权方案
@@ -171,10 +171,10 @@ JSON 请求体沿用 AI 导入文档定义的聚合结构。
| 字段 | 是否必填 | 中文说明 |
| --- | --- | --- |
| `hotel_id` | | 酒店上下文 ID,用于反查 SourceMessage Inbox 幂等键 |
| `hotel_id` | | 酒店上下文 IDSuperAgent 默认不传,单酒店阶段由后端解析系统酒店 |
| `source_message_id` | 是 | 外部来源消息 ID对应 AgentBus `source.external_message_id`;一次请求只能有一个 |
| `source_provider` | 否 | 来源提供方,第一版缺省为 `AGENTBUS` |
| `source_channel` | 否 | 来源渠道,第一版缺省为 `EMAIL` |
| `source_provider` | 否 | V2 兼容字段;通常不传。写入定位不使用该字段,真实 provider 以 SourceMessage Inbox 入库值为准 |
| `source_channel` | 否 | V2 兼容字段通常不传。写入定位不使用该字段AgentBus 邮件真实入库渠道可能是 `OUTLOOK` |
| `ai_task_results[]` | 是 | AI 拆分出的任务结果列表,必须保留数组顺序 |
| `extraction_warnings[]` | 否 | 抽取警告;不直接等同于业务任务 |
@@ -227,7 +227,7 @@ S999,mail-20260708-0001
处理规则:
- 第一版使用系统默认酒店反查 SourceMessage Inbox不要求文本 body 携带 `hotel_id`
- 后端按 `默认酒店 + AGENTBUS + EMAIL + external_message_id` 查询 SourceMessage。
- 后端按 `默认酒店 + external_message_id` 查询唯一 SourceMessage;真实 provider/channel 以 Inbox 入库值为准
- 命中后创建 `SOURCE_MESSAGE_ONLY` 只读任务。
- 任务列表可见,订单列表不可见。
- 不允许编辑、确认、转换订单、执行 OPERA 或重试 OPERA。
@@ -243,7 +243,7 @@ S999,mail-20260708-0001
- 鉴权签名合法。
- 请求体大小不超过限制。
- JSON body 可解析S000/S999 文本 body 必须符合 `结果码,source_message_id`
- JSON body 中 `hotel_id` 存在。仅本地旧夹具兼容缺少 `hotel_id``source_message_id` 为内部数字 ID 的调用。
- JSON body 中 `hotel_id` 可不传;正式 REST / MCP 调用由后端解析系统酒店。仅本地旧夹具在显式开启兼容开关时允许缺少 `hotel_id``source_message_id` 为内部数字 ID 的调用。
- S000/S999 文本 body 第一版使用系统默认酒店,不读取 `hotel_id`
- 顶层只有一个 `source_message_id`
- `source_message_id` 对应的外部来源消息已经写入 SourceMessage Inbox。
@@ -253,6 +253,8 @@ S999,mail-20260708-0001
- 同一个请求内 `source_event_index` 和数组顺序可保存。
- 关键字符串长度不超过数据库限制。
- V3 P0.1 Parent split 当前合法结构必须是 `Cancel Allotment + cancel_allotment_control_block``Cancel Booking + linked_parent_release_after_child_split` 属于当前 producer 契约错误,只能作为历史 payload 只读兼容。
- Parent 只提供 `case_keys.group_code` 或只提供 `case_keys.block_code` 时,后端会在 adapter 派生副本中补齐另一边,不回写原始 payload。
- Parent `case_keys.group_code``case_keys.block_code` 原始候选冲突时SuperAgent 应输出 `manual_review.reason_code=target_object_unclear` 和非空 `context_used.parent_identity_candidates[]`;后端会创建同卡 type-known manual review。缺少该复核结构时按 adapter contract error 处理。
- 同一个 Parent split cluster 只能有一个 Parent 候选;重复 Parent 候选不创建第二张业务任务卡。
### 5.2 不在本接口判断
@@ -459,6 +461,7 @@ S000 / S999 文本结果创建成功时,同样返回 `201 Created`。这类结
| 409 | `SYSTEM_HOTEL_AMBIGUOUS` | 单酒店阶段平台酒店表存在多家 ACTIVE 酒店 |
| 400 | `SOURCE_MESSAGE_REQUIRED` | `source_message_id` 缺失 |
| 404 | `SOURCE_MESSAGE_NOT_FOUND` | 外部来源消息尚未写入 SourceMessage Inbox |
| 409 | `SOURCE_MESSAGE_AMBIGUOUS` | 同一系统酒店下存在多条相同外部 `source_message_id` 的 Inbox 记录,后端拒绝随机选择 |
| 400 | `TASK_RESULTS_EMPTY` | `ai_task_results[]` 为空 |
| 400 | `TASK_RESULT_UNSUPPORTED_TYPE` | `result_type``task_type` 不可识别 |
| 400 | `DUPLICATE_TASK_RESULT_ITEM` | 同一请求内 item 重复 |

View File

@@ -82,6 +82,7 @@ S10、S99、Fallback、unhandled display = 4 条
- Parent 的 `requires_downstream_hard_validation=true`
- Parent 的 `case_keys.group_code``case_keys.block_code` 必须同时存在且完全相等;只取得一边时复制到另一边。
- Parent 的 `extracted_fields.parent_group_code` 必须与归一后的 Parent code 一致。
- Parent 的 `case_keys.group_code``case_keys.block_code` 原始候选冲突时adapter 不猜测目标对象;如 SuperAgent 已输出 `manual_review.reason_code=target_object_unclear``context_used.parent_identity_candidates[]` 非空,则创建同卡 type-known manual review否则写入 adapter contract error。
- Parent 的 `related_source_event_indices[]` 必须与 `extracted_fields.child_group_codes[]` 数量一致、顺序一一对应,并指向同根 `message_events[]` 中的 Child New Booking。
如果当前 producer 输出:
@@ -126,10 +127,12 @@ Cancel Booking
- 路由枚举为 40 条。
-`linked_parent_release_after_child_split` 不再是当前合法 route definition。
- 当前入站 `Cancel Booking + linked_parent_release_after_child_split` 记录 `adapter_contract_error`,不创建业务任务;该规则同时适用于 V3 `message_events[]` 和旧 V2 兼容 `ai_task_results[]`
- 当前 V3 `message_events[]` 入站 `Cancel Booking + linked_parent_release_after_child_split` 按 event 记录 `adapter_contract_error` transition,不创建业务任务。
- 旧 V2 兼容 `ai_task_results[]` 若提交 `Cancel Booking + linked_parent_release_after_child_split`,按请求级 `ADAPTER_CONTRACT_ERROR` 拒绝,不创建业务任务,也不创建 AI transition。
- 当前入站 `Cancel Allotment + cancel_allotment_control_block + linked_parent_release_after_child_split` 可以创建 `CANCEL_ALLOTMENT` 业务卡。
- 同一个 Parent split cluster 重复提交 Parent 候选时,后续重复 Parent 记录为 `adapter_contract_error`,不再创建第二张 Parent 任务卡。
- Parent 双 key 不一致时不猜测,进入 type-known manual review 或 adapter contract error不能改成普通 Cancel Booking
- Parent 只提供 `group_code` 或只提供 `block_code`adapter 可在派生副本中补齐另一边;原始 payload 不回写
- Parent 双 key 不一致时不猜测,满足 `target_object_unclear + parent_identity_candidates[]` 时进入 type-known manual review否则进入 adapter contract error不能改成普通 Cancel Booking。
- Parent `child_group_codes[]``related_source_event_indices[]` 数量、顺序和 Child New Booking 目标一致。
- 普通 FIT / Group Block 的 `Cancel Booking` 不受影响。
- 旧历史数据只读兼容,不迁移、不改写原 payload。