Initial TrueGrowth source import

This commit is contained in:
2026-07-07 09:36:36 +08:00
commit 3b6781d695
2283 changed files with 691996 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
## Context
当前音频生成链路已经支持:
- `music``lyrics` 两类 Suno 提交动作
- 统一通过 `/suno/submit/music``/suno/submit/lyrics` 提交
- 统一通过 `/suno/fetch/{task_id}` 轮询
- 将音乐结果标准化为 `primaryClipId / clipIds / clips`
同时,项目已有两个关键前提:
- 爆款音乐工具倾向使用统一工作流,而不是拆散成多个独立工具
- `clip_id` 才是 Suno 续写所需的真实片段标识,不能退化成列表层的 `id`
## Goals / Non-Goals
- Goals:
- 在统一表单中支持新生成、续写、Infill 三类音乐动作
- 根据动作自动约束和显隐 `continue_clip_id / continue_at / infill_start_s / infill_end_s`
- 把轮询里发现的 `clip_id` 串到续写和 Infill 请求
- 尽量复用现有 `/suno/submit/music` 与轮询标准化逻辑
- Non-Goals:
- 本次不引入新的独立音乐编辑工具
- 本次不实现 clip 拼接 `concat`
- 本次不实现音频波形编辑器
## Decisions
- Decision: 统一入口 + 动作切换
-`GeneratePage` 中增加动作枚举,例如 `generate | continue | infill`
- 表单仍保持单页结构,但根据动作切换展示不同字段
- Decision: 参数按动作严格约束
- `generate`
- 使用 `prompt / title / tags / mv`
- 不发送 `continue_clip_id / continue_at / infill_start_s / infill_end_s`
- `continue`
- 必须有 `continue_clip_id`
- 必须有 `continue_at`
- 可继续使用 `prompt / title / tags / mv`
- 不发送 `infill_start_s / infill_end_s`
- `infill`
- 必须有 `continue_clip_id`
- 必须有 `continue_at`
- 必须有 `infill_start_s / infill_end_s`
- 要求 `infill_start_s < infill_end_s`
- Decision: 续写目标优先来自已生成片段
- 每个 `GeneratedClip` 必须稳定保存轮询得到的真实 `clip_id`
- 点击片段上的“续写 / Infill”入口时自动把目标 `clip_id` 带入表单
- 若当前任务还没有真实 `clip_id`,则禁止进入续写动作
- Decision: 仍走同一 Suno submit 接口
- 三种动作都沿用 `POST /suno/submit/music`
- 通过 body 中是否携带 `continue_clip_id / continue_at / infill_start_s / infill_end_s` 决定服务端行为
## Data Model
```ts
type SunoMusicEditAction = 'generate' | 'continue' | 'infill';
interface MusicAnalysisRecord {
continueFromClipId?: string | null;
continueAt?: number | null;
infillStartS?: number | null;
infillEndS?: number | null;
musicEditAction?: SunoMusicEditAction | null;
}
interface AudioGenerationRequest {
prompt: string;
title?: string;
tags?: string;
mv?: string;
continueClipId?: string;
continueAt?: number;
params?: {
infillStartS?: number | null;
infillEndS?: number | null;
};
}
```
## UI Strategy
- 在“爆款音乐生成 -> 生成”页面增加动作切换区:
- `新生成`
- `续写`
- `Infill`
- 在已生成片段卡片上增加快捷入口:
- `续写`
- `Infill`
- 字段展示策略:
- `新生成`:标题 / 风格标签 / 歌词 / 版本 / 调用次数
- `续写`:目标片段 / 续写起点秒数 / 标题 / 风格标签 / 歌词 / 版本 / 调用次数
- `Infill`:目标片段 / 续写起点秒数 / Infill 开始秒数 / Infill 结束秒数 / 标题 / 风格标签 / 歌词 / 版本 / 调用次数
- 表单校验失败时,错误提示继续贴近提交按钮
## Risks / Trade-offs
- 风险:统一表单状态过多,切动作时容易串值
- Mitigation将动作相关字段单独建模并在切换动作时只保留兼容字段
- 风险:用户不知道 `continue_at``infill_start_s/end_s` 的区别
- MitigationUI 文案明确区分“续写起点”和“局部重绘窗口”
- 风险:早期轮询返回有 `clip_id`、最终结果缺 `clip_id`
- Mitigation在轮询层缓存并回填真实 `clip_id`
## Open Questions
- 是否需要在第一版允许手动输入 `continue_clip_id`,还是只允许从已生成片段选择
- 是否要在统一表单中直接支持“续写完成后自动拼接完整音频”,还是留到后续 `concat` 能力再做

View File

