7.8 KiB
M4 module-ai Axum facade 设计(2026-04-22)
更新时间:2026-04-22
0. 文档目标
本文件只冻结一件事:
把已经在 spacetime-module 落地的 module-ai 任务真相表与最小 procedure / reducer,继续向上接到 shared-contracts、spacetime-client 与 api-server,形成可由 HTTP 直接调用的 AI task mutation facade。
本轮只做最小同步 mutation 链,不扩到 SSE、真实模型供应商请求或前端订阅。
1. 本轮要解决的问题
当前仓库已经具备:
module-ai- 统一
AiTaskKind / AiTaskStageKind / AiResultReferenceKind - 统一任务、阶段、文本片段、结果引用领域模型
- 统一
spacetime-moduleai_task / ai_task_stage / ai_text_chunk / ai_result_referencecreate / append / complete / attach / fail / cancel最小 procedurestart_ai_task / start_ai_task_stagereducer
spacetime-client- 已生成 AI 相关 Rust bindings
但当前仍缺三层:
shared-contracts还没有 AI task HTTP DTOspacetime-client还没有 AI facade 方法与 record 映射api-server还没有/api/ai/tasks*路由
因此本轮只补下面三层:
shared-contractsAI DTOspacetime-clientAI facadeapi-serverAI tasks HTTP route
2. 当前明确不做的事
本轮明确不做:
- 不接入真实
platform-llm流式回调 - 不提供 SSE 增量推送接口
- 不增加 AI task 查询 / 订阅 projection
- 不把 story / npc / quest / custom-world 旧入口自动迁到这组新接口
- 不修改
spacetime-client/src/module_bindings/*生成文件
原因很直接:
- 当前先把 AI task mutation 的最小 HTTP contract 固定下来
- SSE 与查询态必须等待后续订阅策略或 query procedure 冻结
- 业务编排入口切换应该在上层模块各自评估,不在本轮提前硬迁
3. 路由冻结
本轮首版新增以下路由:
POST /api/ai/tasksPOST /api/ai/tasks/{taskId}/startPOST /api/ai/tasks/{taskId}/stages/{stageKind}/startPOST /api/ai/tasks/{taskId}/chunksPOST /api/ai/tasks/{taskId}/stages/{stageKind}/completePOST /api/ai/tasks/{taskId}/referencesPOST /api/ai/tasks/{taskId}/completePOST /api/ai/tasks/{taskId}/failPOST /api/ai/tasks/{taskId}/cancel
3.1 同步返回路由
当前下列路由走 procedure,成功时同步返回 aiTask 快照:
POST /api/ai/tasksPOST /api/ai/tasks/{taskId}/chunksPOST /api/ai/tasks/{taskId}/stages/{stageKind}/completePOST /api/ai/tasks/{taskId}/referencesPOST /api/ai/tasks/{taskId}/completePOST /api/ai/tasks/{taskId}/failPOST /api/ai/tasks/{taskId}/cancel
其中:
chunks额外返回aiTextChunk- 其他 mutation 当前只返回
aiTask
3.2 Accepted 路由
当前下列路由只接 reducer,不会同步返回快照:
POST /api/ai/tasks/{taskId}/startPOST /api/ai/tasks/{taskId}/stages/{stageKind}/start
因此本轮明确冻结为:
- HTTP 成功状态码返回
202 Accepted - body 只返回:
acceptedtaskIdactionstageKind(仅 stage start)
- 不伪装成“已经拿到最新任务快照”
后续如果要让这两条路由也同步返回快照,应先在 spacetime-module 增加对应 procedure。
4. 请求与响应 DTO 冻结
4.1 创建任务请求
POST /api/ai/tasks 请求体冻结为:
taskKindrequestLabelsourceModulesourceEntityIdrequestPayloadJsonstageKinds
其中:
taskId不接受外部写入,由 Axum 使用generate_ai_task_id(nowMicros)生成ownerUserId不接受外部写入,必须取自 Bearer tokenstageKinds为空时,由module-ai根据taskKind.default_stage_blueprints()自动补齐默认阶段蓝图
4.2 追加文本片段请求
POST /api/ai/tasks/{taskId}/chunks 请求体冻结为:
stageKindsequencedeltaText
4.3 完成阶段请求
POST /api/ai/tasks/{taskId}/stages/{stageKind}/complete 请求体冻结为:
textOutputstructuredPayloadJsonwarningMessages
4.4 绑定结果引用请求
POST /api/ai/tasks/{taskId}/references 请求体冻结为:
referenceKindreferenceIdlabel
4.5 失败请求
POST /api/ai/tasks/{taskId}/fail 请求体冻结为:
failureMessage
4.6 成功响应
本轮统一返回以下 payload:
AiTaskPayloadAiTaskStagePayloadAiResultReferencePayloadAiTextChunkPayloadAiTaskMutationResponseAiTaskAcceptedResponse
时间字段继续统一为 RFC3339 字符串。
5. spacetime-client 冻结口径
本轮新增以下 facade:
create_ai_taskstart_ai_taskstart_ai_task_stageappend_ai_text_chunkcomplete_ai_stageattach_ai_result_referencecomplete_ai_taskfail_ai_taskcancel_ai_task
5.1 输入边界
- procedure 输入直接复用
module-ai领域输入结构 start_ai_task与start_ai_task_stage直接复用 reducer 输入结构- 不让
api-server直接依赖 generated binding 类型
5.2 输出边界
spacetime-client 新增下列 record,供 api-server 直接消费:
AiTaskRecordAiTaskStageRecordAiTextChunkRecordAiResultReferenceRecordAiTaskMutationRecord
字符串字段规范:
taskKind使用:story_generationcharacter_chatnpc_chatcustom_world_generationquest_intentruntime_item_intent
stageKind使用module-ai::AiTaskStageKind::as_str()status使用 snake_casereferenceKind使用 snake_case
5.3 错误映射
AI facade 在 spacetime-client 内部按以下规则区分:
- procedure / reducer 返回的业务拒绝
- 映射为
SpacetimeClientError::Runtime
- 映射为
- SDK 调用、连接、超时、意外缺字段
- 映射为
Build / Procedure / ConnectDropped / Timeout
- 映射为
这样 api-server 才能稳定把业务错误映射成 400。
6. api-server 冻结口径
6.1 鉴权与身份
所有 /api/ai/tasks* 路由继续统一挂 Bearer 鉴权。
其中:
ownerUserId必须来自AuthenticatedAccessToken.claims().user_id()- 不接受前端自行写入任务所有者
6.2 时间与 ID
以下字段不接受外部写入:
taskIdcreatedAtMicrosstartedAtMicroscompletedAtMicros
统一由 Axum 在请求进入时生成。
6.3 字段解析
api-server 负责把 HTTP 字符串解析为领域枚举:
taskKindstageKindreferenceKind
解析失败统一返回 400,details.provider 分别写:
ai-taskai-task-stageai-task-reference
7. 错误映射
本轮 AI facade 的错误策略冻结如下:
- 请求 JSON 非法、路径字段非法、枚举解析失败:
400 SpacetimeClientError::Runtime(_):400- 其他
SpacetimeClientError:502
details.provider 统一写:
- 路由入参准备错误:
ai-task - SpacetimeDB 上游错误:
spacetimedb
8. 本轮验收口径
满足以下条件,视为本轮 facade 基线完成:
shared-contracts已新增ai.rsspacetime-client已新增 AI facade 方法与 record 映射api-server已新增ai_tasks.rs/api/ai/tasks*路由已注册并挂 Bearer 鉴权cargo fmt -p shared-contracts -p spacetime-client -p api-server通过cargo check -p shared-contracts -p spacetime-client -p api-server通过
9. 下一步建议
本轮完成后,后续最稳的顺序是:
- 为
start_ai_task / start_ai_task_stage增加同步 procedure - 增加 AI task 查询态或订阅 projection
- 再把
platform-llm流式回调真正接到append_ai_text_chunk / complete_ai_stage / fail_ai_task - 最后再把 story / npc / custom-world / quest / runtime-item 的 AI 编排主链逐步切到这组新接口