Initial TrueGrowth source import
This commit is contained in:
255
openspec/changes/add-audio-generation-suno-routing/design.md
Normal file
255
openspec/changes/add-audio-generation-suno-routing/design.md
Normal file
@@ -0,0 +1,255 @@
|
||||
## Context
|
||||
|
||||
`opentu` 当前的生成体系围绕三类模态构建:
|
||||
|
||||
- `text`
|
||||
- `image`
|
||||
- `video`
|
||||
|
||||
这三个模态已经贯穿以下层级:
|
||||
|
||||
- `model-config` 中的静态模型类型
|
||||
- `settings-manager` 中的默认路由 preset
|
||||
- `provider-routing` 中的 operation 与 binding
|
||||
- `model-adapters` 中的适配器接口
|
||||
- `task-queue` 与历史记录中的任务类型与结果结构
|
||||
- `AIInputBar` 与设置页中的模型/模式切换
|
||||
|
||||
因此“增加音频层”并不是简单地再加一个 UI 选项,而是需要把音频模态接入整条调用链。
|
||||
|
||||
Suno 的特殊点在于,它暴露的是一组能力动作,而不是一组可以直接照抄提交的模型:
|
||||
|
||||
- 发现能力示例:
|
||||
- `suno_music`
|
||||
- `suno-continue`
|
||||
- `suno-continue-uploaded`
|
||||
- `suno-remix`
|
||||
- `suno-remix-uploaded`
|
||||
- `suno-infill`
|
||||
- `suno-lyrics`
|
||||
- `suno-tags`
|
||||
- `suno_act_tags`
|
||||
- `suno_act_timing`
|
||||
- 真实音乐生成提交接口:
|
||||
- `POST /suno/submit/music`
|
||||
- 真实版本切换字段:
|
||||
- `mv`
|
||||
- 真实状态查询接口:
|
||||
- `GET /suno/fetch/{task_id}`
|
||||
|
||||
因此,如果把 `suno_music` 这类标识直接当成“可调用模型 ID”,最终会出现两个问题:
|
||||
|
||||
1. UI 上看到的能力动作和请求里真正需要的 `mv`、续写参数混在一起
|
||||
2. 运行时发现层与执行层之间失去稳定映射
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
- Goals:
|
||||
- 为 `opentu` 增加一等音频生成模态
|
||||
- 为 Suno 建立“能力动作 -> 执行规则 -> 版本参数”的明确映射
|
||||
- 复用现有多供应商路由和任务轮询思路,而不是单独再造一套音频系统
|
||||
- 先跑通音乐生成和单任务查询闭环
|
||||
- Non-Goals:
|
||||
- 本次不一次性覆盖 Suno 全量能力
|
||||
- 本次不实现完整的画布音频后处理编辑器
|
||||
- 本次不让发现到的所有 Suno 能力都自动出现在 UI 主路径中
|
||||
|
||||
## Decisions
|
||||
|
||||
- Decision: 引入 `audio` 作为一等模态
|
||||
|
||||
- `ModelType`、`GenerationType`、`TaskType`、`ProviderOperation`、默认 preset 都增加 `audio`
|
||||
- 音频不再借用文本或视频通道透传
|
||||
|
||||
- Decision: 区分“能力动作”和“执行版本”
|
||||
|
||||
- `suno_music`、`suno-continue` 等发现项表示能力或操作入口
|
||||
- `mv` 表示真实执行使用的 Suno 版本,例如 `chirp-v3-0`、`chirp-v3-5`
|
||||
- 续写上传场景通过 `mv + '-upload'` 表达
|
||||
|
||||
- Decision: Suno 初始切片只做 `music submit + fetch`
|
||||
|
||||
- 首批只支持 `POST /suno/submit/music`
|
||||
- 首批只支持 `GET /suno/fetch/{task_id}`
|
||||
- 其余 Suno 动作先作为已发现但未激活的能力保留在元数据层
|
||||
|
||||
- Decision: UI 不直接展示所有发现能力
|
||||
|
||||
- 用户主路径先暴露统一的 `音频` 模式
|
||||
- 进入音频模式后,再根据绑定能力展示当前支持的生成方式和字段
|
||||
- 避免让用户直接面对一串 `suno-*` 能力代号
|
||||
|
||||
- Decision: 任务轮询采用 provider-specific 标准化
|
||||
|
||||
- `/suno/fetch/{task_id}` 返回的 `status/progress/data` 需要统一转换成内部任务状态
|
||||
- 不能强制复用视频任务的原始响应结构
|
||||
|
||||
## Proposed Data Model
|
||||
|
||||
```ts
|
||||
type ModelType = 'text' | 'image' | 'video' | 'audio';
|
||||
|
||||
type SunoAction =
|
||||
| 'music'
|
||||
| 'continue'
|
||||
| 'continue-uploaded'
|
||||
| 'lyrics'
|
||||
| 'tags'
|
||||
| 'remix'
|
||||
| 'remix-uploaded'
|
||||
| 'infill'
|
||||
| 'infill-uploaded';
|
||||
|
||||
interface ProviderAudioBindingMetadata {
|
||||
action: SunoAction | string;
|
||||
versionField?: string;
|
||||
versionOptions?: string[];
|
||||
defaultVersion?: string;
|
||||
supportsContinuation?: boolean;
|
||||
supportsUploadContinuation?: boolean;
|
||||
supportsLyricsPrompt?: boolean;
|
||||
supportsTags?: boolean;
|
||||
supportsTitle?: boolean;
|
||||
taskIdField?: string;
|
||||
resultAudioUrlPath?: string;
|
||||
}
|
||||
|
||||
interface AudioGenerationRequest {
|
||||
prompt: string;
|
||||
model?: string;
|
||||
modelRef?: ModelRef | null;
|
||||
title?: string;
|
||||
tags?: string;
|
||||
mv?: string;
|
||||
continueClipId?: string;
|
||||
continueAt?: number;
|
||||
params?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
interface AudioGenerationResult {
|
||||
url: string;
|
||||
title?: string;
|
||||
duration?: number | null;
|
||||
waveformUrl?: string;
|
||||
raw?: unknown;
|
||||
}
|
||||
```
|
||||
|
||||
## Suno Binding Strategy
|
||||
|
||||
### Capability Layer
|
||||
|
||||
发现层保留原始能力标识,例如:
|
||||
|
||||
- `suno_music`
|
||||
- `suno-continue`
|
||||
- `suno-continue-uploaded`
|
||||
- `suno-lyrics`
|
||||
- `suno-tags`
|
||||
|
||||
这些标识用于:
|
||||
|
||||
- 推断该 profile 是否支持音频
|
||||
- 推断该 profile 支持哪些音频动作
|
||||
- 决定 UI 允许展示哪些高级入口
|
||||
|
||||
### Execution Layer
|
||||
|
||||
执行层不直接按发现能力 ID 发请求,而是映射成:
|
||||
|
||||
- `submitPath`
|
||||
- `pollPathTemplate`
|
||||
- `action`
|
||||
- `mv` 规则
|
||||
- 字段可用性
|
||||
|
||||
例如首批音乐生成统一映射为:
|
||||
|
||||
```ts
|
||||
{
|
||||
operation: 'audio',
|
||||
protocol: 'tuzi.suno.music',
|
||||
submitPath: '/suno/submit/music',
|
||||
pollPathTemplate: '/suno/fetch/{task_id}',
|
||||
metadata: {
|
||||
audio: {
|
||||
action: 'music',
|
||||
versionField: 'mv',
|
||||
versionOptions: ['chirp-v3-0', 'chirp-v3-5'],
|
||||
defaultVersion: 'chirp-v3-5',
|
||||
supportsContinuation: true,
|
||||
supportsUploadContinuation: true,
|
||||
supportsTags: true,
|
||||
supportsTitle: true,
|
||||
supportsLyricsPrompt: true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当用户选择“续写已上传音频”时,不改 submitPath,而是通过 metadata 规则把:
|
||||
|
||||
- `mv=chirp-v3-5`
|
||||
|
||||
转换为:
|
||||
|
||||
- `mv=chirp-v3-5-upload`
|
||||
|
||||
## UI Strategy
|
||||
|
||||
### Settings
|
||||
|
||||
- 在默认路由 preset 中增加 `audio`
|
||||
- 音频默认路由保存 `ModelRef`
|
||||
- 如果当前 provider profile 未发现音频能力,则不允许被选为音频默认路由
|
||||
|
||||
### AI Input Bar
|
||||
|
||||
- 增加 `音频` 模式
|
||||
- 进入音频模式后,参数区支持:
|
||||
- `mv`
|
||||
- `title`
|
||||
- `tags`
|
||||
- `continue_clip_id`
|
||||
- `continue_at`
|
||||
- 默认交互仍保持与图片/视频一致:
|
||||
- 选择模型
|
||||
- 输入提示词
|
||||
- 提交任务
|
||||
|
||||
### Task And History
|
||||
|
||||
- 任务类型增加 `audio`
|
||||
- 历史记录支持展示音频结果
|
||||
- 结果结构至少包含:
|
||||
- 音频 URL
|
||||
- 标题
|
||||
- 创建时间
|
||||
- 执行状态
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. 先补核心类型层和 preset 路由层的 `audio`
|
||||
2. 再补 provider routing / adapter / service 的 Suno 音频闭环
|
||||
3. 再补 AI 输入栏和设置页入口
|
||||
4. 最后补任务列表、历史记录和结果回显
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- 风险: 音频能力切入口过大,影响现有图片/视频链路
|
||||
- Mitigation: 首批只做 `music submit + fetch`,不扩张到所有 Suno 动作
|
||||
|
||||
- 风险: 发现能力与执行规则混在一起,导致后续高级动作难扩展
|
||||
- Mitigation: 明确拆分 capability layer 和 execution layer
|
||||
|
||||
- 风险: UI 直接暴露 `suno-*` 原始能力名,增加理解成本
|
||||
- Mitigation: 主路径只暴露 `音频` 模式和人类可理解的操作标签
|
||||
|
||||
- 风险: 音频结果结构与视频结果结构不同,历史记录复用成本高
|
||||
- Mitigation: 在 `TaskResult` 中增加音频最小字段集,而不是强行套用视频字段
|
||||
|
||||
## Open Questions
|
||||
|
||||
- 首批是否需要同时支持“仅生成纯音乐”和“包含人声/歌词”的 UI 开关
|
||||
- `suno_lyrics`、`suno_tags` 是否应该作为后续独立工具,还是继续作为音乐生成前的辅助步骤
|
||||
- 音频结果进入画布后,第一版是否只作为可播放资源卡片,而不引入完整音频节点编辑器
|
||||
@@ -0,0 +1,78 @@
|
||||
# Change: 增加音频生成模态与 Suno 动作路由适配
|
||||
|
||||
## Why
|
||||
|
||||
当前 `opentu` 的生成链路默认只支持 `text / image / video` 三类模态:
|
||||
|
||||
- AI 输入栏只能切换图片、视频和 Agent
|
||||
- 默认模型预设只维护文本、图片、视频三条路由
|
||||
- 任务队列、适配器、历史记录和自动插入逻辑都假设生成结果是图片或视频
|
||||
|
||||
这使得“音频生成”无法作为一等能力进入现有架构。
|
||||
|
||||
同时,Suno 供应商的调用模式与当前的多供应商模型路由假设存在关键差异:
|
||||
|
||||
- 运行时发现到的 `suno_music`、`suno-continue`、`suno-remix`、`suno_lyrics` 等标识,更像“能力动作”而不是可以直接提交调用的裸模型
|
||||
- 真正的音乐生成接口通过 `/suno/submit/music` 提交
|
||||
- 实际版本选择通过请求体中的 `mv` 决定,例如 `chirp-v3-0`、`chirp-v3-5`,以及续写上传音频时的 `-upload` 变体
|
||||
- 任务状态查询通过 `/suno/fetch/{task_id}` 完成,而不是沿用图片/视频侧已有的统一轮询约定
|
||||
|
||||
如果继续沿用“发现模型 ID -> 直接提交调用”的现有假设,音频能力会在路由层、适配层和 UI 层同时失真。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 引入一等 `audio` 模态,贯穿模型类型、默认路由、任务队列、结果结构和历史记录
|
||||
- 为 Suno 引入“能力动作”和“执行版本”分离的绑定模型
|
||||
- 新增音频生成服务与轮询链路,首批支持 `POST /suno/submit/music` 与 `GET /suno/fetch/{task_id}`
|
||||
- 在设置页、AI 输入栏和任务/历史 UI 中增加音频入口与基础参数配置
|
||||
- 允许将已发现的 Suno 能力集合映射为 UI 可用的音频操作,而不是把每个能力 ID 暴露成一个可直接执行的模型
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
- 增加 `audio` 模态
|
||||
- 首批支持 Suno 音乐生成提交与单任务轮询
|
||||
- 首批适配 `mv` 版本选择
|
||||
- 首批适配音乐生成的核心字段:
|
||||
- `prompt`
|
||||
- `tags`
|
||||
- `title`
|
||||
- `mv`
|
||||
- `continue_clip_id`
|
||||
- `continue_at`
|
||||
- 在 UI 中增加音频生成模式和对应的基础参数表单
|
||||
|
||||
### Out Of Scope
|
||||
|
||||
- 本次不实现 Suno 全量高级动作的完整执行链路,例如:
|
||||
- `suno-remix`
|
||||
- `suno-infill`
|
||||
- `suno-overpainting`
|
||||
- `suno-midi`
|
||||
- `suno-all-stems`
|
||||
- `suno-vocal-stems`
|
||||
- 本次不实现完整的画布音频节点编辑器
|
||||
- 本次不实现音频波形剪辑、片段拼接或多轨混音
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected specs:
|
||||
- `audio-generation`
|
||||
- Affected code:
|
||||
- `packages/drawnix/src/constants/model-config.ts`
|
||||
- `packages/drawnix/src/utils/settings-manager.ts`
|
||||
- `packages/drawnix/src/utils/ai-input-parser.ts`
|
||||
- `packages/drawnix/src/services/provider-routing/*`
|
||||
- `packages/drawnix/src/services/model-adapters/*`
|
||||
- `packages/drawnix/src/services/task-queue*`
|
||||
- `packages/drawnix/src/components/ai-input-bar/*`
|
||||
- `packages/drawnix/src/components/settings-dialog/*`
|
||||
- `packages/drawnix/src/components/task-queue/*`
|
||||
- `packages/drawnix/src/components/generation-history/*`
|
||||
|
||||
## Relationship To Existing Changes
|
||||
|
||||
- 本变更建立在 `add-multi-provider-profiles`、`add-runtime-model-discovery` 与 `add-provider-protocol-routing` 的多供应商基础之上
|
||||
- 本变更不会推翻现有协议路由架构,而是补足新的 `audio` 模态和 Suno 的动作路由规则
|
||||
- 本变更会首次把“能力标识不等于直接执行版本”明确建模到运行时绑定中
|
||||
@@ -0,0 +1,98 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Support Audio As A First-Class Generation Modality
|
||||
|
||||
The system SHALL treat audio as a first-class generation modality across routing, task execution, and UI entry points.
|
||||
|
||||
#### Scenario: Audio default route is configured in presets
|
||||
|
||||
- **GIVEN** the user manages invocation presets
|
||||
- **WHEN** the user selects a default provider-backed model for audio generation
|
||||
- **THEN** the preset SHALL store an `audio` route independently from `text`, `image`, and `video`
|
||||
|
||||
#### Scenario: Audio mode is available in the AI input bar
|
||||
|
||||
- **GIVEN** the current workspace supports AI generation entry from the input bar
|
||||
- **WHEN** the user switches generation type
|
||||
- **THEN** the user SHALL be able to choose an `audio` mode
|
||||
- **AND** the request SHALL be parsed as an audio generation request rather than being routed through text or video fallbacks
|
||||
|
||||
### Requirement: Resolve Suno Capability Identifiers Separately From Execution Versions
|
||||
|
||||
The system SHALL distinguish discovered Suno capability identifiers from the executable version fields required by submit requests.
|
||||
|
||||
#### Scenario: Discovered Suno capability is not used as submit version directly
|
||||
|
||||
- **GIVEN** a provider profile exposes discovered capabilities such as `suno_music` or `suno-continue`
|
||||
- **WHEN** the user submits a music generation request
|
||||
- **THEN** the system SHALL map the chosen capability to an executable binding
|
||||
- **AND** SHALL send the actual Suno version through the request field `mv`
|
||||
- **AND** SHALL not assume the discovered capability identifier itself is the executable version string
|
||||
|
||||
#### Scenario: Uploaded continuation appends upload suffix to mv
|
||||
|
||||
- **GIVEN** the selected audio action represents continuation from an uploaded clip
|
||||
- **WHEN** the user submits the request with a base Suno version such as `chirp-v3-5`
|
||||
- **THEN** the system SHALL transform the submitted version to the upload variant required by the provider
|
||||
- **AND** SHALL keep the rest of the request flow on the same submit endpoint
|
||||
|
||||
### Requirement: Submit Suno Music Requests Through Provider-Specific Audio Bindings
|
||||
|
||||
The system SHALL submit Suno music generation requests through provider-specific audio bindings that describe the provider endpoint, request fields, and supported parameters.
|
||||
|
||||
#### Scenario: Submit a basic music generation request
|
||||
|
||||
- **GIVEN** the active audio binding targets Suno music generation
|
||||
- **WHEN** the user provides lyrics or prompt text and submits an audio request
|
||||
- **THEN** the system SHALL send the request to `/suno/submit/music`
|
||||
- **AND** SHALL include the selected `mv`
|
||||
- **AND** SHALL include `prompt`
|
||||
|
||||
#### Scenario: Submit music request with optional tags and title
|
||||
|
||||
- **GIVEN** the active audio binding supports Suno custom music generation fields
|
||||
- **WHEN** the user provides `tags` and `title`
|
||||
- **THEN** the system SHALL forward those fields in the submit request
|
||||
- **AND** SHALL keep them associated with the created audio task
|
||||
|
||||
#### Scenario: Submit continuation fields when continuing a clip
|
||||
|
||||
- **GIVEN** the user is continuing an existing clip
|
||||
- **WHEN** the user provides `continue_clip_id` and `continue_at`
|
||||
- **THEN** the system SHALL include those fields in the submit request
|
||||
- **AND** SHALL execute the request through the same provider-specific audio binding
|
||||
|
||||
### Requirement: Poll Suno Audio Tasks Through Fetch Endpoint
|
||||
|
||||
The system SHALL poll Suno audio tasks through the provider fetch endpoint and normalize provider statuses into internal task states.
|
||||
|
||||
#### Scenario: Audio task is queried after submit
|
||||
|
||||
- **GIVEN** a Suno audio submit request returns a task identifier
|
||||
- **WHEN** the system tracks that task asynchronously
|
||||
- **THEN** it SHALL query `/suno/fetch/{task_id}`
|
||||
- **AND** SHALL update the internal audio task status based on the provider response
|
||||
|
||||
#### Scenario: Completed Suno task returns audio output
|
||||
|
||||
- **GIVEN** a Suno fetch response indicates success or completion
|
||||
- **WHEN** the result payload includes audio clip data
|
||||
- **THEN** the system SHALL extract at least one playable audio URL
|
||||
- **AND** SHALL store it in the internal task result for audio history and follow-up actions
|
||||
|
||||
### Requirement: Expose Audio Parameters In User-Facing Controls
|
||||
|
||||
The system SHALL expose the audio parameters needed for Suno music generation in user-facing configuration and submission flows.
|
||||
|
||||
#### Scenario: Audio parameters are editable before submit
|
||||
|
||||
- **GIVEN** the user is preparing an audio generation request
|
||||
- **WHEN** the current binding supports Suno music generation
|
||||
- **THEN** the UI SHALL allow the user to review and edit `mv`, `title`, `tags`, and continuation parameters when relevant
|
||||
|
||||
#### Scenario: Unsupported advanced Suno actions stay hidden from primary flow
|
||||
|
||||
- **GIVEN** the provider profile exposes additional Suno capabilities beyond initial music generation
|
||||
- **WHEN** those capabilities are not implemented in the current product slice
|
||||
- **THEN** the primary audio generation flow SHALL not expose them as if they were fully supported submit actions
|
||||
- **AND** the runtime MAY preserve their metadata for future expansion
|
||||
39
openspec/changes/add-audio-generation-suno-routing/tasks.md
Normal file
39
openspec/changes/add-audio-generation-suno-routing/tasks.md
Normal file
@@ -0,0 +1,39 @@
|
||||
## 1. Architecture
|
||||
|
||||
- [ ] 1.1 为 `audio` 模态补齐核心类型,包括模型类型、任务类型、结果类型和默认路由
|
||||
- [ ] 1.2 设计 Suno 的动作绑定结构,区分能力动作、执行端点和 `mv` 版本
|
||||
- [ ] 1.3 定义音频任务提交与轮询状态的标准化映射
|
||||
|
||||
## 2. Provider Routing And Adapter Layer
|
||||
|
||||
- [ ] 2.1 为 provider routing 增加 `audio` 操作与对应的 binding metadata
|
||||
- [ ] 2.2 新增 `AudioModelAdapter` 和音频 API service
|
||||
- [ ] 2.3 实现 Suno 音乐生成提交 `/suno/submit/music`
|
||||
- [ ] 2.4 实现 Suno 单任务查询 `/suno/fetch/{task_id}`
|
||||
- [ ] 2.5 将 Suno 的能力动作映射到可执行请求,而不是直接按发现模型 ID 调用
|
||||
|
||||
## 3. UI And Settings
|
||||
|
||||
- [ ] 3.1 在设置页中增加音频默认模型路由
|
||||
- [ ] 3.2 在 AI 输入栏中增加 `音频` 模式切换
|
||||
- [ ] 3.3 为 Suno 音乐生成暴露基础参数表单:
|
||||
- `mv`
|
||||
- `title`
|
||||
- `tags`
|
||||
- `continue_clip_id`
|
||||
- `continue_at`
|
||||
- [ ] 3.4 在任务队列和历史记录中展示音频任务与音频结果
|
||||
|
||||
## 4. Runtime Behavior
|
||||
|
||||
- [ ] 4.1 保证未显式选择模型时,音频请求可正确走默认 preset
|
||||
- [ ] 4.2 保证显式选择 Suno 能力动作时,可以解析到正确的执行规则与 `mv`
|
||||
- [ ] 4.3 保证任务刷新恢复时,音频任务可继续轮询并更新进度
|
||||
|
||||
## 5. Verification
|
||||
|
||||
- [ ] 5.1 验证 AI 输入栏可发起音频生成任务
|
||||
- [ ] 5.2 验证 Suno 音乐生成接口可提交并回填 `task_id`
|
||||
- [ ] 5.3 验证 `/suno/fetch/{task_id}` 能驱动任务状态从提交到完成
|
||||
- [ ] 5.4 验证音频结果能进入任务列表与历史记录
|
||||
- [ ] 5.5 验证图片、视频、文本既有链路不回归
|
||||
Reference in New Issue
Block a user