@@ -0,0 +1,58 @@
# Change: 为爆款音乐工具增加统一的续写与 Infill 动作
## Why
当前“爆款音乐工具”已经具备:
- 从零创作歌词
- 提交 Suno 音乐生成
- 轮询获取音乐生成结果
但还缺少两类核心后续编辑能力:
- 基于已生成片段继续续写
- 基于已生成片段对局部时间窗口进行 Infill
而且这些能力依赖一组强约束参数:
- `continue_clip_id`
- `continue_at`
- `infill_start_s`
- `infill_end_s`
如果只是把这些字段直接堆进现有“新生成”表单,会产生三个问题:
- 用户难以理解哪些参数在什么动作下必填
- UI 容易形成无效参数组合,例如普通生成时误填续写字段
- 续写依赖的 `clip_id` 与展示层 `id` 容易混淆,导致后续调用失败
因此需要在现有统一入口中,引入显式动作模型,并把参数约束、轮询回填和后续调用链打通。
## What Changes
- 在爆款音乐工具的统一入口下新增音乐动作选择:
- 新生成
- 续写
- Infill
- 统一沿用现有 Suno `/suno/submit/music` + `/suno/fetch/{task_id}` 链路,不拆分成独立工具
-`continue_clip_id / continue_at / infill_start_s / infill_end_s` 建立动作级参数约束与 UI 显隐规则
- 将轮询结果中的 `clip_id` 作为续写和 Infill 的真实目标 ID 持久化保存
- 在已生成片段区域增加“继续创作”入口,自动带入目标片段与默认参数
- 扩展音频请求模型与结果模型,使 unified 表单能安全表达新生成、续写、Infill 三类请求
## Impact
- Affected specs:
- `audio-generation`
- Affected code:
- `packages/drawnix/src/components/music-analyzer/pages/GeneratePage.tsx`
- `packages/drawnix/src/components/music-analyzer/types.ts`
- `packages/drawnix/src/components/music-analyzer/storage.ts`
- `packages/drawnix/src/components/music-analyzer/task-sync.ts`
- `packages/drawnix/src/services/audio-api-service.ts`
- `packages/drawnix/src/services/model-adapters/types.ts`
- `packages/drawnix/src/services/model-adapters/default-adapters.ts`
- `packages/drawnix/src/services/task-queue-service.ts`
- `packages/drawnix/src/mcp/tools/audio-generation.ts`
- `packages/drawnix/src/utils/suno-model-aliases.ts`

View File

@@ -0,0 +1,68 @@
## ADDED Requirements
### Requirement: Support Unified Suno Music Edit Actions In The Music Analyzer
The system SHALL expose Suno music generation, continuation, and infill as action variants within one unified music creation flow.
#### Scenario: User switches from generate to continue in one unified form
- **GIVEN** the user is editing music in the music analyzer generation page
- **WHEN** the user changes the action from `generate` to `continue`
- **THEN** the UI SHALL keep the user in the same unified form
- **AND** SHALL reveal only the continuation parameters relevant to the selected action
#### Scenario: User switches from continue to infill in one unified form
- **GIVEN** the user is editing music in the music analyzer generation page
- **WHEN** the user changes the action from `continue` to `infill`
- **THEN** the UI SHALL remain in the same unified form
- **AND** SHALL reveal `infill_start_s` and `infill_end_s`
- **AND** SHALL preserve any compatible shared fields such as `prompt`, `title`, `tags`, and `mv`
### Requirement: Use clip_id As The Source Of Truth For Continuation Targets
The system SHALL use the Suno polling result field `clip_id` as the source-of-truth identifier for continuation and infill requests.
#### Scenario: Polling response discovers continuation clip ids before audio is ready
- **GIVEN** `/suno/fetch/{task_id}` returns generated items that already include `clip_id`
- **WHEN** playable audio URLs are not yet fully available
- **THEN** the system SHALL still remember those `clip_id` values
- **AND** SHALL reuse them in later normalized results for continuation actions
#### Scenario: User launches continuation from a generated clip card
- **GIVEN** the music analyzer displays generated clips
- **WHEN** the user chooses to continue or infill a clip
- **THEN** the system SHALL use that clip's remembered `clip_id`
- **AND** SHALL not substitute the list row `id` in place of `clip_id`
### Requirement: Scope Suno Music Parameters By Edit Action
The system SHALL validate and submit Suno music parameters according to the selected unified edit action.
#### Scenario: Basic generation omits continuation parameters
- **GIVEN** the selected action is `generate`
- **WHEN** the user submits the request
- **THEN** the system SHALL send `prompt`, `mv`, `title`, and `tags` when provided
- **AND** SHALL omit `continue_clip_id`, `continue_at`, `infill_start_s`, and `infill_end_s`
#### Scenario: Continuation requires clip id and continue time
- **GIVEN** the selected action is `continue`
- **WHEN** the user submits the request
- **THEN** the system SHALL require `continue_clip_id`
- **AND** SHALL require `continue_at`
- **AND** SHALL submit both fields to `/suno/submit/music`
#### Scenario: Infill requires continuation anchor and infill window
- **GIVEN** the selected action is `infill`
- **WHEN** the user submits the request
- **THEN** the system SHALL require `continue_clip_id`
- **AND** SHALL require `continue_at`
- **AND** SHALL require `infill_start_s`
- **AND** SHALL require `infill_end_s`
- **AND** SHALL ensure `infill_start_s` is less than `infill_end_s`

View File

@@ -0,0 +1,24 @@
## 1. Spec
- [x] 1.1 补充 unified 动作模型与参数约束说明
- [x] 1.2 明确 `clip_id` 作为续写真实标识的保存规则
## 2. Data And Service
- [x] 2.1 扩展音频请求类型,支持 `infill_start_s / infill_end_s`
- [x] 2.2 扩展音乐记录类型,保存统一动作与续写参数
- [x] 2.3 在音频服务中为 `/suno/submit/music` 发送续写与 Infill 参数
- [x] 2.4 确保轮询中发现的 `clip_id` 能稳定进入最终结果
## 3. Music Analyzer UI
- [x] 3.1 在 `GeneratePage` 增加 `新生成 / 续写 / Infill` 动作切换
- [x] 3.2 根据动作展示和校验 `continueAt / infillStartS / infillEndS`
- [x] 3.3 在已生成片段卡片上增加“续写 / Infill”快捷入口
- [x] 3.4 将所选片段的真实 `clip_id` 自动带入表单
## 4. Verification
- [x] 4.1 为音频服务补充续写与 Infill 参数构造测试
- [x] 4.2 为 `clip_id` 继承逻辑补充回归测试
- [x] 4.3 手工验证统一入口下三种动作的字段显隐与校验