Conversation
Wraps studio.tripo3d.ai's Smart Mesh engine: generate an untextured 3D
mesh from a prompt, one reference image, or front/left/back/right views,
bake a texture onto an existing mesh, and read back tasks, projects and
credits.
Commands: text-to-model, image-to-model, multiview-to-model, texture,
status, assets, credits.
Strategy is PAGE_FETCH for every call. api.tripo3d.ai authenticates with
an HttpOnly cookie and sits behind Cloudflare bot management, so the
requests are issued from the studio's own origin rather than replayed
from Node. Tripo's documented REST API on platform.tripo3d.ai is a
separate product needing its own key, not the studio session these
commands reuse.
Notes on the choices that are easy to get wrong:
* Smart Mesh has two engines. --model p1 (Nexus-v1.0) is 35 credits and
triangles only; --model p2 (Nexus-v2.0) is 100 credits and the only
one that can emit quads. p1 is the default even though the studio's
dropdown now defaults to P2, so no existing command line silently
starts costing 3x.
* --topology quad is rejected on p1 instead of being downgraded to
triangles, because the studio renders that button disabled.
* The polycount ceiling moves with both (p1 20000, p2 triangle 50000,
p2 quad 25000). The page clamps silently; this throws instead, so a
paid generation never runs at a face count nobody asked for.
* P2 carries a `symmetry` field the UI has no control for: the studio
runs operation/symmetry_check on the main reference image and forwards
the verdict. Text mode has no reference image and sends false.
* Privacy is members-only, so --visibility defaults to `auto` and
resolves the way the store does (public on a free plan, shareable for
a subscriber). Anything else on a free plan is refused with HTTP 403
6102 after the image has already been uploaded.
* Only 401 means a lost session (code 1002). A 403 is a business refusal
against a healthy session and is surfaced with its own code, so
"Insufficient membership" is not reported as "please log in".
Exporting to a local file is deliberately left out: operation/export-lite
returns {} and only bumps a counter, while the file is built inside the
page and handed to the browser as a Blob, so a download command has to
drive the studio's Export dialog. That surface is still drifting, so it
is a follow-up rather than something shipped half-working.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EPFwuPThapaSgr1QFBtXsQ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A browser adapter for Tripo Studio (
studio.tripo3d.ai), wrapping its Smart Mesh engine — text / image / multi-view to 3D mesh, texture baking, and the read commands needed to drive them.text-to-model <prompt>image-to-model <image>multiview-to-model <front>texture <project>status <operators>assetscreditsStrategy
PAGE_FETCHfor every call.api.tripo3d.aiauthenticates with an HttpOnly cookie on.tripo3d.ai— the captured requests carry no bearer token and no CSRF header — and sits behind Cloudflare bot management (__cf_bm), which binds to the browser's TLS/UA fingerprint. Replaying the calls from Node risks intermittent 403s, so they are issued from the studio's own origin.Tripo does publish a documented REST API on
platform.tripo3d.ai, but it needs a separate API key rather than the studio session these commands reuse, so it is not an alternative here.Design decisions worth reviewing
Two engines, and the cheaper one stays the default. Smart Mesh's AI Model dropdown offers
Nexus-v1.0(P1, 35 credits, triangles only) andNexus-v2.0(P2, 100 credits, quad-capable). The studio itself now defaults to P2; the adapter defaults to--model p1on purpose, so an existing command line does not silently start costing 3x.--model p2opts in.Errors instead of silent coercion, in three places where the page does the opposite:
--topology quadon P1 is rejected, not downgraded to triangles — the studio renders the Quad button disabled on that engine.Math.round(Math.min(value, ceiling)); the adapter throws, because a clamp the caller cannot see is a 100-credit generation at a face count nobody asked for.403is no longer reported as a lost session. Measured against the live studio: signed out is HTTP 401 + code 1002, while a plan refusal is HTTP 403 with a real business code (6102 Insufficient membership,9103 Project count limit exceeded). Only 401 raisesAuthRequiredErrornow.symmetryis P2-only and has no UI control. The page attaches it only once the dropdown is on P2, filling it fromoperation/symmetry_checkrun against the main reference image. The adapter mirrors that exactly: text mode has no reference image and sends a literalfalse, image mode checks the uploaded image, multi-view checks the front slot.--visibilitydefaults toauto. Privacy now sits under a "Members Only" heading; on a free plan the combobox opens the pricing dialog rather than a dropdown, and the API answers anything butpublicwith 4036102— after the reference image has already been uploaded.autoresolves the way the store does (payment.member.type !== 'basic'→shareable, elsepublic); explicit values pass straight through.Testing
clis/tripo3d/tripo3d.test.js— 22 tests covering the polycount matrix, the quad/P1 rejection, the 401-vs-403 split, symmetry forwarding, visibility resolution, and the exact request bodyrunSmartMeshbuilds for each engine. Each guard was reverse-validated by injecting the corresponding regression and confirming it fails.npm testwas also run in full; the 11 failing files it reports are pre-existing on this Windows checkout (path/home-expansion assertions insuno,twitter,instagram,xiaoyuzhou,src/cli.test.ts) and fail identically with this branch stashed.Verified live against a real account (
opencli browser verifygreen forassets,credits,status; an end-to-endimage-to-model --model p2 --topology quad --polycount 22000came backsuccess, andproject/detail/v3echoed the stored operator as{"quad":true,"face_limit":22000,"model_version":"Nexus-v2.0-20260801","symmetry":false}).Deliberately not included
A
downloadcommand. File export is not a server-side endpoint here:operation/export-litereturns{}and only bumps the account's monthly export counter, while the FBX/OBJ/STL is produced inside the page and handed to the browser as a Blob — so it has to drive the studio's Export dialog. That surface drifted three times in 24 hours while this was being prepared (the project deep link rendering the SPA's error boundary, the viewer switching from.glbtooutput_mesh_<operator_id>.fbx, and the Export dialog not opening in a background window), so it is left as a follow-up rather than shipped half-working.operation/download_with_nameremains the cheap path for the stored native asset when no format conversion is needed.🤖 Generated with Claude Code
https://claude.ai/code/session_01EPFwuPThapaSgr1QFBtXsQ