tripo-cli 0.5.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,7 +35,7 @@ Works with both Tripo regions from the same install — international (`openapi.
35
35
  | `tripo login / logout / whoami / use` | device flow: browser approves, key arrives automatically (paste fallback); stored 0600 in `~/.tripo/config.json`; `use` switches accounts |
36
36
  | `tripo topup / balance / usage` | open the billing page + detect the credits arriving; check spend |
37
37
  | `tripo generate <endpoint>` | deterministic access to all 8 generation endpoints |
38
- | `tripo model / anim / mesh <step>` | refine, texture, stylize, convert, import, rig-check, rig, retarget, segment, complete, decimate, smartsegment |
38
+ | `tripo model / anim / mesh <step>` | refine, texture, convert, import, rig-check, rig, retarget, segment, complete, decimate, uv, smartsegment |
39
39
  | `tripo task get/list/watch` | query and stream task progress (NDJSON in `--json` mode) |
40
40
  | `tripo files upload` | upload a file, print the `file_token` |
41
41
  | `tripo batch run <manifest.yaml>` | bulk pipelines with concurrency, retries, and resume |
@@ -32,7 +32,7 @@ const SPECIALIST_PROMPTS = {
32
32
  print: `You are a 3D-printing engineer. Geometry only (texture=false,pbr=false), watertight meshes, flatten_bottom for FDM, STL or colored 3MF via convert, real-world sizing via scale_factor/auto_size.`,
33
33
  'ar-web': `You are a realtime AR/Web 3D engineer. Keep faces <= 20000 via decimate, 2K textures, deliver GLB + USDZ (iOS QuickLook).`,
34
34
  anim: `You are a character animation TD. Chain: rig-check → rig (v2.5 rig, spec tripo|mixamo) → retarget (<=5 preset animations, billed per animation). Mixamo/Unity Humanoid → spec=mixamo.`,
35
- toy: `You are a stylized collectible designer. P1 low-poly or stylize steps (lego/voxel/voronoi/minecraft). STL via convert for physical prints.`,
35
+ toy: `You are a stylized collectible designer. P1 low-poly. STL via convert for physical prints.`,
36
36
  };
37
37
  function specialistSystem(scenarioId) {
38
38
  const persona = SPECIALIST_PROMPTS[scenarioId] ?? SPECIALIST_PROMPTS['game-mobile'];
@@ -9,9 +9,9 @@ const COMMANDS = [
9
9
  ];
10
10
  const SUBS = {
11
11
  generate: ['text-to-model', 'image-to-model', 'multiview-to-model', 'text-to-image', 'image-to-image', 'image-to-multiview', 'edit-multiview', 'image-to-splat'],
12
- model: ['refine', 'texture', 'stylize', 'convert', 'import'],
12
+ model: ['refine', 'texture', 'convert', 'import'],
13
13
  anim: ['check', 'rig', 'retarget'],
14
- mesh: ['segment', 'complete', 'decimate', ...(isMeshEditEnabled() ? ['edit'] : []), 'smartsegment'],
14
+ mesh: ['segment', 'complete', 'decimate', 'uv', ...(isMeshEditEnabled() ? ['edit'] : []), 'smartsegment'],
15
15
  task: ['get', 'list', 'watch'],
16
16
  files: ['upload'],
17
17
  batch: ['run'],
@@ -70,14 +70,14 @@ function collectStepArgs(step, flags) {
70
70
  return pick(['format', 'texture_size', 'texture_format', 'face_limit', 'quad', 'flatten_bottom', 'fbx_preset', 'export_orientation', 'scale_factor', 'auto_size', 'pivot_to_center_bottom', 'export_vertex_colors']);
71
71
  case 'texture':
72
72
  return pick(['model', 'texture_quality', 'texture_alignment', 'pbr']);
73
- case 'stylize':
74
- return pick(['style', 'block_size']);
75
73
  case 'rig':
76
74
  return pick(['model', 'rig_type', 'spec', 'out_format']);
77
75
  case 'retarget':
78
76
  return pick(['animation', 'out_format', 'animate_in_place']);
79
77
  case 'decimate':
80
- return pick(['face_limit', 'quad', 'bake']);
78
+ return pick(['model', 'face_limit', 'quad', 'smart_uv', 'bake']);
79
+ case 'uv':
80
+ return pick(['bake', 'export_orientation']);
81
81
  case 'segment':
82
82
  return pick(['model']);
83
83
  case 'complete':
@@ -92,18 +92,13 @@ function collectStepArgs(step, flags) {
92
92
  }
93
93
  export function registerProcessCommands(program) {
94
94
  // ---- tripo model ----
95
- const model = program.command('model').description('model processing: refine / texture / stylize / convert / import');
95
+ const model = program.command('model').description('model processing: refine / texture / convert / import');
96
96
  withTaskOptions(model.command('refine [input]').description('refine a draft text-to-model task (task id / @last)')).action(makeStepAction('refine'));
97
97
  withTaskOptions(model
98
98
  .command('texture [input]')
99
99
  .description('re-texture a model (task/@last/file/url)')
100
100
  .option('--texture-quality <q>', 'standard|detailed|extreme')
101
101
  .option('--texture-alignment <a>', 'original_image|geometry')).action(makeStepAction('texture'));
102
- withTaskOptions(model
103
- .command('stylize [input]')
104
- .description('stylize a model (lego/voxel/voronoi/minecraft)')
105
- .option('--style <style>', 'lego|voxel|voronoi|minecraft')
106
- .option('--block-size <n>', 'minecraft block size 32-128', (v) => Number(v))).action(makeStepAction('stylize'));
107
102
  withTaskOptions(model
108
103
  .command('convert [input]')
109
104
  .description('convert format (GLTF/USDZ/FBX/OBJ/STL/3MF)')
@@ -147,7 +142,7 @@ export function registerProcessCommands(program) {
147
142
  await makeStepAction('retarget')(input, flags);
148
143
  });
149
144
  // ---- tripo mesh ----
150
- const mesh = program.command('mesh').description('mesh ops: segment / complete / decimate / smartsegment');
145
+ const mesh = program.command('mesh').description('mesh ops: segment / complete / decimate / uv / smartsegment');
151
146
  withTaskOptions(mesh.command('segment [input]').description('segment a model into parts').option('--model <v>', 'v1.0-20250506|v2.0-20260430')).action(makeStepAction('segment'));
152
147
  withTaskOptions(mesh
153
148
  .command('complete [input]')
@@ -156,9 +151,16 @@ export function registerProcessCommands(program) {
156
151
  withTaskOptions(mesh
157
152
  .command('decimate [input]')
158
153
  .description('high-poly → low-poly (bakes textures by default)')
154
+ .option('--model <v>', 'v3.0|v2.0|v1.0 (default v2.0)')
159
155
  .option('--face-limit <n>', 'target faces 500–20000 tri / 500–10000 quad', (v) => Number(v))
160
156
  .option('--quad', 'quad output')
157
+ .option('--smart-uv', 'unwrap UVs in the same task (v3.0 only; selects v3.0 when --model is omitted)')
161
158
  .option('--no-bake', 'skip baking textures onto the low-poly')).action(makeStepAction('decimate'));
159
+ withTaskOptions(mesh
160
+ .command('uv [input]')
161
+ .description('smart UV unwrap; remaps textures/rig/animation (input ≤80k equivalent triangles)')
162
+ .option('--no-bake', 'skip baking textures onto the new UV layout (geometry + UVs only)')
163
+ .option('--export-orientation <o>', '+x|-x|+y|-y')).action(makeStepAction('uv'));
162
164
  // Hidden until /v3/mesh/edit is live server-side (see isMeshEditEnabled).
163
165
  if (isMeshEditEnabled()) {
164
166
  withTaskOptions(mesh
@@ -73,7 +73,8 @@ export async function downloadArtifacts(task, outputDir, historyEntry, options =
73
73
  const ext = extname(name).toLowerCase();
74
74
  if (!modelFile && MODEL_EXTS.has(ext))
75
75
  modelFile = dest;
76
- if (!preview && (IMAGE_EXTS.has(ext) || /rendered|preview/i.test(field)))
76
+ // uv_render (mesh/uv) is a flat UV atlas, not a render of the model.
77
+ if (!preview && !/uv_render/.test(field) && (IMAGE_EXTS.has(ext) || /rendered|preview/i.test(field)))
77
78
  preview = dest;
78
79
  }
79
80
  // Normalize the preview name so agents can rely on preview.png existing.
@@ -165,12 +165,6 @@ export function buildStepRequest(stepName, input, args) {
165
165
  }
166
166
  break;
167
167
  }
168
- case 'stylize': {
169
- if (typeof params.style !== 'string') {
170
- throw new UsageError('stylize requires style (lego/voxel/voronoi/minecraft)');
171
- }
172
- break;
173
- }
174
168
  case 'smartsegment': {
175
169
  if (params.seg_type === undefined)
176
170
  params.seg_type = 'model';
@@ -17,13 +17,13 @@ export const MODEL_PRODUCING_TYPES = new Set([
17
17
  'mesh_segmentation',
18
18
  'mesh_completion',
19
19
  'mesh_edit',
20
+ 'mesh_uv',
20
21
  'animate_rig',
21
22
  'animate_retarget',
22
23
  ]);
23
24
  export const STEPS = [
24
25
  { name: 'refine', endpoint: '/v3/models/refine', produces: 'refine_model', accepts: ['text_to_model'], acceptsFile: false, describe: { zh: '精修文生模型的几何细节', en: 'refine geometry of a text-to-model result' } },
25
26
  { name: 'texture', endpoint: '/v3/models/texture', produces: 'texture_model', accepts: 'any-model', acceptsFile: true, describe: { zh: '重新生成贴图 / PBR 材质', en: 'regenerate textures / PBR materials' } },
26
- { name: 'stylize', endpoint: '/v3/models/stylize', produces: 'stylize_model', accepts: 'any-model', acceptsFile: true, describe: { zh: '按风格重塑模型(lego/voxel/...)', en: 'restyle the model (lego/voxel/...)' } },
27
27
  { name: 'convert', endpoint: '/v3/models/convert', produces: 'convert_model', accepts: 'any-model', acceptsFile: true, describe: { zh: '转换输出格式 / 贴图尺寸 / 朝向', en: 'convert format / texture size / orientation' } },
28
28
  { name: 'import', endpoint: '/v3/models/import', produces: 'import_model', accepts: [], acceptsFile: true, describe: { zh: '导入本地模型文件作为加工起点', en: 'import a local model file as the chain source' } },
29
29
  { name: 'rig-check', endpoint: '/v3/animations/rig-check', produces: 'animate_prerigcheck', accepts: 'any-model', acceptsFile: true, passthrough: true, aliases: ['check', 'rigcheck'], describe: { zh: '检查是否可绑骨(不产出模型,不可绑则止损)', en: 'check riggability (no model output; stops the chain if not riggable)' } },
@@ -32,6 +32,7 @@ export const STEPS = [
32
32
  { name: 'segment', endpoint: '/v3/mesh/segment', produces: 'mesh_segmentation', accepts: 'any-model', acceptsFile: true, describe: { zh: '把网格分割成部件', en: 'segment the mesh into parts' } },
33
33
  { name: 'complete', endpoint: '/v3/mesh/complete', produces: 'mesh_completion', accepts: ['mesh_segmentation'], acceptsFile: false, describe: { zh: '补全分割后的部件', en: 'complete the segmented parts' } },
34
34
  { name: 'decimate', endpoint: '/v3/mesh/decimate', produces: 'highpoly_to_lowpoly', accepts: 'any-model', acceptsFile: true, aliases: ['lowpoly'], describe: { zh: '减面到目标面数', en: 'decimate to a target face count' } },
35
+ { name: 'uv', endpoint: '/v3/mesh/uv', produces: 'mesh_uv', accepts: 'any-model', acceptsFile: true, describe: { zh: '智能展 UV,原贴图/骨骼/动画映射到新布局', en: 'smart UV unwrap; remaps textures/rig/animation onto the new layout' } },
35
36
  // mesh/edit: local retry/refine inside a bbox, P2 pipeline (model fixed to P2-20260801).
36
37
  { name: 'edit', endpoint: '/v3/mesh/edit', produces: 'mesh_edit', accepts: 'any-model', acceptsFile: true, describe: { zh: '在 bbox 区域内局部重做(P2 管线)', en: 'redo one bbox region locally (P2 pipeline)' } },
37
38
  // smartsegment's `input` is file_token/URL only (the server does not resolve
@@ -69,7 +70,7 @@ export function getStep(name) {
69
70
  * Parse a --then expression: "texture,rig,convert:fbx" or
70
71
  * "convert:format=fbx,texture_size=2048". A bare value after ":" is sugar for
71
72
  * the step's primary argument (convert→format, retarget→animation,
72
- * stylize→style, decimate→face_limit).
73
+ * decimate→face_limit).
73
74
  */
74
75
  export function parseThenExpression(expr) {
75
76
  const out = [];
@@ -114,7 +115,6 @@ function applyPrimaryArg(step, args, value) {
114
115
  const primary = {
115
116
  convert: 'format',
116
117
  retarget: 'animation',
117
- stylize: 'style',
118
118
  decimate: 'face_limit',
119
119
  texture: 'texture_quality',
120
120
  rig: 'rig_type',
@@ -109,7 +109,7 @@ export const TEXTURE_MODELS = ['v3.0-20250812', 'v2.5-20250123'];
109
109
  /** mesh_segmentation whitelist (ALLOWED_SEGMENT_MODELS). */
110
110
  export const SEGMENT_MODELS = ['v1.0-20250506', 'v2.0-20260430'];
111
111
  /** mesh/decimate whitelist (ALLOWED_DECIMATE_MODELS; blank/"default" → server default v2.0). */
112
- export const DECIMATE_MODELS = ['v2.0', 'v1.0'];
112
+ export const DECIMATE_MODELS = ['v3.0', 'v2.0', 'v1.0'];
113
113
  /** Server whitelists differ per endpoint (ImageGenerationValidation). */
114
114
  export const TEXT_TO_IMAGE_TEMPLATES = [
115
115
  'asset_extraction',
@@ -139,7 +139,6 @@ export const TEXTURE_FORMATS = [
139
139
  ];
140
140
  export const FBX_PRESETS = ['blender', '3dsmax', 'mixamo'];
141
141
  export const EXPORT_ORIENTATIONS = ['+x', '-x', '+y', '-y'];
142
- export const STYLIZE_STYLES = ['lego', 'voxel', 'voronoi', 'minecraft'];
143
142
  export const TEXTURE_QUALITIES = ['standard', 'detailed', 'extreme'];
144
143
  /** Normalize any accepted alias to the canonical wire value; unknown values pass through. */
145
144
  export function normalizeModel(input) {
@@ -5,7 +5,7 @@
5
5
  * Every rule here prevents a guaranteed 400 or a silently wasted credit.
6
6
  * Rules marked [hard] mirror server enforcement; [soft] are CLI smart defaults.
7
7
  */
8
- import { CONVERT_FORMATS, EXPORT_ORIENTATIONS, FBX_PRESETS, MODEL_P2, P1_FACE_LIMIT, P1_FORBIDDEN_PARAMS, P2_FACE_LIMIT, P2_FORBIDDEN_PARAMS, TEXTURE_FORMATS, TEXTURE_QUALITIES, isP1, isP2, normalizeModel, } from './models.js';
8
+ import { CONVERT_FORMATS, DECIMATE_MODELS, EXPORT_ORIENTATIONS, FBX_PRESETS, MODEL_P2, P1_FACE_LIMIT, P1_FORBIDDEN_PARAMS, P2_FACE_LIMIT, P2_FORBIDDEN_PARAMS, TEXTURE_FORMATS, TEXTURE_QUALITIES, isP1, isP2, normalizeModel, } from './models.js';
9
9
  const PROMPT_MAX = 1024;
10
10
  const NEGATIVE_PROMPT_MAX = 255;
11
11
  /** Validate + auto-fix parameters for 3D generation (text/image/multiview-to-model). */
@@ -168,7 +168,8 @@ export function validateConvertParams(input) {
168
168
  }
169
169
  /**
170
170
  * Validate parameters for mesh/decimate (ModelPostProcessValidation):
171
- * v2.0 (default): face_limit 500–20000 tri / 500–10000 quad.
171
+ * v2.0 (default) / v3.0: face_limit 500–20000 tri / 500–10000 quad.
172
+ * v3.0 only: smart_uv (UV unwrap in the same task).
172
173
  * v1.0: face_limit REQUIRED, 500–2,000,000 tri / 500–150,000 quad; no bake/part_names.
173
174
  */
174
175
  export function validateDecimateParams(input) {
@@ -176,8 +177,18 @@ export function validateDecimateParams(input) {
176
177
  const warnings = [];
177
178
  const errors = [];
178
179
  const model = typeof params.model === 'string' ? params.model.toLowerCase() : undefined;
179
- if (model !== undefined && !['v1.0', 'v2.0', 'default'].includes(model)) {
180
- errors.push(`decimate model must be v2.0 or v1.0 (got "${String(params.model)}")`);
180
+ if (model !== undefined && model !== 'default' && !DECIMATE_MODELS.includes(model)) {
181
+ errors.push(`decimate model must be ${DECIMATE_MODELS.join('/')} (got "${String(params.model)}")`);
182
+ }
183
+ // [hard] smart_uv is v3.0-only (server: 1004 on v1.0/v2.0); [soft] no model given → v3.0.
184
+ if (params.smart_uv === true) {
185
+ if (model === undefined) {
186
+ params.model = 'v3.0';
187
+ warnings.push('smart_uv requires decimate v3.0: using model=v3.0 (35 credits tri / 40 quad; v2.0 is 30)');
188
+ }
189
+ else if (model !== 'v3.0') {
190
+ errors.push(`smart_uv only works with decimate model v3.0 (got "${String(params.model)}")`);
191
+ }
181
192
  }
182
193
  const isV1 = model === 'v1.0';
183
194
  const quad = params.quad === true;
@@ -92,14 +92,14 @@ export const SCENARIOS = [
92
92
  {
93
93
  id: 'toy',
94
94
  label: { zh: '风格化摆件', en: 'Stylized toy / desk piece' },
95
- description: { zh: '低模可爱风或积木/体素风格化', en: 'Cute low-poly or brick/voxel stylization' },
95
+ description: { zh: '低模可爱风摆件', en: 'Cute low-poly desk piece' },
96
96
  model: MODEL_P1,
97
97
  genParams: { texture: true, pbr: true, face_limit: 20000 },
98
98
  chain: [],
99
99
  deliverables: ['GLB', 'STL via convert'],
100
100
  notes: {
101
- zh: ['P1 出干净低模', '积木/体素风追加 --then stylize:lego 或 stylize:voxel', '要打印实物追加 --then convert:stl'],
102
- en: ['P1 produces clean low-poly', 'append --then stylize:lego or stylize:voxel for brick/voxel looks', 'append --then convert:stl to print it'],
101
+ zh: ['P1 出干净低模', '要打印实物追加 --then convert:stl'],
102
+ en: ['P1 produces clean low-poly', 'append --then convert:stl to print it'],
103
103
  },
104
104
  },
105
105
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tripo-cli",
3
- "version": "0.5.2",
3
+ "version": "0.6.1",
4
4
  "description": "Tripo 3D intelligent CLI — turn a prompt or an image into engine-ready 3D assets from your terminal (Tripo V3 API)",
5
5
  "keywords": [
6
6
  "tripo",
package/skill/SKILL.md CHANGED
@@ -50,8 +50,8 @@ tripo make @last --then convert:fbx --json --yes # continue from last t
50
50
  ```
51
51
 
52
52
  - `--for` scenario presets: `game-mobile` `game-pc` `film` `print` `ar-web` `anim` `toy`
53
- - `--then` chain steps: `refine texture stylize convert import rig-check rig retarget segment complete decimate smartsegment`
54
- - step args: `convert:format=FBX,texture_size=2048` (bare value = primary arg: `convert:fbx`, `stylize:lego`, `decimate:5000`)
53
+ - `--then` chain steps: `refine texture convert import rig-check rig retarget segment complete decimate uv smartsegment`
54
+ - step args: `convert:format=FBX,texture_size=2048` (bare value = primary arg: `convert:fbx`, `decimate:5000`)
55
55
  - Output JSON: `{"task_id","type","status","credits_consumed","output_dir","files",["model_file"],["preview"],["chain"],["credits_breakdown"]}` — with `--then`, `credits_consumed` is the **total** for the run and `credits_breakdown` itemizes every task (`[{task_id,type,credits_consumed}]`, generation first)
56
56
 
57
57
  ## Pipes (composing steps yourself)
@@ -40,7 +40,7 @@ In a TTY it then asks `Run this plan?`; answering no exits 0 with `cancelled; no
40
40
  ## Options
41
41
 
42
42
  - `--for <scenario>` — `game-mobile` `game-pc` `film` `print` `ar-web` `anim` `toy`. Sets model+params+chain+format from the domain knowledge base.
43
- - `--then <steps>` — processing chain, comma-separated. Steps: `refine texture stylize convert import rig-check rig retarget segment complete decimate smartsegment`. Args: `step:key=value,...`; bare value maps to the step's primary arg (`convert:fbx` → format, `stylize:lego` → style, `decimate:5000` → face_limit, `retarget:preset:walk` → animation). Overrides the scenario chain.
43
+ - `--then <steps>` — processing chain, comma-separated. Steps: `refine texture convert import rig-check rig retarget segment complete decimate uv smartsegment`. Args: `step:key=value,...`; bare value maps to the step's primary arg (`convert:fbx` → format, `decimate:5000` → face_limit, `retarget:preset:walk` → animation). Overrides the scenario chain.
44
44
  - `--model <m>` — force `tripo-v3.1` (high fidelity, default), `tripo-p1` (low-poly; face_limit 50–20000; quad/parts/geometry_quality unsupported and stripped) or `tripo-p2` (P-series preview; adds quad, face_limit 48–50000 tri / 48–25000 quad; never auto-selected). The CLI normalizes these aliases to the wire versions (`v3.1-20260211` / `P1-20260311` / `P2-20260801`) the server actually accepts. Full table with status (GA / Preview / Legacy) and official links: `tripo docs --topic commands/generate` → "Models & Versions".
45
45
  - `-n, --candidates <n>` — up to 4 parallel candidates with different seeds (interactive pick when chaining).
46
46
  - `--seed <n>` — fixed model_seed for reproducible geometry.
@@ -9,7 +9,6 @@ Any API parameter without a first-class flag can be passed with `-p key=value` (
9
9
  ```bash
10
10
  tripo model refine [input] # only accepts text_to_model tasks
11
11
  tripo model texture [input] --texture-quality detailed --texture-alignment geometry [-p pbr=true]
12
- tripo model stylize [input] --style lego|voxel|voronoi|minecraft [--block-size 80]
13
12
  tripo model convert [input] --format GLTF|USDZ|FBX|OBJ|STL|3MF \
14
13
  [--texture-size 2048] [--texture-format JPEG|PNG|OPEN_EXR|...] [--face-limit N] \
15
14
  [--quad] [--flatten-bottom] [--fbx-preset blender|3dsmax|mixamo] \
@@ -22,7 +21,6 @@ tripo model import <file-or-url> # GLB/GLTF/FBX/OBJ/STL ≤150MB
22
21
  | --- | --- | --- |
23
22
  | `refine` | successful `text_to_model` task only | `model` (default `tripo-v3.1`) |
24
23
  | `texture` | task / file / URL (file/URL is imported implicitly) | `model` `v3.0-20250812` (default) / `v2.5-20250123`; `texture_quality` standard/detailed/extreme; `pbr` (default true); `texture_seed`; `texture_alignment` original_image/geometry |
25
- | `stylize` | task / file (no URL) | `style` lego/voxel/voronoi/minecraft; `block_size` 32–128 (minecraft only, default 80) |
26
24
  | `convert` | task / file | see table below; `format` required |
27
25
  | `import` | file / URL | GLB / GLTF / FBX / OBJ / STL ≤150 MB. `.gltf` references external files, so it only works as a URL — upload `.glb` |
28
26
 
@@ -92,7 +90,8 @@ All prefixed `preset:biped:`
92
90
  ```bash
93
91
  tripo mesh segment [input] [--model v1.0-20250506|v2.0-20260430]
94
92
  tripo mesh complete [input] [--completion-mode ai_completion|quick_cap] # needs a segment task
95
- tripo mesh decimate [input] --face-limit 5000 [--quad] [--no-bake] # 500–20000 tri / 500–10000 quad
93
+ tripo mesh decimate [input] --face-limit 5000 [--model v3.0|v2.0|v1.0] [--quad] [--smart-uv] [--no-bake] # 500–20000 tri / 500–10000 quad
94
+ tripo mesh uv [input] [--no-bake] [--export-orientation +x|-x|+y|-y] # input ≤ 80,000 equivalent triangles
96
95
  tripo mesh smartsegment <file-or-url> [--seg-type image|model] [--granularity coarse|medium|fine] [--hint "..."]
97
96
  ```
98
97
 
@@ -100,9 +99,12 @@ tripo mesh smartsegment <file-or-url> [--seg-type image|model] [--granularity co
100
99
  | --- | --- | --- |
101
100
  | `segment` | task / file / URL | `model` `v1.0-20250506` (default, geometry-based) / `v2.0-20260430` (Beta, semantic labels + geometry). **v2 only**: `segmentation_granularity` simple/balanced/detailed (default balanced), `split_by_connectivity` (default true), `ref_image` file_token/URL — when `ref_image` is set the other two are ignored; setting `ref_image` on v1 → `1004` |
102
101
  | `complete` | **segment task only** | `completion_mode` `ai_completion` (AI diffusion, default) / `quick_cap` (fast hole-fill, no AI); `part_names` (default: all parts); `model` `v1.0-20250506` (only version) |
103
- | `decimate` | task / file | `face_limit` (docs quote 1000–20000; CLI accepts 500–20000 tri / 500–10000 quad); `quad`; `bake` (default true — bake textures onto the low-poly, right for LODs); `part_names`. `-p model=v1.0`: up to 2,000,000 tri / 150,000 quad but `face_limit` becomes required and `bake`/`part_names` are unsupported |
102
+ | `decimate` | task / file / URL | `model` `v2.0` (default, smart retopology, 30 credits) / `v3.0` (newest retopology, 35 credits tri / 40 quad) / `v1.0` (basic decimation, 10 credits); `face_limit` (v2.0/v3.0: optional, 500–20000 tri / 500–10000 quad, adaptive if omitted); `quad`; `bake` (default true — bake textures onto the low-poly, right for LODs); `part_names`; `smart_uv` (**v3.0 only**, default false — unwrap UVs in the same task, no extra cost, no UV atlas image; `--smart-uv` without `--model` selects v3.0, an explicit v1.0/v2.0 is rejected locally because the server answers `1004`). `--model v1.0`: up to 2,000,000 tri / 150,000 quad but `face_limit` becomes required and `bake`/`part_names` are unsupported |
103
+ | `uv` | task / file / URL | re-unwraps UVs and remaps the existing textures, rig and animation onto the new layout; **20 credits**. `bake` (default true; `--no-bake` returns geometry + UVs only); `export_orientation` `+x`/`-x`/`+y`/`-y`; `compress` `geometry` (meshopt, `-p compress=geometry`); `model` `default` (only value). **Input ≤ 80,000 equivalent triangles** (a quad counts as two): larger inputs are accepted, then the task fails and refunds — decimate first |
104
104
  | `smartsegment` | **file / URL only (no task ids)** | `seg_type` `image` (photo → auto-model → segment, **85 credits**) / `model` (existing **GLB only** → segment, **55 credits**; CLI default); `granularity` coarse/medium/fine (default medium); `hint` free text describing the parts; `transform` 4×4 column-major matrix required for `model` — the CLI auto-fills identity |
105
105
 
106
106
  - `segment` vs `smartsegment`: segment only splits an existing model; smartsegment is the end-to-end pipeline (asset → auto modelling → segmentation).
107
107
  - smartsegment output: `prompt` (comma-separated part labels), `mask_url` (PNG semantic mask), `seg_model_url` (segmented GLB), `seg_task_id` (inner segmentation task), `model_task_id` (inner image_to_model / import task). Task types: `smartsegment_image` / `smartsegment_model`.
108
108
  - `mesh complete` only accepts segmentation tasks; segmented / completed parts can then be exported selectively via `convert -p 'part_names=[...]'`.
109
+ - UVs in one task or two: `decimate --smart-uv` (v3.0) unwraps during retopology — one task, no atlas image. `uv` is its own task that also returns the UV atlas; run it on models that are already under the limit, e.g. `--then decimate:20000,uv`.
110
+ - uv output: the model plus `uv_render.webp` (the UV atlas). It is a flat layout, not a render of the model, so the CLI does not copy it to `preview.png`.
@@ -4,7 +4,7 @@
4
4
  | --- | --- | --- | --- |
5
5
  | 3 | 1002 | authentication failed (invalid/missing API key) | set `TRIPO_API_KEY` or run `tripo login`; check the key wasn't revoked |
6
6
  | 3 | 1005 | forbidden (no permission for this resource) | check account permissions |
7
- | 2 | 1003/1004 | malformed request / invalid parameter | check spelling against `tripo docs --topic commands/<cmd>`; the CLI already strips illegal P1 params. Classic 1004s: `generate_parts=true` with texture/pbr on, `ref_image` on segment v1, `quad=true` on P1, non-GLB input to smartsegment `model` / rig-check. `invalid model`: the API only accepts dated wire values (`P2-20260801`, `v3.1-20260211`…) — pass the CLI alias (`--model tripo-p2`) and let the CLI normalize, or the wire value itself; never `tripo-*` straight to the API. Table: `commands/generate` § "Models & Versions" |
7
+ | 2 | 1003/1004 | malformed request / invalid parameter | check spelling against `tripo docs --topic commands/<cmd>`; the CLI already strips illegal P1 params. Classic 1004s: `generate_parts=true` with texture/pbr on, `ref_image` on segment v1, `quad=true` on P1, `smart_uv=true` on decimate v1.0/v2.0, non-GLB input to smartsegment `model` / rig-check. `invalid model`: the API only accepts dated wire values (`P2-20260801`, `v3.1-20260211`…) — pass the CLI alias (`--model tripo-p2`) and let the CLI normalize, or the wire value itself; never `tripo-*` straight to the API. Table: `commands/generate` § "Models & Versions" |
8
8
  | 9 | 1007 | per-API-key rate limit | wait and retry with backoff; honour `Retry-After` / `X-RateLimit-Reset` headers |
9
9
  | 9 | 2000 | per-account concurrency pool full (see table below) | wait for a task in that category to finish, or lower `--concurrency` in batch; other categories are unaffected |
10
10
  | 8 | 2001 | task not found | task ids are account-scoped — same key that created it? right region (ov/cn)? |
@@ -42,6 +42,7 @@ Pools are independent: a full H-series pool does not block P-series or image tas
42
42
  - `complete` only accepts a `segment` task; `retarget` only accepts a `rig` task
43
43
  - quad + GLTF export → rejected (quads cannot be stored in glTF); use FBX/OBJ/USDZ
44
44
  - P1 + face_limit outside 50–20000 → rejected with a suggestion to use v3.1
45
+ - decimate `smart_uv` on an explicit v1.0/v2.0 → rejected (v3.0 only); with no model given the CLI selects v3.0
45
46
  - multiview without a front view → rejected (name a file "front" or pass it first)
46
47
  - `-n` with `--then` needs an interactive terminal (pick the winner first, then chain)
47
48
 
@@ -57,3 +58,4 @@ All of these surface in `tripo make ... --dry-run --json` as `errors` (blocking)
57
58
  - A downstream step after a generation that used `export_orientation` succeeds but comes out **wrongly oriented** — no error is raised. Set the orientation on the final `convert` step instead.
58
59
  - `generate_parts` with `smart_low_poly=true` silently produces no parts (smart_low_poly wins); with `quad=true` the parts are triangles.
59
60
  - `image-to-splat` yields a `.splat`, not a mesh — texture / rig / convert steps cannot follow it.
61
+ - `uv` accepts any model at creation, but an input over 80,000 equivalent triangles fails at run time (credits refunded) — decimate first: `--then decimate:20000,uv`.