diff --git a/game-cloud/game-module-aigc/game-module-aigc-server/src/main/java/com/wanxiang/huijing/game/module/aigc/saa/SaaGraphDispatcher.java b/game-cloud/game-module-aigc/game-module-aigc-server/src/main/java/com/wanxiang/huijing/game/module/aigc/saa/SaaGraphDispatcher.java index 08481ee3..71888931 100644 --- a/game-cloud/game-module-aigc/game-module-aigc-server/src/main/java/com/wanxiang/huijing/game/module/aigc/saa/SaaGraphDispatcher.java +++ b/game-cloud/game-module-aigc/game-module-aigc-server/src/main/java/com/wanxiang/huijing/game/module/aigc/saa/SaaGraphDispatcher.java @@ -609,7 +609,14 @@ public class SaaGraphDispatcher implements GenerationDispatcher { DifyCallbackReqVO reqVO = new DifyCallbackReqVO(); reqVO.setTraceId(traceId); reqVO.setTemplateId(templateId); - reqVO.setAssets(java.util.Collections.emptyList()); + // ── U2/B8 消费侧(§5.2 产消接通):忠实取已落库源 assets[](六类源资产)填充包级 assets,替代历史硬置空。 ── + // 兑现 SaaStudioNodes 处自标的「engine-E2/E3 消费侧本期不做」TODO:源 asset 节点已产 assets[6] + // (schemaVersion+gameDefinition+顶层 assets,落 game_source_project.source_json),此处把同批源 assets + // 忠实带进 GamePackage.assets(DifyCallbackTxService.buildGamePackage 读 reqVO.getAssets()),闭合产消断链。 + // 形态注记:源 assetSpec={id,category,ref,provider}(source-project.schema.json #/$defs/assetSpec,运行时 + // gd-runtime 经 gdef.assets 同形消费);geom: ref 为几何占位资产引用,原样透传不伪造 type/hash/bytes/mime。 + // 空/缺/非数组源 assets → 回退空集(不抛):严格非破坏,存量无源回调字节零变。 + reqVO.setAssets(extractSourceAssets(s, traceId)); // gameConfig 最小合法占位(engine 路游戏逻辑全在 engineBundle,gameConfig 仍不可空:GamePackage required)。 Map gameConfig = new LinkedHashMap<>(); gameConfig.put("templateId", templateId); // 须与包级 templateId 一致(一致性校验) @@ -763,6 +770,55 @@ public class SaaGraphDispatcher implements GenerationDispatcher { } } + /** + * U2/B8 消费侧(§5.2 产消接通):从图终态 {@code K_SOURCE_PROJECT} 抽顶层 {@code assets[]} 映射为包级 assets。 + * + *

兑现 TODO:源 asset 节点已把六类源资产写入 {@code sourceProject} 顶层 {@code assets} + * ({@code source-project.schema.json #/$defs/assetSpec},形态 {@code {id,category,ref,provider}}),历史上组包侧 + * 硬置空集导致产消断链;本方法把同一批源 assets 忠实搬进 {@link DifyCallbackReqVO#getAssets()}, + * 由 {@code DifyCallbackTxService.buildGamePackage} 落进 {@code GamePackage.assets}。运行时 {@code gd-runtime} + * 经 {@code gdef.assets}(同 source assetSpec 形态)消费,故原样透传不重塑:{@code geom:} 为几何占位 + * 资产引用,不伪造包契约 strict AssetSpec 的 {@code type/url/hash/bytes/mime}(无真图、无真 sha256,伪造即脏数据)。 + * + *

best-effort 非阻断(严格 additive):源缺失/空白/非 JSON/无 assets 键/assets 非数组/任意异常 → + * 一律返回空集(绝不外抛、绝不打断 SAA 生成),与历史「恒空集」对存量无源回调字节零变化。 + * + * @param s 图终态(可能 null) + * @param traceId 贯穿键(仅日志) + * @return 源 assets 映射出的 {@code List>}(忠实透传字段);无/异常时空集(非 null) + */ + private static java.util.List> extractSourceAssets(OverAllState s, String traceId) { + if (s == null) { + return java.util.Collections.emptyList(); + } + try { + // 复用 best-effort 宽松解析(null/空白/非法 JSON → null);源串即 §5.2 落库的 source_json。 + JsonNode root = parseTrace(s.value(SaaStudioNodes.K_SOURCE_PROJECT, String.class).orElse("")); + if (root == null) { + return java.util.Collections.emptyList(); + } + JsonNode assets = root.path("assets"); + if (!assets.isArray() || assets.isEmpty()) { + // 无 assets 键 / 非数组 / 空数组 → 回退空集(不抛,存量无源回调字节零变)。 + return java.util.Collections.emptyList(); + } + // 逐项忠实映射为 Map(保 {id,category,ref,provider} 等全部源字段;geom: ref 原样);非对象项跳过(防御脏数据)。 + java.util.List> out = new java.util.ArrayList<>(assets.size()); + for (JsonNode a : assets) { + if (a != null && a.isObject()) { + out.add(TRACE_MAPPER.convertValue(a, new com.fasterxml.jackson.core.type.TypeReference>() {})); + } + } + // 可追溯日志:接通了几个源 assets(0 表示源里确无对象项,等价历史空集,不告警)。 + log.info("[saa-dispatch] 包级 assets 接通源 assets[] 共 {} 个(产消接通,兑现 engine-E2/E3 消费侧 TODO)traceId={}", out.size(), traceId); + return out; + } catch (Exception e) { + // 命门:抽取/映射异常一律吞 + warn 返空集,绝不打断 SAA 生成(生成成败由 status/engineBundle 既有逻辑决定)。 + log.warn("[saa-dispatch] 源 assets 抽取失败,包级 assets 回退空集(不阻断生成)traceId={}", traceId, e); + return java.util.Collections.emptyList(); + } + } + /** * 派生 models 并集:{@code K_TOKENS_BY_MODEL} 的 model 名键集 ∪ {@code K_ATTEMPTS[].{role:model}},组同形 {role:model} map。 *