实现SuperAgent特殊入口结果处理

This commit is contained in:
andy
2026-07-10 12:05:57 +08:00
parent 9de4f0e7b6
commit 74e429a2cb
29 changed files with 1121 additions and 97 deletions

View File

@@ -4,9 +4,9 @@
| 项目 | 内容 |
| --- | --- |
| 文档版本 | 0.3 |
| 日期 | 2026-07-09 |
| 状态 | 已增加邮件会话任务和受控正文查询接口 |
| 文档版本 | 0.4 |
| 日期 | 2026-07-10 |
| 状态 | 已增加 S000/S999 特殊入口结果处理 |
| 适用范围 | SuperAgent 调用本系统查询上下文、查询邮件会话、提交 AI 任务结果 |
| 主要读者 | SuperAgent 对接方、后端、测试、运维 |
@@ -17,7 +17,7 @@
| 参数 | 当前联调值 | 中文说明 |
| --- | --- | --- |
| `TH_HOTEL_API_BASE_URL` | `http://8.138.234.141:18087` | 本系统后端基础地址;本地联调用 8080部署环境改为实际网关或服务地址。 |
| `HOTEL_ID` | `HOTEL-DEV` | 当前 dev profile 下 AgentBus 入库默认酒店 ID调用五个 SuperAgent 接口时均应传入请求体 `hotel_id`。 |
| `HOTEL_ID` | `HOTEL-DEV` | 当前 dev profile 下 AgentBus 入库默认酒店 ID查询接口和 JSON 任务结果请求体应传入 `hotel_id`S000/S999 文本结果使用本系统默认酒店。 |
| `SUPERAGENT_CLIENT_ID` | `superagent-debug` | SuperAgent 调用方 ID对应 Header `X-TH-Hotel-SuperAgent-Client-Id`。 |
| `SUPERAGENT_HMAC_SECRET` | `th-hotel-superagent-debug-20260709-change-before-prod` | dev/test 联调临时 HMAC 密钥;生产上线前必须更换为新的高强度随机密钥。 |
@@ -45,7 +45,7 @@
| Header | 是否必填 | 中文说明 |
| --- | --- | --- |
| `Content-Type` | 是 | 固定 `application/json` |
| `Content-Type` | 是 | 查询接口固定 `application/json`;任务结果通知接口支持 `application/json``text/plain` |
| `X-TH-Hotel-SuperAgent-Client-Id` | 是 | SuperAgent 调用方客户端 ID |
| `X-TH-Hotel-SuperAgent-Timestamp` | 是 | UTC ISO-8601 时间,例如 `2026-07-08T01:30:00Z` |
| `X-TH-Hotel-SuperAgent-Nonce` | 是 | 每次请求唯一随机值,用于防重放 |
@@ -81,14 +81,14 @@ X-TH-Hotel-SuperAgent-Signature: sha256=<lowercase-hex-signature>
### 2.3 服务端校验顺序
1. 校验请求体大小。
2. 校验 HMAC 相关 Header 是否存在
3. 校验 timestamp 是否在允许时间窗口内
4. 计算原始请求体 SHA-256
5. 使用共享 secret 重新计算 HMAC
6. 常量时间比较签名
7. 校验并记录 `client_id + nonce`,防止重放
8. 查询接口校验 `Content-Type` 是否为 `application/json`
9. 鉴权和协议校验通过后再解析业务 JSON。
2. 查询接口校验 `Content-Type` 是否为 `application/json`;任务结果通知接口校验是否为 `application/json``text/plain`,不支持的媒体类型不消耗 nonce
3. 校验 HMAC 相关 Header 是否存在
4. 校验 timestamp 是否在允许时间窗口内
5. 计算原始请求体 SHA-256
6. 使用共享 secret 重新计算 HMAC
7. 常量时间比较签名
8. 校验并记录 `client_id + nonce`,防止重放
9. 鉴权和协议校验通过后再解析业务 JSON 或 S000/S999 文本结果
## 3. SourceMessage ID 口径
@@ -437,10 +437,10 @@ SuperAgent 不应知道或依赖内部 SourceMessage Inbox ID。任务结果通
| Method | `POST` |
| URL | `{TH_HOTEL_API_BASE_URL}/api/integrations/superagent/task-results` |
| request_path | `/api/integrations/superagent/task-results` |
| Content-Type | `application/json` |
| 业务动作 | 接收 AI 任务结果,写入 AI 过渡层、订单任务任务 |
| Content-Type | `application/json``text/plain` |
| 业务动作 | 接收 AI 任务结果JSON 写入业务订单任务S000/S999 创建只读特殊任务 |
### 8.2 请求体
### 8.2 JSON 请求体
```json
{
@@ -487,7 +487,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` | 否 | 订单关联候选键 |
@@ -495,7 +495,33 @@ SuperAgent 不应知道或依赖内部 SourceMessage Inbox 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 正式契约。
### 8.3 成功响应
`informational_message` 结构化任务仅用于历史兼容。新入口如果是纯信息类邮件或无法形成业务素材包,不要提交空数组,也不要生成 `informational_message`;应使用下面的 S000/S999 文本请求体。
### 8.3 S000/S999 文本请求体
纯信息类邮件:
```text
S000,mail-20260708-0001
```
无法形成业务素材包:
```text
S999,mail-20260708-0001
```
字段规则:
| 片段 | 中文说明 |
| --- | --- |
| `S000` | 纯信息类邮件,不需要形成业务任务。 |
| `S999` | 入口阶段无法形成业务素材包,不需要进入业务执行。 |
| `mail-20260708-0001` | 外部来源消息 ID对应 SourceMessage Inbox 的 `external_message_id`。 |
第一版 S000/S999 不在 body 里传 `hotel_id`,后端使用系统默认酒店 `AGENTBUS_DEFAULT_HOTEL_ID` 查询 SourceMessage Inbox。命中后创建 `SOURCE_MESSAGE_ONLY` 只读特殊任务:任务列表可见,订单列表不可见,不允许编辑、确认、转换订单、执行 OPERA 或重试 OPERA也不参与同订单任务执行顺序阻塞。
### 8.4 成功响应
```json
{
@@ -522,6 +548,33 @@ SuperAgent 不应知道或依赖内部 SourceMessage Inbox ID。任务结果通
}
```
S000/S999 成功响应示例:
```json
{
"request_id": "req-004",
"source_message_id": "mail-20260708-0001",
"batch_id": "1900000000000000500",
"idempotent_replay": false,
"accepted_count": 1,
"items": [
{
"source_event_index": 1,
"array_index": 1,
"ai_transition_id": "1900000000000000550",
"order_id": "1900000000000000600",
"task_id": "1900000000000000700",
"system_task_type": "SOURCE_MESSAGE_ONLY",
"task_card_type": "SOURCE_MESSAGE_ONLY",
"task_status": "COMPLETED",
"order_status": "TEMPORARY",
"execution_order": 1
}
],
"warnings": []
}
```
## 9. 错误响应
### 9.1 查询接口错误响应
@@ -562,13 +615,13 @@ SuperAgent 不应知道或依赖内部 SourceMessage Inbox ID。任务结果通
| `AUTH_SIGNATURE_INVALID` | 401 | 签名不匹配或服务端未配置 secret |
| `AUTH_NONCE_REPLAY` | 409 | nonce 已被使用 |
| `REQUEST_BODY_TOO_LARGE` | 413 | 请求体超过大小限制 |
| `REQUEST_CONTENT_TYPE_UNSUPPORTED` | 415 | `Content-Type` 不是 `application/json` |
| `REQUEST_BODY_INVALID` | 400 | JSON 不合法 |
| `REQUEST_CONTENT_TYPE_UNSUPPORTED` | 415 | 查询接口 `Content-Type` 不是 `application/json`,或任务结果通知接口不是 `application/json` / `text/plain` |
| `REQUEST_BODY_INVALID` | 400 | JSON 不合法,或 S000/S999 文本格式不符合 `结果码,source_message_id` |
| `QUERY_KEY_REQUIRED` | 400 | 查询接口缺少可用业务 key |
| `MESSAGE_CONVERSATION_QUERY_KEY_REQUIRED` | 400 | 会话查询缺少 `external_conversation_id``source_message_id` |
| `OBJECT_NOT_FOUND` | 404 | 对象详情查询目标不存在 |
| `MESSAGE_CONVERSATION_NOT_FOUND` | 404 | 外部邮件会话尚未写入 SourceMessage Inbox |
| `HOTEL_ID_REQUIRED` | 400 | 五个 SuperAgent 接口缺少必填 `hotel_id` |
| `HOTEL_ID_REQUIRED` | 400 | 查询接口和 JSON 任务结果缺少必填 `hotel_id`S000/S999 使用系统默认酒店 |
| `SOURCE_MESSAGE_NOT_FOUND` | 404 | 任务结果通知或会话锚点引用的外部来源消息尚未写入 SourceMessage Inbox |
## 10. HMAC 上线配置