zizi b70e90b775 feat(wave3-phaseB): compliance/studio 模块 + contractGaps(后端全绿)
Phase B 并行建(4 路互斥目录),主 agent 合并 reactor 验证:
- compliance(109/V9):ComplianceGateApi.evaluate seam + 风格原子桩(StyleComplianceAtom/IpComplianceSeam)
  + 分级 + 封禁(R3 状态分支,下架联动留 Phase C)+ V9 DDL(gate_result/content_rating/user_ban,不建审核状态机表 D2)
- studio(112/V8):创作任务链(createDraft→project.createProject / generate→aigc)+ attachments 持久化-only
  + 新增 AigcApi seam(additive)+ V8 DDL
- contractGaps 后端:GAP-3 feed ShareMeta versionId(调 getCurrentVersionId 仅已发布)、GAP-2 runtime manifestUrl(纯派生零DDL)
- contractGaps 前端 game-studio:GAP-1 publish admitted/gates、GAP-3 share→play versionId、GAP-2 取包 manifestUrl+sha256
- 合并验证:全 53 模块 reactor 编译 SUCCESS;新/改模块单测全绿(compliance8/studio11/feed12/runtime24)
- 注:前端 game-studio build 待 mini-desktop 验;Phase C 待接入 project.publish→ComplianceGateApi

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 02:15:20 +00:00

187 lines
11 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

