# 更新云端任务

## 基本信息

| 名称 | 描述 |
| --- | --- |
| HTTP Path | `/api/task/v1/developer/update_remote_task` |
| HTTP Method | POST |
| Content-Type | `application/json` |
| 鉴权 | `X-DB-AccessToken` + 最新 push token |

更新任务使用创建或上一次运行中更新返回的 push token。运行中更新后保存响应中的 `next_push_token` 并作为后续首选凭证。当前 token 按签名和到期时间校验；返回新 token 不等于立即撤销旧 token。

## 请求头

| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `X-DB-AccessToken` | 是 | 使用 AppID/AppSecret 获取的应用级 Token |
| `Content-Type` | 是 | 固定为 `application/json` |

## 请求体

| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `push_token` | 是 | 当前任务最新推送凭证 |
| `task_status` | 条件必填 | 状态更新；当前任务完成使用 `completed` |
| `task_detail` | 条件必填 | JSON 字符串；更新展示、进度、变量、跳转或有效期 |

`task_status` 和 `task_detail` 至少提供一项。更新业务模板任务时，`task_detail` 解析后的结构与创建接口一致：

```json
{
  "expire_in_sec": 1800,
  "display_data": {
    "title_scene_key": "preparing_title",
    "sub_title_scene_key": "preparing_subtitle"
  },
  "progress_data": {
    "progress": 70,
    "text_scene_key": "preparing_progress",
    "remaining_seconds": 60
  },
  "variables": {
    "name": "珍珠奶茶",
    "pickup_code": "A018",
    "minutes": "1"
  }
}
```

如果变量变化会影响已展示文案，同一请求重新携带对应 scene key。只传新的 variables 不保证已经固化的文案自动重新渲染。

## 更新进度示例

```bash
curl -X POST 'https://hello.doubao-dev.com/api/task/v1/developer/update_remote_task' \
  -H 'X-DB-AccessToken: <access_token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "push_token": "<latest_push_token>",
    "task_detail": "{\"expire_in_sec\":1800,\"display_data\":{\"title_scene_key\":\"preparing_title\",\"sub_title_scene_key\":\"preparing_subtitle\"},\"progress_data\":{\"progress\":70,\"text_scene_key\":\"preparing_progress\",\"remaining_seconds\":60},\"variables\":{\"name\":\"珍珠奶茶\",\"pickup_code\":\"A018\",\"minutes\":\"1\"}}"
  }'
```

## 完成任务示例

```json
{
  "push_token": "<latest_push_token>",
  "task_status": "completed"
}
```

当前实现中 completed 把任务更新为 SUCCESS/HIDDEN，忽略同一请求中的 `task_detail`，并且不返回 next token。需要先展示 100% 或最终文案时，先做一次 running 更新，再单独完成。只在业务任务真实完成后设置 completed，不要根据前端关闭、MCP Tool 返回或进度数值自动推断完成。

## 响应

| 字段 | 说明 |
| --- | --- |
| `code` | `0` 表示业务成功 |
| `msg` | 结果说明 |
| `log_id` | 平台排障 ID |
| `data.next_push_token.token` | 运行中更新返回的后续首选 token；completed 时为空 |
| `data.next_push_token.expires_in` | 运行中 token 有效期，单位秒 |

示例：

```json
{
  "code": 0,
  "msg": "success",
  "log_id": "202607220002",
  "data": {
    "next_push_token": {
      "token": "pt_yyyyyyyyyyyyyyyy",
      "expires_in": 86400
    }
  }
}
```

## Token 轮换和并发

1. 从持久化读取当前首选 token、到期时间和更新版本。
2. 使用该 token 调用更新接口。
3. 运行中更新 `code == 0` 且 `next_push_token.token` 非空时，按旧版本做原子条件更新。
4. completed 成功时保存终态，允许 `next_push_token` 为空。
5. 条件更新失败表示另一请求已提交更新；重新读取最新记录，不用最后到达者简单覆盖。
6. 修改 `expire_in_sec` 时，新 token 使用新的到期时间；旧 token 可能在原到期前仍有效，业务不能把这当作并发控制机制。

不要在普通日志中记录 push token。只记录脱敏任务标识、模板、进度、状态、token 版本、结果码和 `log_id`。

## 运行时校验

- AccessToken 必须属于任务所在应用。
- push token 必须是该任务当前有效 token。
- `progress` 在 `0–100`。
- scene key 属于任务创建时绑定的模板。
- variables 是字符串 map，并满足本次所选文案需要。
- `expire_in_sec` 只在需要从本次更新重新计算有效期时提供。
- completed 等终态只能由可信业务事实触发。

调用完整流程和 Sandbox 验证读取 [多任务管理接入指南](../../../task-management.md)。
