tripo-cli 0.5.0 → 0.5.2
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 +4 -1
- package/dist/commands/completion.js +1 -1
- package/dist/commands/update.js +138 -0
- package/dist/core/client.js +23 -5
- package/dist/core/errors.js +5 -1
- package/dist/core/task-service.js +10 -2
- package/dist/program.js +6 -0
- package/package.json +1 -1
- package/skill/SKILL.md +1 -1
- package/skill/commands/task.md +1 -1
- package/skill/common-errors.md +3 -3
package/README.md
CHANGED
|
@@ -40,6 +40,7 @@ Works with both Tripo regions from the same install — international (`openapi.
|
|
|
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 |
|
|
42
42
|
| `tripo config / doctor` | settings (global + per-directory `.tripo/context.json`) and self-diagnosis |
|
|
43
|
+
| `tripo update [--check]` | upgrade to the latest release (`npm install -g tripo-cli@latest`); every command also hints when a newer version exists |
|
|
43
44
|
| `tripo docs [--topic t]` | print the bundled agent/skill docs (`--topic commands/generate` has the model versions / P series table) |
|
|
44
45
|
| `tripo mcp` | run as an MCP server (Cursor / Claude Desktop) |
|
|
45
46
|
| `tripo completion <shell>` | bash/zsh/fish completion |
|
|
@@ -90,7 +91,7 @@ tripo batch run assets.yaml --concurrency 2
|
|
|
90
91
|
|
|
91
92
|
- `make`/`watch` are blocking: run them, wait for exit, read the single JSON line on stdout. Do not poll yourself.
|
|
92
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.
|
|
93
|
-
- 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.
|
|
94
95
|
- `preview.png` in every output directory is your eyes: look at it, then decide to `tripo redo` or continue the chain.
|
|
95
96
|
- Full behavior rules: `tripo docs --llm`, per-command docs via `tripo docs --topic commands/make`.
|
|
96
97
|
|
|
@@ -103,6 +104,8 @@ tripo batch run assets.yaml --concurrency 2
|
|
|
103
104
|
| `TRIPO_REGION` | `ov` or `cn` — normally unnecessary: `tripo login` probes both regions with your key and stores the right one automatically |
|
|
104
105
|
| `TRIPO_API_BASE_URL` / `TRIPO_PLATFORM_BASE_URL` | endpoint overrides |
|
|
105
106
|
| `TRIPO_HOME` | config/history directory (default `~/.tripo`) |
|
|
107
|
+
| `TRIPO_NO_UPDATE_CHECK` | disable the startup "new version available" hint (also off when `CI` is set, headless, or `--json`) |
|
|
108
|
+
| `TRIPO_NPM_REGISTRY` | npm registry used by `tripo update` and the version check (default `https://registry.npmjs.org`; e.g. a mirror) |
|
|
106
109
|
| `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` | standard proxy variables, honored for all CLI traffic (plain Node fetch ignores them) |
|
|
107
110
|
| `TRIPO_LLM_BASE_URL` / `TRIPO_LLM_API_KEY` / `TRIPO_LLM_MODEL` | optional OpenAI-compatible LLM for `tripo ai` conversation mode |
|
|
108
111
|
|
|
@@ -5,7 +5,7 @@ const COMMANDS = [
|
|
|
5
5
|
'login', 'logout', 'whoami', 'use', 'balance', 'usage', 'topup',
|
|
6
6
|
'make', 'view', 'redo', 'ai',
|
|
7
7
|
'generate', 'model', 'anim', 'mesh', 'task', 'files', 'batch', 'history',
|
|
8
|
-
'config', 'doctor', 'docs', 'completion', 'mcp',
|
|
8
|
+
'config', 'doctor', 'update', 'docs', 'completion', 'mcp',
|
|
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'],
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `tripo update` — self-update via npm, plus the startup "new version
|
|
3
|
+
* available" hint (like Claude Code / Codex CLI).
|
|
4
|
+
*
|
|
5
|
+
* The startup check never blocks a command: it reads a 24h cache at
|
|
6
|
+
* ~/.tripo/update-check.json and only refreshes it in the background when
|
|
7
|
+
* stale. The hint is printed to stderr, TTY-only, and never in --json mode,
|
|
8
|
+
* so agents and pipes are unaffected.
|
|
9
|
+
*/
|
|
10
|
+
import { spawn } from 'node:child_process';
|
|
11
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import pc from 'picocolors';
|
|
14
|
+
import { tripoHome } from '../config/config.js';
|
|
15
|
+
import { CliError, NetworkError } from '../core/errors.js';
|
|
16
|
+
import { emitResult, isJsonMode, log, success } from '../core/output.js';
|
|
17
|
+
import { t } from '../i18n.js';
|
|
18
|
+
import { EXIT } from '../knowledge/error-catalog.js';
|
|
19
|
+
import { cliVersion } from '../version.js';
|
|
20
|
+
const PACKAGE_NAME = 'tripo-cli';
|
|
21
|
+
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
22
|
+
const FETCH_TIMEOUT_MS = 3000;
|
|
23
|
+
function registryUrl() {
|
|
24
|
+
const base = process.env.TRIPO_NPM_REGISTRY || 'https://registry.npmjs.org';
|
|
25
|
+
return `${base.replace(/\/+$/, '')}/${PACKAGE_NAME}/latest`;
|
|
26
|
+
}
|
|
27
|
+
function cachePath() {
|
|
28
|
+
return join(tripoHome(), 'update-check.json');
|
|
29
|
+
}
|
|
30
|
+
function readCache() {
|
|
31
|
+
try {
|
|
32
|
+
const raw = JSON.parse(readFileSync(cachePath(), 'utf8'));
|
|
33
|
+
if (typeof raw.checked_at === 'number' && typeof raw.latest === 'string')
|
|
34
|
+
return raw;
|
|
35
|
+
}
|
|
36
|
+
catch { }
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
function writeCache(latest) {
|
|
40
|
+
try {
|
|
41
|
+
mkdirSync(tripoHome(), { recursive: true, mode: 0o700 });
|
|
42
|
+
writeFileSync(cachePath(), JSON.stringify({ checked_at: Date.now(), latest }) + '\n');
|
|
43
|
+
}
|
|
44
|
+
catch { }
|
|
45
|
+
}
|
|
46
|
+
/** Numeric major.minor.patch comparison; pre-release tags are ignored. */
|
|
47
|
+
export function isNewerVersion(candidate, current) {
|
|
48
|
+
const parse = (v) => v.replace(/^v/, '').split('-')[0].split('.').map((x) => Number(x) || 0);
|
|
49
|
+
const a = parse(candidate);
|
|
50
|
+
const b = parse(current);
|
|
51
|
+
for (let i = 0; i < 3; i++) {
|
|
52
|
+
if ((a[i] ?? 0) !== (b[i] ?? 0))
|
|
53
|
+
return (a[i] ?? 0) > (b[i] ?? 0);
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
/** Ask the npm registry for the latest published version. */
|
|
58
|
+
export async function fetchLatestVersion() {
|
|
59
|
+
const url = registryUrl();
|
|
60
|
+
let response;
|
|
61
|
+
try {
|
|
62
|
+
response = await fetch(url, { headers: { Accept: 'application/json' }, signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
throw new NetworkError(`cannot reach the npm registry (${url}): ${err instanceof Error ? err.message : String(err)}`);
|
|
66
|
+
}
|
|
67
|
+
if (!response.ok)
|
|
68
|
+
throw new NetworkError(`npm registry answered HTTP ${response.status} for ${url}`);
|
|
69
|
+
const body = (await response.json());
|
|
70
|
+
if (typeof body.version !== 'string')
|
|
71
|
+
throw new NetworkError(`unexpected npm registry response for ${url}`);
|
|
72
|
+
writeCache(body.version);
|
|
73
|
+
return body.version;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Startup hook: print a one-line hint when a newer version is known.
|
|
77
|
+
* Cheap on every run (one small file read); refreshes the cache in the
|
|
78
|
+
* background at most once a day. Skipped headless, in --json mode, and when
|
|
79
|
+
* TRIPO_NO_UPDATE_CHECK is set.
|
|
80
|
+
*/
|
|
81
|
+
export function notifyIfOutdated() {
|
|
82
|
+
if (process.env.TRIPO_NO_UPDATE_CHECK || process.env.CI)
|
|
83
|
+
return;
|
|
84
|
+
if (isJsonMode() || !process.stderr.isTTY)
|
|
85
|
+
return;
|
|
86
|
+
const current = cliVersion();
|
|
87
|
+
const cache = readCache();
|
|
88
|
+
if (cache && isNewerVersion(cache.latest, current)) {
|
|
89
|
+
process.stderr.write(pc.yellow(t({
|
|
90
|
+
zh: `! 有新版本 tripo-cli ${cache.latest} 可用(当前 ${current}),运行 tripo update 升级`,
|
|
91
|
+
en: `! a new version of tripo-cli is available: ${cache.latest} (current ${current}) — run "tripo update" to upgrade`,
|
|
92
|
+
})) + '\n');
|
|
93
|
+
}
|
|
94
|
+
if (!cache || Date.now() - cache.checked_at > CHECK_INTERVAL_MS) {
|
|
95
|
+
// Fire-and-forget; the result shows up on the next run.
|
|
96
|
+
fetchLatestVersion().catch(() => { });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function runNpmInstall() {
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
const child = spawn('npm', ['install', '-g', `${PACKAGE_NAME}@latest`], {
|
|
102
|
+
stdio: 'inherit',
|
|
103
|
+
shell: process.platform === 'win32',
|
|
104
|
+
});
|
|
105
|
+
child.on('error', (err) => reject(new CliError(`failed to run npm: ${err.message}`, EXIT.FATAL)));
|
|
106
|
+
child.on('exit', (code) => {
|
|
107
|
+
if (code === 0)
|
|
108
|
+
resolve();
|
|
109
|
+
else
|
|
110
|
+
reject(new CliError(`npm install exited with code ${code}`, EXIT.FATAL, t({ zh: `手动执行: npm install -g ${PACKAGE_NAME}@latest`, en: `run manually: npm install -g ${PACKAGE_NAME}@latest` })));
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
export function registerUpdateCommand(program) {
|
|
115
|
+
program
|
|
116
|
+
.command('update')
|
|
117
|
+
.description('update tripo-cli to the latest version (npm install -g tripo-cli@latest)')
|
|
118
|
+
.option('--check', 'only check for a newer version; do not install')
|
|
119
|
+
.action(async (opts) => {
|
|
120
|
+
const current = cliVersion();
|
|
121
|
+
const latest = await fetchLatestVersion();
|
|
122
|
+
const available = isNewerVersion(latest, current);
|
|
123
|
+
if (!available) {
|
|
124
|
+
success(t({ zh: `已是最新版本 ${current}`, en: `already up to date (${current})` }));
|
|
125
|
+
emitResult({ current, latest, update_available: false, updated: false }, current);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (opts.check) {
|
|
129
|
+
log(t({ zh: `有新版本 ${latest} 可用(当前 ${current}),运行 tripo update 升级`, en: `new version ${latest} available (current ${current}); run "tripo update" to upgrade` }));
|
|
130
|
+
emitResult({ current, latest, update_available: true, updated: false }, `${current} → ${latest}`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
log(t({ zh: `正在升级 ${current} → ${latest}…`, en: `updating ${current} → ${latest}…` }));
|
|
134
|
+
await runNpmInstall();
|
|
135
|
+
success(t({ zh: `已升级到 tripo-cli ${latest}`, en: `updated to tripo-cli ${latest}` }));
|
|
136
|
+
emitResult({ current, latest, update_available: true, updated: true }, `${current} → ${latest}`);
|
|
137
|
+
});
|
|
138
|
+
}
|
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/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/program.js
CHANGED
|
@@ -16,6 +16,7 @@ import { registerMcpCommand } from './commands/mcp.js';
|
|
|
16
16
|
import { registerProcessCommands } from './commands/process-groups.js';
|
|
17
17
|
import { registerTaskCommands } from './commands/task.js';
|
|
18
18
|
import { registerTopupCommand } from './commands/topup.js';
|
|
19
|
+
import { notifyIfOutdated, registerUpdateCommand } from './commands/update.js';
|
|
19
20
|
import { registerViewCommands } from './commands/view.js';
|
|
20
21
|
import { loadConfig } from './config/config.js';
|
|
21
22
|
import { RefError } from './config/history.js';
|
|
@@ -55,6 +56,10 @@ export function buildProgram() {
|
|
|
55
56
|
const lang = loadConfig().language;
|
|
56
57
|
if (lang)
|
|
57
58
|
setLocale(lang);
|
|
59
|
+
// Startup version hint (cached, non-blocking). `update` reports on its
|
|
60
|
+
// own; `mcp` speaks JSON-RPC over stdio and must stay silent.
|
|
61
|
+
if (actionCommand.name() !== 'update' && actionCommand.name() !== 'mcp')
|
|
62
|
+
notifyIfOutdated();
|
|
58
63
|
});
|
|
59
64
|
registerMakeCommand(program);
|
|
60
65
|
registerAiCommand(program);
|
|
@@ -68,6 +73,7 @@ export function buildProgram() {
|
|
|
68
73
|
registerBatchCommand(program);
|
|
69
74
|
registerConfigCommands(program);
|
|
70
75
|
registerDoctorCommand(program);
|
|
76
|
+
registerUpdateCommand(program);
|
|
71
77
|
registerDocsCommand(program);
|
|
72
78
|
registerCompletionCommand(program);
|
|
73
79
|
registerMcpCommand(program);
|
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").
|
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
|
@@ -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
|
|