tripo-cli 0.5.1 → 0.6.0
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 +2 -2
- package/dist/commands/completion.js +1 -1
- package/dist/commands/process-groups.js +11 -2
- package/dist/core/client.js +23 -5
- package/dist/core/download.js +2 -1
- package/dist/core/errors.js +5 -1
- package/dist/core/task-service.js +10 -2
- package/dist/knowledge/chains.js +2 -0
- package/dist/knowledge/models.js +1 -1
- package/dist/knowledge/params.js +15 -4
- package/package.json +1 -1
- package/skill/SKILL.md +2 -2
- package/skill/commands/make.md +1 -1
- package/skill/commands/process.md +6 -2
- package/skill/commands/task.md +1 -1
- package/skill/common-errors.md +6 -4
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, stylize, 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 |
|
|
@@ -91,7 +91,7 @@ tripo batch run assets.yaml --concurrency 2
|
|
|
91
91
|
|
|
92
92
|
- `make`/`watch` are blocking: run them, wait for exit, read the single JSON line on stdout. Do not poll yourself.
|
|
93
93
|
- The plan card on stderr lists every call before it runs; the final JSON carries `credits_consumed` (total for the run) plus `credits_breakdown` (per task) when a chain ran.
|
|
94
|
-
- Exit codes: `0` ok · `2` usage · `3` auth · `4` insufficient credits · `5` content policy · `6` task failed (credits auto-refunded) · `7` network · `8` not found · `9` rate limit.
|
|
94
|
+
- Exit codes: `0` ok · `2` usage · `3` auth · `4` insufficient credits · `5` content policy · `6` task failed (credits auto-refunded; a `timeout` means it is still running) · `7` network (a failed submit is never resent — check `tripo balance` before re-running) · `8` not found · `9` rate limit.
|
|
95
95
|
- `preview.png` in every output directory is your eyes: look at it, then decide to `tripo redo` or continue the chain.
|
|
96
96
|
- Full behavior rules: `tripo docs --llm`, per-command docs via `tripo docs --topic commands/make`.
|
|
97
97
|
|
|
@@ -11,7 +11,7 @@ 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
12
|
model: ['refine', 'texture', 'stylize', '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'],
|
|
@@ -77,7 +77,9 @@ function collectStepArgs(step, flags) {
|
|
|
77
77
|
case 'retarget':
|
|
78
78
|
return pick(['animation', 'out_format', 'animate_in_place']);
|
|
79
79
|
case 'decimate':
|
|
80
|
-
return pick(['face_limit', 'quad', 'bake']);
|
|
80
|
+
return pick(['model', 'face_limit', 'quad', 'smart_uv', 'bake']);
|
|
81
|
+
case 'uv':
|
|
82
|
+
return pick(['bake', 'export_orientation']);
|
|
81
83
|
case 'segment':
|
|
82
84
|
return pick(['model']);
|
|
83
85
|
case 'complete':
|
|
@@ -147,7 +149,7 @@ export function registerProcessCommands(program) {
|
|
|
147
149
|
await makeStepAction('retarget')(input, flags);
|
|
148
150
|
});
|
|
149
151
|
// ---- tripo mesh ----
|
|
150
|
-
const mesh = program.command('mesh').description('mesh ops: segment / complete / decimate / smartsegment');
|
|
152
|
+
const mesh = program.command('mesh').description('mesh ops: segment / complete / decimate / uv / smartsegment');
|
|
151
153
|
withTaskOptions(mesh.command('segment [input]').description('segment a model into parts').option('--model <v>', 'v1.0-20250506|v2.0-20260430')).action(makeStepAction('segment'));
|
|
152
154
|
withTaskOptions(mesh
|
|
153
155
|
.command('complete [input]')
|
|
@@ -156,9 +158,16 @@ export function registerProcessCommands(program) {
|
|
|
156
158
|
withTaskOptions(mesh
|
|
157
159
|
.command('decimate [input]')
|
|
158
160
|
.description('high-poly → low-poly (bakes textures by default)')
|
|
161
|
+
.option('--model <v>', 'v3.0|v2.0|v1.0 (default v2.0)')
|
|
159
162
|
.option('--face-limit <n>', 'target faces 500–20000 tri / 500–10000 quad', (v) => Number(v))
|
|
160
163
|
.option('--quad', 'quad output')
|
|
164
|
+
.option('--smart-uv', 'unwrap UVs in the same task (v3.0 only; selects v3.0 when --model is omitted)')
|
|
161
165
|
.option('--no-bake', 'skip baking textures onto the low-poly')).action(makeStepAction('decimate'));
|
|
166
|
+
withTaskOptions(mesh
|
|
167
|
+
.command('uv [input]')
|
|
168
|
+
.description('smart UV unwrap; remaps textures/rig/animation (input ≤80k equivalent triangles)')
|
|
169
|
+
.option('--no-bake', 'skip baking textures onto the new UV layout (geometry + UVs only)')
|
|
170
|
+
.option('--export-orientation <o>', '+x|-x|+y|-y')).action(makeStepAction('uv'));
|
|
162
171
|
// Hidden until /v3/mesh/edit is live server-side (see isMeshEditEnabled).
|
|
163
172
|
if (isMeshEditEnabled()) {
|
|
164
173
|
withTaskOptions(mesh
|
package/dist/core/client.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Lightweight V3 API client on top of global fetch (Node 20+).
|
|
3
3
|
* Handles the response envelope, error translation, timeouts, and
|
|
4
|
-
* exponential-backoff retries for transient failures (429/5xx/network
|
|
4
|
+
* exponential-backoff retries for transient failures (429/5xx/network;
|
|
5
|
+
* task creation is only resent on 429).
|
|
5
6
|
*/
|
|
6
7
|
import { activeProfileName, DEFAULT_PROFILE, listProfiles, loadConfig, resolveApiBaseUrl, resolveApiKey } from '../config/config.js';
|
|
7
8
|
import { t } from '../i18n.js';
|
|
9
|
+
import { EXIT } from '../knowledge/error-catalog.js';
|
|
8
10
|
import { ApiError, AuthError, NetworkError } from './errors.js';
|
|
9
11
|
export class TripoClient {
|
|
10
12
|
baseUrl;
|
|
@@ -37,10 +39,11 @@ export class TripoClient {
|
|
|
37
39
|
this.maxRetries = options.maxRetries ?? 3;
|
|
38
40
|
this.onRetry = options.onRetry;
|
|
39
41
|
}
|
|
40
|
-
async request(method, path, body) {
|
|
42
|
+
async request(method, path, body, options = {}) {
|
|
41
43
|
return this.send(method, path, {
|
|
42
44
|
headers: { 'Content-Type': 'application/json' },
|
|
43
45
|
body: body === undefined ? undefined : JSON.stringify(body),
|
|
46
|
+
idempotent: options.idempotent,
|
|
44
47
|
});
|
|
45
48
|
}
|
|
46
49
|
async uploadFile(fileName, data) {
|
|
@@ -61,7 +64,11 @@ export class TripoClient {
|
|
|
61
64
|
}
|
|
62
65
|
catch (err) {
|
|
63
66
|
lastError = err;
|
|
64
|
-
|
|
67
|
+
// A create that timed out or hit a 5xx may already be accepted (and
|
|
68
|
+
// billed); only a rate-limit rejection proves the server did nothing.
|
|
69
|
+
const retryable = init.idempotent === false
|
|
70
|
+
? err instanceof ApiError && err.exitCode === EXIT.RATE_LIMIT
|
|
71
|
+
: err instanceof NetworkError || (err instanceof ApiError && err.retryable);
|
|
65
72
|
if (!retryable || attempt === this.maxRetries)
|
|
66
73
|
throw err;
|
|
67
74
|
}
|
|
@@ -134,8 +141,19 @@ export class TripoClient {
|
|
|
134
141
|
}
|
|
135
142
|
/** Create a task; returns its id. Response may be {task_id} or a full detail. */
|
|
136
143
|
async createTask(endpoint, payload) {
|
|
137
|
-
|
|
138
|
-
|
|
144
|
+
try {
|
|
145
|
+
const data = await this.request('POST', endpoint, payload, { idempotent: false });
|
|
146
|
+
return data.task_id;
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
if (err instanceof NetworkError || (err instanceof ApiError && err.exitCode === EXIT.NETWORK)) {
|
|
150
|
+
err.suggestion = t({
|
|
151
|
+
zh: '任务可能已在服务端创建并冻结积分;重试前先用 tripo balance 查看冻结额或到控制台确认,避免重复扣费',
|
|
152
|
+
en: 'the task may already exist server-side (credits frozen); check "tripo balance" or the console before retrying, to avoid a duplicate charge',
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
throw err;
|
|
156
|
+
}
|
|
139
157
|
}
|
|
140
158
|
}
|
|
141
159
|
export function sleep(ms) {
|
package/dist/core/download.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
package/dist/core/errors.js
CHANGED
|
@@ -45,13 +45,17 @@ export class NetworkError extends CliError {
|
|
|
45
45
|
}
|
|
46
46
|
export class TaskFailedError extends CliError {
|
|
47
47
|
taskId;
|
|
48
|
+
status;
|
|
48
49
|
constructor(taskId, status, detail) {
|
|
49
50
|
const refundNote = t({
|
|
50
51
|
zh: '预扣积分已自动退还',
|
|
51
52
|
en: 'frozen credits have been refunded automatically',
|
|
52
53
|
});
|
|
53
|
-
super(
|
|
54
|
+
super(
|
|
55
|
+
// A timed-out task is still running server-side: nothing has been refunded.
|
|
56
|
+
`task ${taskId} ${status}${detail ? `: ${detail}` : ''}${status === 'timeout' ? '' : ` (${refundNote})`}`, EXIT.TASK_FAILED);
|
|
54
57
|
this.taskId = taskId;
|
|
58
|
+
this.status = status;
|
|
55
59
|
}
|
|
56
60
|
}
|
|
57
61
|
/** Decorate insufficient-balance errors with the topup path and the gap. */
|
|
@@ -13,7 +13,7 @@ import { detectInput } from '../util/input-detect.js';
|
|
|
13
13
|
import { notifyDone } from '../util/notify.js';
|
|
14
14
|
import { createSpinner } from '../util/spinner.js';
|
|
15
15
|
import { defaultOutputDir, downloadArtifacts } from './download.js';
|
|
16
|
-
import { ApiError, UsageError, balanceSuggestion } from './errors.js';
|
|
16
|
+
import { ApiError, CliError, TaskFailedError, UsageError, balanceSuggestion } from './errors.js';
|
|
17
17
|
import { isQuiet, log, warn } from './output.js';
|
|
18
18
|
import { uploadLocalFile } from './upload.js';
|
|
19
19
|
/** Placeholder `input` value for a local file that a dry run would upload. */
|
|
@@ -115,7 +115,15 @@ export async function runTask(options) {
|
|
|
115
115
|
}
|
|
116
116
|
catch (err) {
|
|
117
117
|
spinner.fail(`${taskType} · ${taskId}`);
|
|
118
|
-
|
|
118
|
+
if (err instanceof TaskFailedError && err.status !== 'timeout') {
|
|
119
|
+
updateHistoryStatus(taskId, 'failed');
|
|
120
|
+
}
|
|
121
|
+
else if (err instanceof CliError) {
|
|
122
|
+
err.suggestion = t({
|
|
123
|
+
zh: `任务仍在服务端运行,成功后照常扣费;用 tripo task watch ${taskId} --download 继续等待,不要重新提交`,
|
|
124
|
+
en: `the task keeps running server-side and is billed if it succeeds; resume with "tripo task watch ${taskId} --download" instead of resubmitting`,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
119
127
|
throw err;
|
|
120
128
|
}
|
|
121
129
|
updateHistoryStatus(taskId, 'success', { credits_consumed: task.credits_consumed });
|
package/dist/knowledge/chains.js
CHANGED
|
@@ -17,6 +17,7 @@ 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
|
]);
|
|
@@ -32,6 +33,7 @@ export const STEPS = [
|
|
|
32
33
|
{ name: 'segment', endpoint: '/v3/mesh/segment', produces: 'mesh_segmentation', accepts: 'any-model', acceptsFile: true, describe: { zh: '把网格分割成部件', en: 'segment the mesh into parts' } },
|
|
33
34
|
{ name: 'complete', endpoint: '/v3/mesh/complete', produces: 'mesh_completion', accepts: ['mesh_segmentation'], acceptsFile: false, describe: { zh: '补全分割后的部件', en: 'complete the segmented parts' } },
|
|
34
35
|
{ 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' } },
|
|
36
|
+
{ 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
37
|
// mesh/edit: local retry/refine inside a bbox, P2 pipeline (model fixed to P2-20260801).
|
|
36
38
|
{ 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
39
|
// smartsegment's `input` is file_token/URL only (the server does not resolve
|
package/dist/knowledge/models.js
CHANGED
|
@@ -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',
|
package/dist/knowledge/params.js
CHANGED
|
@@ -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 &&
|
|
180
|
-
errors.push(`decimate model must be
|
|
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;
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -34,7 +34,7 @@ Regions (ov = international, cn = China mainland) share one CLI: `tripo login --
|
|
|
34
34
|
2. **stdout is the contract; stderr is commentary.** With `--json` (auto-enabled when piped), stdout carries exactly one final JSON line. Progress/logs go to stderr.
|
|
35
35
|
3. **Artifacts are local files.** The result JSON has `output_dir`, `model_file`, `preview`. Look at `preview.png` to judge quality; re-roll with `tripo redo` if needed.
|
|
36
36
|
4. **Exit codes are stable** — branch on them:
|
|
37
|
-
- 0 success · 2 usage/params · 3 auth · 4 insufficient credits (tell the human to run `tripo topup`) · 5 content policy · 6 task failed (credits auto-refunded) · 7 network · 8 not found · 9 rate limit (retry with backoff)
|
|
37
|
+
- 0 success · 2 usage/params · 3 auth · 4 insufficient credits (tell the human to run `tripo topup`) · 5 content policy · 6 task failed (credits auto-refunded; on `timeout` it is still running — `tripo task watch <id>`, never redo) · 7 network (a failed submit is never resent and may already exist — check `tripo balance` before re-running) · 8 not found · 9 rate limit (retry with backoff)
|
|
38
38
|
5. **Never invent parameters.** Unknown `--param key=value` pairs pass through to the API; stick to documented ones. The full parameter/model/preset reference from the official API docs is bundled: `tripo docs --topic commands/generate` (3D + image generation) and `tripo docs --topic commands/process` (texture/convert/rig/retarget/mesh) — read those instead of browsing the website.
|
|
39
39
|
6. **Validate before spending: `--dry-run --json`.** Same command plus `--dry-run` prints the plan as JSON with zero network calls and no credits: the chosen `model`, the completed `steps[].payload` for every API call, `warnings` (auto-adjustments) and `errors` (blocking; exit 2). When `valid` is true, re-run without `--dry-run`. Details: `tripo docs --topic commands/make` § "Dry run".
|
|
40
40
|
7. **Don't pick legacy model versions.** The CLI auto-selects `tripo-v3.1` (high fidelity) or `tripo-p1` (low-poly, face budget ≤ 20000). Only override `--model` when the human asks (e.g. `--model tripo-p2` for the P-series **Preview** with quad support, or `tripo-v3.0` / `tripo-v2.5` for reproducing old projects). `tripo-*` names are CLI aliases — the CLI sends the dated wire value (`tripo-p2` → `P2-20260801`); the API rejects the alias itself with 1004. Alias ↔ wire ↔ status table: `tripo docs --topic commands/generate` ("Models & Versions").
|
|
@@ -50,7 +50,7 @@ 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`
|
|
53
|
+
- `--then` chain steps: `refine texture stylize convert import rig-check rig retarget segment complete decimate uv smartsegment`
|
|
54
54
|
- step args: `convert:format=FBX,texture_size=2048` (bare value = primary arg: `convert:fbx`, `stylize:lego`, `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
|
|
package/skill/commands/make.md
CHANGED
|
@@ -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 stylize 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, `stylize:lego` → style, `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.
|
|
@@ -92,7 +92,8 @@ All prefixed `preset:biped:`
|
|
|
92
92
|
```bash
|
|
93
93
|
tripo mesh segment [input] [--model v1.0-20250506|v2.0-20260430]
|
|
94
94
|
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]
|
|
95
|
+
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
|
|
96
|
+
tripo mesh uv [input] [--no-bake] [--export-orientation +x|-x|+y|-y] # input ≤ 80,000 equivalent triangles
|
|
96
97
|
tripo mesh smartsegment <file-or-url> [--seg-type image|model] [--granularity coarse|medium|fine] [--hint "..."]
|
|
97
98
|
```
|
|
98
99
|
|
|
@@ -100,9 +101,12 @@ tripo mesh smartsegment <file-or-url> [--seg-type image|model] [--granularity co
|
|
|
100
101
|
| --- | --- | --- |
|
|
101
102
|
| `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
103
|
| `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 | `
|
|
104
|
+
| `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 |
|
|
105
|
+
| `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
106
|
| `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
107
|
|
|
106
108
|
- `segment` vs `smartsegment`: segment only splits an existing model; smartsegment is the end-to-end pipeline (asset → auto modelling → segmentation).
|
|
107
109
|
- 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
110
|
- `mesh complete` only accepts segmentation tasks; segmented / completed parts can then be exported selectively via `convert -p 'part_names=[...]'`.
|
|
111
|
+
- 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`.
|
|
112
|
+
- 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`.
|
package/skill/commands/task.md
CHANGED
|
@@ -12,7 +12,7 @@ tripo task get @last --download --json
|
|
|
12
12
|
|
|
13
13
|
Block until the task finishes. In `--json` mode, progress streams as NDJSON events on stdout (`{"event":"progress",...}` lines) and the final task detail is the last line. `--download` grabs artifacts on success. `--timeout <seconds>` (default 1800).
|
|
14
14
|
|
|
15
|
-
Rules for agents: treat `watch` as synchronous; read lines until process exit; exit code 6 means the task failed (credits refunded).
|
|
15
|
+
Rules for agents: treat `watch` as synchronous; read lines until process exit; exit code 6 means the task failed (credits refunded) — or, if the error says `timeout`, that it is still running (watch it again; do not resubmit).
|
|
16
16
|
|
|
17
17
|
## tripo task list [ids...]
|
|
18
18
|
|
package/skill/common-errors.md
CHANGED
|
@@ -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)? |
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
| 2 | 2018 | too complex to remesh | lower `face_limit` or simplify the input model |
|
|
20
20
|
| 8 | 2019 | file not found (token expired?) | re-upload; file tokens are short-lived |
|
|
21
21
|
| 2 | 2020/2021/2022 | bad image URL / file too large / image too large | fix the URL or shrink the file |
|
|
22
|
-
| 7 | 1000/1001 | server-side error |
|
|
23
|
-
| 6 | — | task failed server-side | frozen credits auto-refund; `tripo redo` often succeeds with a new seed |
|
|
24
|
-
| 7 | — | network/5xx | auto-retried 3
|
|
22
|
+
| 7 | 1000/1001 | server-side error | queries auto-retry on 1000, task creation does not (the task may already exist and be billed — check `tripo balance` frozen credits before re-running); if persistent, contact support with the `request_id` |
|
|
23
|
+
| 6 | — | task failed server-side, or the watch timed out | failed: frozen credits auto-refund; `tripo redo` often succeeds with a new seed. `timeout`: the task is still running and is billed if it succeeds — `tripo task watch <id> --download`, never redo |
|
|
24
|
+
| 7 | — | network/5xx | queries auto-retried 3×, task creation is not (follow the `suggestion`: check `tripo balance` before re-running); check `tripo doctor`; region mismatch (ov/cn) is a common cause |
|
|
25
25
|
|
|
26
26
|
## Concurrency pools (default per account; error 2000 when full)
|
|
27
27
|
|
|
@@ -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`.
|