openapi: 3.0.3
# 契约 #1 API | 模块:studio(game-module-studio,Wave3 创作主链路最小版)| owner:studio 路
# 职责(架构 Doc B §71-76):有状态创作工作台后端。编排「建草稿(委托 project createProject)→一句话生成(委托 aigc)
# →进度轮询→重生成→模板应用」。不跑 LLM(委托 aigc)、不持久化项目版本(交 project)、不做锁风裁决(调 compliance)。
# 与 game-studio 前端仓区分:本契约是后端 studio 模块(错误码段 112),game-studio 是产品端前端仓名,二者不同。
# 端:/app-api(产品端 game-studio,用户 Token);前缀由 yudao 框架按 controller.app 包名自动添加。
# 错误码段:studio = 1-112-***-***(R4 治理新登记,本模块独占,禁与他模块重叠:
# 100 project/101 aigc/102 runtime/103 feed/104 telemetry/105 pay/106 trade/107 community/108 ip/109 compliance/110 biz/111 ad/112 studio)
# 响应统一 Yudao CommonResult 信封:{ code, data, msg };code=0 成功。
# 编排链路(MVP 轮询非 MQ,D4):
# /template/list (透传 aigc 模板注册表) → /draft (调 project ProjectApi.createProject 拿 gameId upsert 会话)
# → /generate (调 aigc AigcApi.submitGenerate 落任务链回填 aigc_task_id) → /task/{id} (透传 aigc 进度轮询)
# → /task/{id}/regenerate (调 aigc AigcApi.retryTask 新建 retry_of 任务链)
# x-feign-contracts(studio 是调用方,依赖以下对方 -api seam,本契约不对外暴露 Feign):
# - project-api ProjectApi.createProject(creatorUserId, title, templateId) → gameId(写类 RPC,显式 creatorUserId,归属校验在 project service)
# - aigc-api AigcApi.submitGenerate / getTask / retryTask / getTemplateList(Wave3 新增 seam,纯暴露层委托 AigcTaskService)
# attachments(R7):StudioGenerateReqVO.attachments 本波仅持久化(studio 侧落库),不透传 aigc(aigc reqDTO 无 attachments 字段);P1 再透传。
# 狠切留 seam 不实现(P1):rig/对白树/可视化批量;资产图仅槽位表(game_studio_asset)+ 单步调度,不六路并发。
info:
title: 造梦AI studio 模块 API
version: 1.0.0
description: >-
创作主链路最小版("做得出"工作台)。创作者进工作坊建草稿(移交 project 建游戏拿 gameId)→ 一句话生成(委托 aigc)→
轮询进度直至终态(透传 aigc)→ 失败可重生成(委托 aigc retryTask)。MVP 轮询非 MQ;前端据此 vite-plugin-mock 自动生成 mock。
servers:
- url: http://localhost:48080
description: 本地(Swagger/Knife4j http://localhost:48080/doc.html)
paths:
# ===========================================================================
# 产品端 /app-api(创作工作台,用户 Token)
# ===========================================================================
/app-api/studio/template/list:
get:
tags: [app-studio]
summary: 玩法模板列表(模板浏览/应用 P-TPL-01/03,透传 aigc 模板注册表)
description: 透传 aigc 模板注册表(T-AGC-03);MVP 骨架返回空列表占位,待模板注册表接入。
responses:
'200':
description: 成功(玩法模板列表)
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultStudioTemplateList' }
/app-api/studio/draft:
post:
tags: [app-studio]
summary: 建草稿(进工作坊 P-CRT-10 + 草稿移交 project P-TPL-03)
description: >-
编排:服务端调 project ProjectApi.createProject(creatorUserId=当前登录用户, title, templateId) 建游戏拿 gameId
回写会话,再落会话(status=0 草稿)。attachments 仅持久化(R7)。createProject 是硬前置,返回空 gameId 视为移交失败。
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/StudioDraftCreateReqVO' }
responses:
'200':
description: 成功(新建会话,含回写的 gameId)
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultStudioSession' }
/app-api/studio/generate:
post:
tags: [app-studio]
summary: 一句话生成(P-CRT-01,委托 aigc 提交生成)
description: >-
编排:校验 session 归属 → 落任务链(status=1 生成中) → 委托 aigc AigcApi.submitGenerate(带 prompt/templateId/gameId/userId)
→ 回填 aigc_task_id → 立即返回任务链句柄,前端据 taskChainId 轮询。同步直写无 MQ(D4)。
attachments 仅持久化(R7),不入 aigc reqDTO。
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/StudioGenerateReqVO' }
responses:
'200':
description: 成功(任务链句柄,含 aigc_task_id)
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultStudioTaskChain' }
/app-api/studio/task/{id}:
get:
tags: [app-studio]
summary: 进度轮询(P-CRT-12,透传 aigc 进度/状态)
description: >-
编排:校验任务链归属 → 委托 aigc AigcApi.getTask 取进度/状态 → 映射链态
(aigc succeeded → 链完成回填 version_id + 会话完成;failed/timed_out → 链失败 + 会话失败;其余保持生成中仅回写 progress)。
parameters:
- { name: id, in: path, required: true, schema: { type: integer, format: int64 }, description: '创作任务链 ID(taskChainId)' }
responses:
'200':
description: 成功(任务链最新态,完成后 versionId 非空)
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultStudioTaskChain' }
/app-api/studio/task/{id}/regenerate:
post:
tags: [app-studio]
summary: 重生成迭代(P-CRT-09,委托 aigc retryTask)
description: 编排:校验原任务链归属 → 委托 aigc AigcApi.retryTask 重提生成 → 新建一条任务链(retry_of=原 id)回填新 aigc_task_id。
parameters:
- { name: id, in: path, required: true, schema: { type: integer, format: int64 }, description: '原创作任务链 ID' }
responses:
'200':
description: 成功(新建的重试任务链句柄)
content:
application/json:
schema: { $ref: '#/components/schemas/CommonResultStudioTaskChain' }
components:
schemas:
# ========== 请求 VO ==========
StudioDraftCreateReqVO:
type: object
required: [title, templateId]
properties:
title: { type: string, maxLength: 128, description: '作品标题(透传 project createProject)', example: '我的放置小镇' }
templateId: { type: string, description: '玩法模板 ID(透传 project/aigc)', example: 'idle' }
prompt: { type: string, maxLength: 1000, description: '一句话 Prompt(建草稿可空,generate 必填)', example: '做一个躲避陨石的小游戏' }
attachments: { type: string, description: '附件上下文 JSON(P-CRT-04);本波仅持久化,P1 透传 aigc' }
StudioGenerateReqVO:
type: object
required: [sessionId, prompt]
properties:
sessionId: { type: integer, format: int64, description: '创作会话 ID(建草稿返回的 sessionId)', example: 1024 }
prompt: { type: string, maxLength: 1000, description: '一句话 Prompt(透传 aigc submitGenerate)', example: '做一个躲避陨石的小游戏' }
attachments: { type: string, description: '附件上下文 JSON(P-CRT-04);【本波仅持久化,P1 透传 aigc】——studio 侧落库持久化,本波不透传 aigc' }
# ========== 响应 VO ==========
StudioTemplateRespVO:
type: object
description: 玩法模板(透传 aigc 模板注册表,对齐 aigc.yaml TemplateRespVO)
properties:
templateId: { type: string, description: '模板 ID', example: 'dodge' }
name: { type: string, description: '模板名称', example: '躲避' }
description: { type: string, description: '模板说明' }
coverUrl: { type: string, description: '模板封面/示意图 URL' }
examplePrompt: { type: string, description: '示例 Prompt(P-CRT-11)', example: '做一个躲避陨石的小游戏' }
StudioSessionRespVO:
type: object
properties:
id: { type: integer, format: int64, description: '创作会话 ID(sessionId)', example: 1024 }
gameId: { type: integer, format: int64, description: '移交后的游戏 ID(project.game_project.id)', example: 2048 }
templateId: { type: string, description: '玩法模板 ID', example: 'idle' }
title: { type: string, description: '作品标题', example: '我的放置小镇' }
prompt: { type: string, description: '一句话 Prompt' }
status: { type: integer, description: '会话状态:0草稿 1生成中 2完成 3失败', example: 0 }
StudioTaskChainRespVO:
type: object
properties:
id: { type: integer, format: int64, description: '创作任务链 ID(taskChainId,轮询用)', example: 1024 }
sessionId: { type: integer, format: int64, description: '所属创作会话 ID', example: 512 }
aigcTaskId: { type: integer, format: int64, description: '委托的 aigc 生成任务 ID', example: 8888 }
gameId: { type: integer, format: int64, description: '关联游戏 ID(project.game_project.id)', example: 2048 }
versionId: { type: integer, format: int64, description: '产物版本 ID(project.game_version.id);完成后非空', example: 4096 }
status: { type: integer, description: '任务链状态:0初始 1生成中 2完成 3失败', example: 1 }
progress: { type: integer, description: '进度百分比 0-100(透传 aigc)', example: 60 }
retryOf: { type: integer, format: int64, description: '若为重生成,指向原任务链 ID(P-CRT-09 血缘)', example: 1000 }
# ========== CommonResult 信封 ==========
CommonResultStudioTemplateList:
type: object
properties:
code: { type: integer, example: 0 }
data: { type: array, items: { $ref: '#/components/schemas/StudioTemplateRespVO' } }
msg: { type: string }
CommonResultStudioSession:
type: object
properties:
code: { type: integer, example: 0 }
data: { $ref: '#/components/schemas/StudioSessionRespVO' }
msg: { type: string }
CommonResultStudioTaskChain:
type: object
properties:
code: { type: integer, example: 0 }
data: { $ref: '#/components/schemas/StudioTaskChainRespVO' }
msg: { type: string }