M7:形仪与语音——真形锚点、候选定相、声音档案与克隆授权、ASR 接入
- 形仪域 domains/xingyi:form_anchors(稳定辨识特征/年龄表现/许可禁忌/可变范围——生成内容不可静默覆盖锚点);forms(主仪/化仪/文字形仪,candidate→adopt 定相治理:未定相不进呈现位、主仪唯一、新主仪自动退役旧主仪);voice_profiles(三来源,授权克隆必填用途与传播范围,revoke-grant 撤回立即生效,assert-usable 合成前置校验拒绝撤回/过期) - ASR:元炁 SenseVoice /v1/audio/transcriptions 透传(Whisper 兼容 multipart);YUANQI_BASE_URL 未配置时 503 不降级不伪造——多模态关闭纪律 - 前端形仪工坊(人物详情页):真形锚点编辑(特征逐行解析)/候选登记定相废弃/声音档案建立与授权撤回;头像呈现位改走定相主仪(forms/primary);xingyi api 库 + mock + 组件 4 用例 - 退役:旧 avatar 模块(services/endpoints/avatar、avatar_dir 配置、avatar_url 字段、前端直传组件与测试) - 验收(test_m7_xingyi 三用例):未定相不成为正式形仪(含主仪唯一与旧主仪 retired 断言);克隆授权可撤回(缺用途拒/撤回即拒/过期同理/预设不受约束);关闭全部多模态后文字相伴完整可用(ASR 503 时镜树缘契百工照常——回归) - 四套件:后端 376、前端 203、BFF 4、神识 5 包全绿(2 个预存环境失败不变);迁移 008 净库+±1 干净
This commit is contained in:
1 parent
7e23d6fa84
commit
b419e0afde
30 files changed
+1876
-468
No files matched your search
@@ -82,6 +82,116 @@ export function resolveMock(
|
||||
// —— 健康检查 ——
|
||||
if (m === "GET" && path === "/health") return ok(data.health);
|
||||
|
||||
// —— 形仪:真形锚点 / 形仪候选 / 声音档案 ——
|
||||
{
|
||||
const m1 = path.match(/^\/characters\/([^/]+)\/form-anchor$/);
|
||||
if (m1 && (m === "GET" || m === "PATCH" || m === "PUT")) {
|
||||
return ok({
|
||||
character_id: m1[1],
|
||||
features: { 发色: "月白", 瞳色: "琥珀" },
|
||||
age_presentation: "adult",
|
||||
permissions: { 画风: "水墨" },
|
||||
mutable_scope: { 服装: "可变", 表情: "可变" },
|
||||
});
|
||||
}
|
||||
}
|
||||
{
|
||||
const m2 = path.match(/^\/characters\/([^/]+)\/forms\/primary$/);
|
||||
if (m2 && m === "GET") {
|
||||
return ok({
|
||||
id: "form_mock_001",
|
||||
character_id: m2[1],
|
||||
kind: "primary",
|
||||
status: "adopted",
|
||||
source: "image_gen",
|
||||
description: "月白长衫立绘",
|
||||
media_ref: null,
|
||||
live2d: {},
|
||||
created_at: "2026-08-27T10:00:00Z",
|
||||
adopted_at: "2026-08-27T10:05:00Z",
|
||||
});
|
||||
}
|
||||
}
|
||||
{
|
||||
const m3 = path.match(/^\/characters\/([^/]+)\/forms$/);
|
||||
if (m3 && m === "GET") {
|
||||
return ok([
|
||||
{
|
||||
id: "form_mock_001",
|
||||
character_id: m3[1],
|
||||
kind: "primary",
|
||||
status: "adopted",
|
||||
source: "image_gen",
|
||||
description: "月白长衫立绘",
|
||||
media_ref: null,
|
||||
live2d: {},
|
||||
created_at: "2026-08-27T10:00:00Z",
|
||||
adopted_at: "2026-08-27T10:05:00Z",
|
||||
},
|
||||
{
|
||||
id: "form_mock_002",
|
||||
character_id: m3[1],
|
||||
kind: "costume",
|
||||
status: "candidate",
|
||||
source: "upload",
|
||||
description: "雪夜披氅(候选)",
|
||||
media_ref: null,
|
||||
live2d: {},
|
||||
created_at: "2026-08-27T11:00:00Z",
|
||||
adopted_at: null,
|
||||
},
|
||||
]);
|
||||
}
|
||||
if (m3 && m === "POST") {
|
||||
return ok({ id: "form_mock_003", status: "candidate" }, 201);
|
||||
}
|
||||
}
|
||||
{
|
||||
const m4 = path.match(
|
||||
/^\/characters\/([^/]+)\/forms\/([^/]+)\/(adopt|discard)$/,
|
||||
);
|
||||
if (m4 && m === "POST") {
|
||||
return ok({
|
||||
id: m4[2],
|
||||
status: m4[3] === "adopt" ? "adopted" : "discarded",
|
||||
});
|
||||
}
|
||||
}
|
||||
{
|
||||
const m5 = path.match(/^\/characters\/([^/]+)\/voices$/);
|
||||
if (m5 && m === "GET") {
|
||||
return ok([
|
||||
{
|
||||
id: "voice_mock_001",
|
||||
character_id: m5[1],
|
||||
source: "synthesis_preset",
|
||||
name: "预设音色 A",
|
||||
params: { timbre: "warm" },
|
||||
grant_purpose: null,
|
||||
grant_expires_at: null,
|
||||
grant_distribution: null,
|
||||
grant_revoked_at: null,
|
||||
is_active: true,
|
||||
},
|
||||
]);
|
||||
}
|
||||
if (m5 && m === "POST") {
|
||||
return ok({ id: "voice_mock_002", status: "created" }, 201);
|
||||
}
|
||||
}
|
||||
{
|
||||
const m6 = path.match(
|
||||
/^\/characters\/([^/]+)\/voices\/([^/]+)\/revoke-grant$/,
|
||||
);
|
||||
if (m6 && m === "POST") {
|
||||
return ok({
|
||||
voice_id: m6[2],
|
||||
grant_revoked: true,
|
||||
effective: "immediate",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// —— 百工:能力目录 / 授契 / 请命 / 行动账 ——
|
||||
if (m === "GET" && path === "/capabilities") {
|
||||
return ok([
|
||||
|
||||
Reference in new issue
Block a user