请求契约把 model 改为必填字段

三个生成请求的 model 由 Option<Model3dModelVersion> 改为必填 Model3dModelVersion,并同步重新生成 TypeScript 绑定

validate_generation_options 不再重复校验 model 缺失,直接由必填的 model 推导 family

三个 client 的 to_sdk_params 改为直接提交模型版本字符串

冒烟示例与技术方案文档同步为必填写法
This commit is contained in:
2026-09-19 14:16:39 +08:00
parent 12512f26b2
commit 1392303f1c
12 changed files with 20 additions and 39 deletions
@@ -24,9 +24,9 @@ task 尚未完成时 `output` 为空;完成后 `output` 必须是与 task type
## 请求与类型
三个生成请求使用官方文档已确认的 enum:模型版本、纹理版本、纹理质量(含 `fast`)、几何质量、纹理对齐、输入方向、导出方向和压缩类型(`geometry`)。文档未将 `style` 列为这三个 endpoint 的请求字段,因此不再保留占位 enum。请求可选字段在 Rust 侧为 `Option`TypeScript 绑定对应 `field?: T | null`,调用方既可省略字段也可显式传 `null`。TypeScript 绑定仍按目录生成到 `packages/shared/src/contracts/model3d/`,并由该目录的 `index.ts``packages/shared` 的 barrel 统一再导出;生成命令 `npm run contracts:model3d:generate` 写入的是未格式化的 ts-rs 输出,需再执行 `prettier --write packages/shared/src/contracts/model3d` 后提交。
三个生成请求使用官方文档已确认的 enum:模型版本、纹理版本、纹理质量(含 `fast`)、几何质量、纹理对齐、输入方向、导出方向和压缩类型(`geometry`)。文档未将 `style` 列为这三个 endpoint 的请求字段,因此不再保留占位 enum。`model` 在三个请求中都是必填字段(缺失或取值非法时在反序列化阶段即拒绝);除它以外的参数可选,在 Rust 侧为 `Option`TypeScript 绑定对应 `field?: T | null`,调用方既可省略字段也可显式传 `null`。TypeScript 绑定仍按目录生成到 `packages/shared/src/contracts/model3d/`,并由该目录的 `index.ts``packages/shared` 的 barrel 统一再导出;生成命令 `npm run contracts:model3d:generate` 写入的是未格式化的 ts-rs 输出,需再执行 `prettier --write packages/shared/src/contracts/model3d` 后提交。
提交前由 provider 统一执行组合校验:模型必填`fast` 必须配 `v3.5-20260815`;几何质量 / 压缩 / 自动尺寸 / P 系列与 H 系列能力按模型版本限制;`quad``generate_parts``smart_low_poly``texture/pbr` 组合按文档的互斥关系拒绝;`face_limit` 按模型、quad 和 smart-low-poly 模式检查范围。SDK 返回的参数错误仍统一归一为 `TripoError`
提交前由 provider 统一执行组合校验:模型版本决定 family`fast` 必须配 `v3.5-20260815`;几何质量 / 压缩 / 自动尺寸 / P 系列与 H 系列能力按模型版本限制;`quad``generate_parts``smart_low_poly``texture/pbr` 组合按文档的互斥关系拒绝;`face_limit` 按模型、quad 和 smart-low-poly 模式检查范围。SDK 返回的参数错误仍统一归一为 `TripoError`
## 验收
@@ -10,7 +10,7 @@ import type { Model3dTextureVersion } from '../common/Model3dTextureVersion';
export type Model3dImageToModelRequest = {
input: string;
model?: Model3dModelVersion | null;
model: Model3dModelVersion;
enableImageAutofix?: boolean | null;
modelSeed?: number | null;
textureSeed?: number | null;
@@ -11,7 +11,7 @@ import type { Model3dMultiviewInputs } from './Model3dMultiviewInputs';
export type Model3dMultiviewToModelRequest = {
inputs: Model3dMultiviewInputs;
model?: Model3dModelVersion | null;
model: Model3dModelVersion;
modelSeed?: number | null;
textureSeed?: number | null;
texture?: boolean | null;
@@ -8,7 +8,7 @@ import type { Model3dTextureVersion } from '../common/Model3dTextureVersion';
export type Model3dTextToModelRequest = {
prompt: string;
model?: Model3dModelVersion | null;
model: Model3dModelVersion;
negativePrompt?: string | null;
imageSeed?: number | null;
modelSeed?: number | null;
@@ -47,7 +47,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let text = client
.submit(&Model3dTextToModelRequest {
prompt: "a low-poly wooden treasure chest".to_string(),
model: Some(Model3dModelVersion::H31),
model: Model3dModelVersion::H31,
negative_prompt: None,
image_seed: None,
model_seed: None,
@@ -73,7 +73,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let image = client
.submit_image_to_model(&Model3dImageToModelRequest {
input: SAMPLE_IMAGE_URL.to_string(),
model: Some(Model3dModelVersion::H31),
model: Model3dModelVersion::H31,
enable_image_autofix: None,
model_seed: None,
texture_seed: None,
@@ -105,7 +105,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
back: None,
right: None,
},
model: Some(Model3dModelVersion::H31),
model: Model3dModelVersion::H31,
model_seed: None,
texture_seed: None,
texture: Some(true),
@@ -6,7 +6,7 @@ use shared_contracts::model3d::common::{
use super::{TripoError, TripoField, TripoValidationReason};
pub(crate) struct TripoGenerationOptions {
pub model: Option<Model3dModelVersion>,
pub model: Model3dModelVersion,
pub texture: Option<bool>,
pub pbr: Option<bool>,
pub texture_quality: Option<Model3dTextureQuality>,
@@ -23,14 +23,7 @@ pub(crate) struct TripoGenerationOptions {
pub(crate) fn validate_generation_options(
options: &TripoGenerationOptions,
) -> Result<(), TripoError> {
let model = options.model.ok_or_else(|| {
invalid(
Some(TripoField::Model),
TripoValidationReason::Required,
"model is required",
)
})?;
let family = ModelFamily::from(model);
let family = ModelFamily::from(options.model);
if options.texture_quality.is_some() && matches!(family, ModelFamily::H25) {
return Err(invalid(
@@ -1,6 +1,6 @@
use shared_contracts::model3d::common::{
Model3dCompression, Model3dExportOrientation, Model3dGeometryQuality, Model3dInputOrientation,
Model3dModelVersion, Model3dTextureAlignment, Model3dTextureQuality, Model3dTextureVersion,
Model3dTextureAlignment, Model3dTextureQuality, Model3dTextureVersion,
};
use shared_contracts::model3d::image_to_model::Model3dImageToModelRequest;
use tripo3d_sdk::{models::FileInput, params::ImageToModelParams};
@@ -49,10 +49,7 @@ impl TripoProviderClient {
fn to_sdk_params(request: &Model3dImageToModelRequest) -> ImageToModelParams {
ImageToModelParams {
input: FileInput::from(request.input.trim()),
model: request
.model
.map(Model3dModelVersion::as_str)
.map(str::to_owned),
model: Some(request.model.as_str().to_owned()),
enable_image_autofix: request.enable_image_autofix,
model_seed: request.model_seed,
texture_seed: request.texture_seed,
@@ -1,6 +1,6 @@
use shared_contracts::model3d::common::{
Model3dCompression, Model3dExportOrientation, Model3dGeometryQuality, Model3dInputOrientation,
Model3dModelVersion, Model3dTextureAlignment, Model3dTextureQuality,
Model3dTextureAlignment, Model3dTextureQuality,
};
use shared_contracts::model3d::multiview_to_model::{
Model3dMultiviewInputs, Model3dMultiviewToModelRequest,
@@ -97,10 +97,7 @@ fn to_sdk_params(request: &Model3dMultiviewToModelRequest) -> MultiviewToModelPa
MultiviewToModelParams::from_task_id(task_id.trim().to_owned())
}
};
params.model = request
.model
.map(Model3dModelVersion::as_str)
.map(str::to_owned);
params.model = Some(request.model.as_str().to_owned());
params.model_seed = request.model_seed;
params.texture_seed = request.texture_seed;
params.texture = request.texture;
@@ -1,7 +1,7 @@
use crate::common::{TripoError, TripoProviderClient, TripoTaskHandle};
use shared_contracts::model3d::common::{
Model3dCompression, Model3dExportOrientation, Model3dGeometryQuality, Model3dModelVersion,
Model3dTextureQuality, Model3dTextureVersion,
Model3dCompression, Model3dExportOrientation, Model3dGeometryQuality, Model3dTextureQuality,
Model3dTextureVersion,
};
use shared_contracts::model3d::text_to_model::Model3dTextToModelRequest;
@@ -25,10 +25,7 @@ impl TripoProviderClient {
fn to_sdk_params(request: &Model3dTextToModelRequest) -> tripo3d_sdk::params::TextToModelParams {
tripo3d_sdk::params::TextToModelParams {
prompt: request.prompt.clone(),
model: request
.model
.map(Model3dModelVersion::as_str)
.map(str::to_owned),
model: Some(request.model.as_str().to_owned()),
negative_prompt: request.negative_prompt.clone(),
image_seed: request.image_seed,
model_seed: request.model_seed,
@@ -13,8 +13,7 @@ use super::MODEL3D_TS_EXPORT_DIR;
#[ts(export, export_to = MODEL3D_TS_EXPORT_DIR)]
pub struct Model3dImageToModelRequest {
pub input: String,
#[ts(optional = nullable)]
pub model: Option<Model3dModelVersion>,
pub model: Model3dModelVersion,
#[ts(optional = nullable)]
pub enable_image_autofix: Option<bool>,
#[ts(type = "number | null")]
@@ -35,8 +35,7 @@ pub enum Model3dMultiviewInputs {
#[ts(export, export_to = MODEL3D_TS_EXPORT_DIR)]
pub struct Model3dMultiviewToModelRequest {
pub inputs: Model3dMultiviewInputs,
#[ts(optional = nullable)]
pub model: Option<Model3dModelVersion>,
pub model: Model3dModelVersion,
#[ts(type = "number | null")]
#[ts(optional = nullable)]
pub model_seed: Option<i64>,
@@ -12,8 +12,7 @@ use crate::model3d::common::{
#[ts(export, export_to = MODEL3D_TS_EXPORT_DIR)]
pub struct Model3dTextToModelRequest {
pub prompt: String,
#[ts(optional = nullable)]
pub model: Option<Model3dModelVersion>,
pub model: Model3dModelVersion,
#[ts(optional = nullable)]
pub negative_prompt: Option<String>,
#[ts(type = "number | null")]