@call-me-sensei/toonlab 0.4.19 → 0.4.21
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/NPM-LIBRARY.md +230 -0
- package/README.md +78 -36
- package/agents/PROMPTS.md +91 -0
- package/agents/README.md +9 -14
- package/agents/claude/CLAUDE.md +8 -0
- package/agents/codex/AGENTS.md +161 -0
- package/agents/cursor/toonlab.mdc +37 -0
- package/agents/references/mcp-asset-discovery.md +12 -9
- package/agents/references/runtime-entry-points.md +5 -4
- package/agents/skills/claude/asset-sourcing/SKILL.md +9 -6
- package/agents/skills/claude/rock-ground-shaders/SKILL.md +16 -0
- package/agents/skills/claude/vegetation-sky/SKILL.md +7 -4
- package/agents/skills/codex/asset-sourcing/SKILL.md +9 -6
- package/agents/skills/codex/rock-ground-shaders/SKILL.md +16 -0
- package/agents/skills/codex/vegetation-sky/SKILL.md +7 -4
- package/cli/toonlab.mjs +3 -2
- package/database/fal-patina.mjs +131 -0
- package/database/generation-service.mjs +108 -7
- package/database/migrations/0007_creation_revisions.sql +80 -0
- package/database/migrations/0008_creation_revision_hardening.sql +98 -0
- package/database/migrations/0009_creation_revision_delete_integrity.sql +11 -0
- package/database/migrations/0010_external_catalog_assets.sql +28 -0
- package/database/providers.mjs +195 -16
- package/database/repository.mjs +518 -70
- package/database/seeds/catalog/0003_2026-08-open-assets.sql +159086 -0
- package/database/seeds/catalog/0004_2026-08-c7-rocks.sql +39405 -0
- package/mcp/public-catalog.mjs +4 -52
- package/mcp/server.mjs +175 -12
- package/mcp/vite-plugin.mjs +78 -2
- package/package.json +32 -12
- package/scripts/generate-catalog-seed.mjs +34 -7
- package/src/asset-policy/catalogLicenses.js +64 -6
- package/src/assetlib/loadImported.js +15 -1
- package/src/catalog/officialCatalogAssetRuntime.js +13 -2
- package/src/catalog/officialCatalogLod.js +34 -1
- package/src/catalog/officialCatalogPlacement.js +29 -14
- package/src/character/animationRetarget.js +2 -0
- package/src/character/characterRig.js +6 -1
- package/src/character/characterRuntime.js +175 -7
- package/src/environment/environmentMaterialAdapter.js +30 -0
- package/src/environment/environmentPresets.js +90 -0
- package/src/environment/environmentSunShadowPass.js +42 -0
- package/src/environment/toonLabSurfaceLighting.js +108 -10
- package/src/environment/urbanPropMaterial.js +104 -2
- package/src/lighting/lightingSystem.js +65 -10
- package/src/renderer/index.js +7 -0
- package/src/renderer/styleComparison.js +985 -0
- package/src/rock-shader/index.js +5 -0
- package/src/rock-shader/rockGeometryDetail.js +701 -0
- package/src/rock-shader/rockMaterial.js +782 -39
- package/src/rock-shader/rockRegionRuntime.js +185 -0
- package/src/rock-shader/rockSemanticMaterialRuntime.js +337 -0
- package/src/rock-shader/rockShaderRuntime.js +354 -67
- package/src/rock-shader/rockShaderSettings.js +246 -16
- package/src/rock-shader/rockTangentIntegrity.js +136 -0
- package/src/rock-shader/rockTextureIntegrity.js +115 -0
- package/src/rockgen/index.js +1 -0
- package/src/rockgen/rockDocument.js +27 -3
- package/src/rockgen/surface/c7GeologySurface.js +372 -0
- package/src/shaders-tsl/water.js +8 -0
- package/src/sky/cloudShadow.js +25 -1
- package/src/sky/skySystem.js +9 -0
- package/src/styles/index.js +23 -0
- package/src/styles/neutralStylePresets.js +712 -0
- package/src/styles/sceneStyleRuntime.js +51 -4
- package/src/styles/styleAdapters.js +13 -2
- package/src/styles/styleBundle.js +1 -1
- package/src/texgen/evaluateTexture.js +30 -3
- package/src/texgen/textureGenerators.js +63 -31
- package/src/texgen/textureSettings.js +25 -8
- package/src/toon/toonSettings.js +96 -2
- package/src/vegetation/branchTree.js +327 -42
- package/src/vegetation/index.js +24 -2
- package/src/vegetation/scatter.js +372 -1
- package/src/vegetation/stylizedTree.js +312 -126
- package/src/vegetation/stylizedTreeFoliage.js +229 -7
- package/src/vegetation/treeSurfaceTextures.js +328 -0
- package/src/version.js +1 -1
- package/src/water/waterSettings.js +15 -7
- package/types/asset-policy/catalogLicenses.d.ts +2 -0
- package/types/asset-policy/index.d.ts +2 -0
- package/types/assetlib/loadImported.d.ts +3 -1
- package/types/catalog/officialCatalogLod.d.ts +63 -5
- package/types/character/characterRig.d.ts +59 -0
- package/types/character/characterRuntime.d.ts +1 -0
- package/types/environment/environmentMaterialAdapter.d.ts +3 -1
- package/types/environment/toonLabSurfaceLighting.d.ts +20 -3
- package/types/index.d.ts +89 -7
- package/types/lighting/lightingSystem.d.ts +7 -0
- package/types/react/index.d.ts +20 -0
- package/types/renderer/index.d.ts +1 -0
- package/types/renderer/styleComparison.d.ts +409 -0
- package/types/rock-shader/index.d.ts +5 -0
- package/types/rock-shader/rockGeometryDetail.d.ts +300 -0
- package/types/rock-shader/rockMaterial.d.ts +3 -0
- package/types/rock-shader/rockRegionRuntime.d.ts +86 -0
- package/types/rock-shader/rockSemanticMaterialRuntime.d.ts +29 -0
- package/types/rock-shader/rockShaderRuntime.d.ts +2 -0
- package/types/rock-shader/rockShaderSettings.d.ts +19 -5
- package/types/rock-shader/rockTangentIntegrity.d.ts +51 -0
- package/types/rock-shader/rockTextureIntegrity.d.ts +61 -0
- package/types/rockgen/index.d.ts +1 -0
- package/types/rockgen/rockDocument.d.ts +29 -1
- package/types/rockgen/surface/c7GeologySurface.d.ts +8 -0
- package/types/sky/cloudShadow.d.ts +1 -0
- package/types/styles/index.d.ts +1 -0
- package/types/styles/neutralStylePresets.d.ts +944 -0
- package/types/styles/sceneStyleRuntime.d.ts +20 -0
- package/types/vegetation/branchTree.d.ts +4 -0
- package/types/vegetation/index.d.ts +9 -7
- package/types/vegetation/scatter.d.ts +1 -0
- package/types/vegetation/stylizedTree.d.ts +1 -2
- package/types/vegetation/stylizedTreeFoliage.d.ts +1 -0
- package/types/version.d.ts +1 -1
- package/agents/references/geology-playbook.md +0 -118
- package/agents/skills/claude/karst-cliff-construction/SKILL.md +0 -258
- package/agents/skills/claude/outdoor-world/SKILL.md +0 -492
- package/agents/skills/claude/outdoor-world/references/coastal-landform-formation.md +0 -100
- package/agents/skills/codex/karst-cliff-construction/SKILL.md +0 -258
- package/agents/skills/codex/outdoor-world/SKILL.md +0 -492
- package/agents/skills/codex/outdoor-world/references/coastal-landform-formation.md +0 -100
- package/src/vegetation/legacyTreePresets.js +0 -120
- package/types/vegetation/legacyTreePresets.d.ts +0 -22
package/database/providers.mjs
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPatinaInput,
|
|
3
|
+
normalizePatinaResult,
|
|
4
|
+
PATINA_MATERIAL_MODEL,
|
|
5
|
+
} from './fal-patina.mjs';
|
|
6
|
+
|
|
1
7
|
const IMAGE_KINDS = new Set(['image', 'texture_image', 'concept_image']);
|
|
2
8
|
const TRIPO_API_BASE = 'https://api.tripo3d.ai/v2/openapi';
|
|
3
9
|
const TRIPO_MODEL_VERSION = 'v2.5-20250123';
|
|
@@ -52,6 +58,7 @@ const ARK_IMAGE_SIZES = {
|
|
|
52
58
|
function providerKey(provider) {
|
|
53
59
|
const names = {
|
|
54
60
|
ark: ['ARK_API_KEY', 'ARK_API_KEYS'],
|
|
61
|
+
fal: ['FAL_KEY', 'FAL_KEYS'],
|
|
55
62
|
gemini: ['GEMINI_API_KEY', 'GEMINI_API_KEYS'],
|
|
56
63
|
openai: ['OPENAI_API_KEY', 'OPENAI_API_KEYS'],
|
|
57
64
|
tripo: ['TRIPO_API_KEY', 'TRIPO_API_KEYS'],
|
|
@@ -64,12 +71,63 @@ function providerKey(provider) {
|
|
|
64
71
|
throw new Error(`${provider} is not configured in the server environment`);
|
|
65
72
|
}
|
|
66
73
|
|
|
67
|
-
async function
|
|
74
|
+
async function runFalPatina(request, key) {
|
|
75
|
+
if (request.kind !== 'material') throw new Error(`Fal cannot serve generation kind ${request.kind}.`);
|
|
76
|
+
const input = createPatinaInput(request);
|
|
77
|
+
const response = await fetch(`https://fal.run/${PATINA_MATERIAL_MODEL}`, {
|
|
78
|
+
body: JSON.stringify(input),
|
|
79
|
+
headers: {
|
|
80
|
+
authorization: `Key ${key}`,
|
|
81
|
+
'content-type': 'application/json',
|
|
82
|
+
},
|
|
83
|
+
method: 'POST',
|
|
84
|
+
signal: AbortSignal.timeout(15 * 60_000),
|
|
85
|
+
});
|
|
86
|
+
const data = await checkedJson(response, 'Fal Patina');
|
|
87
|
+
return {
|
|
88
|
+
material: normalizePatinaResult(data, input),
|
|
89
|
+
provider: 'fal',
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function boundedProviderText(value, maximumLength = 500) {
|
|
94
|
+
if (value === undefined || value === null) return null;
|
|
95
|
+
return String(value).replace(/[\u0000-\u001f\u007f]/g, ' ').trim().slice(0, maximumLength) || null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function sanitizedTraceId(value) {
|
|
99
|
+
const traceId = boundedProviderText(value, 160);
|
|
100
|
+
if (!traceId) return null;
|
|
101
|
+
return /^[A-Za-z0-9._:/-]+$/.test(traceId) ? traceId : '[redacted-invalid-trace-id]';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function providerErrorMetadata(response, body, context = {}) {
|
|
105
|
+
const providerCode = body?.error?.code ?? body?.code ?? null;
|
|
106
|
+
return {
|
|
107
|
+
providerCode: typeof providerCode === 'number' || typeof providerCode === 'string'
|
|
108
|
+
? providerCode
|
|
109
|
+
: null,
|
|
110
|
+
providerMessage: boundedProviderText(body?.error?.message ?? body?.message),
|
|
111
|
+
providerRequestPhase: boundedProviderText(context.requestPhase, 64),
|
|
112
|
+
providerResponseReceived: true,
|
|
113
|
+
providerStatus: response.status,
|
|
114
|
+
providerSuggestion: boundedProviderText(body?.error?.suggestion ?? body?.suggestion),
|
|
115
|
+
retryAfter: boundedProviderText(response.headers.get('retry-after'), 160),
|
|
116
|
+
traceId: sanitizedTraceId(response.headers.get('x-tripo-trace-id')),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function createProviderResponseError(provider, response, body, context = {}) {
|
|
121
|
+
const metadata = providerErrorMetadata(response, body, context);
|
|
122
|
+
return Object.assign(new Error(`${provider} request failed (${response.status}): ${
|
|
123
|
+
metadata.providerMessage ?? 'unknown provider error'
|
|
124
|
+
}`), metadata);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function checkedJson(response, provider, context = {}) {
|
|
68
128
|
const body = await response.json().catch(() => null);
|
|
69
129
|
if (!response.ok) {
|
|
70
|
-
throw
|
|
71
|
-
body?.error?.message ?? body?.message ?? 'unknown provider error'
|
|
72
|
-
}`), { providerStatus: response.status });
|
|
130
|
+
throw createProviderResponseError(provider, response, body, context);
|
|
73
131
|
}
|
|
74
132
|
return body;
|
|
75
133
|
}
|
|
@@ -258,9 +316,16 @@ async function tripoJson(path, key, init = {}) {
|
|
|
258
316
|
},
|
|
259
317
|
signal: init.signal ?? AbortSignal.timeout(2 * 60_000),
|
|
260
318
|
});
|
|
261
|
-
const
|
|
319
|
+
const requestPhase = path === '/task' && init.method === 'POST'
|
|
320
|
+
? 'task-create'
|
|
321
|
+
: path === '/upload' && init.method === 'POST'
|
|
322
|
+
? 'image-upload'
|
|
323
|
+
: path.startsWith('/task/') && init.method === 'GET'
|
|
324
|
+
? 'task-poll'
|
|
325
|
+
: 'tripo-request';
|
|
326
|
+
const envelope = await checkedJson(response, 'Tripo', { requestPhase });
|
|
262
327
|
if (envelope?.code !== 0 || !envelope?.data) {
|
|
263
|
-
throw
|
|
328
|
+
throw createProviderResponseError('Tripo', response, envelope, { requestPhase });
|
|
264
329
|
}
|
|
265
330
|
return envelope.data;
|
|
266
331
|
}
|
|
@@ -280,15 +345,88 @@ async function uploadTripoImage(reference, key) {
|
|
|
280
345
|
};
|
|
281
346
|
}
|
|
282
347
|
|
|
348
|
+
function tripoModelVersion(request) {
|
|
349
|
+
const modelVersion = request.modelVersion ?? TRIPO_MODEL_VERSION;
|
|
350
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(modelVersion)) {
|
|
351
|
+
throw new RangeError('Tripo modelVersion must be a provider snapshot identifier.');
|
|
352
|
+
}
|
|
353
|
+
return modelVersion;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function tripoGenerationOptions(request, modelVersion) {
|
|
357
|
+
const options = {};
|
|
358
|
+
if (request.faceLimit !== undefined) {
|
|
359
|
+
const geometryQuality = request.geometryQuality ?? 'standard';
|
|
360
|
+
const maximumByModel = {
|
|
361
|
+
'P1-20260311': 20_000,
|
|
362
|
+
'v2.5-20250123': 500_000,
|
|
363
|
+
'v3.0-20250812': geometryQuality === 'detailed' ? 2_000_000 : 1_500_000,
|
|
364
|
+
'v3.1-20260211': geometryQuality === 'detailed' ? 2_000_000 : 1_500_000,
|
|
365
|
+
};
|
|
366
|
+
const maximum = maximumByModel[modelVersion];
|
|
367
|
+
if (maximum === undefined) {
|
|
368
|
+
throw new RangeError(`Explicit Tripo faceLimit is not verified for model ${modelVersion}.`);
|
|
369
|
+
}
|
|
370
|
+
if (!Number.isInteger(request.faceLimit) || request.faceLimit < 48 || request.faceLimit > maximum) {
|
|
371
|
+
throw new RangeError(`Tripo ${modelVersion} faceLimit must be an integer from 48 through ${maximum}.`);
|
|
372
|
+
}
|
|
373
|
+
options.face_limit = request.faceLimit;
|
|
374
|
+
}
|
|
375
|
+
if (request.modelSeed !== undefined) {
|
|
376
|
+
if (!Number.isSafeInteger(request.modelSeed)) throw new RangeError('Tripo modelSeed must be a safe integer.');
|
|
377
|
+
options.model_seed = request.modelSeed;
|
|
378
|
+
}
|
|
379
|
+
if (request.textureSeed !== undefined) {
|
|
380
|
+
if (!Number.isSafeInteger(request.textureSeed)) throw new RangeError('Tripo textureSeed must be a safe integer.');
|
|
381
|
+
options.texture_seed = request.textureSeed;
|
|
382
|
+
}
|
|
383
|
+
for (const [requestKey, payloadKey] of [
|
|
384
|
+
['texture', 'texture'],
|
|
385
|
+
['pbr', 'pbr'],
|
|
386
|
+
['exportUv', 'export_uv'],
|
|
387
|
+
]) {
|
|
388
|
+
if (request[requestKey] !== undefined) {
|
|
389
|
+
if (typeof request[requestKey] !== 'boolean') {
|
|
390
|
+
throw new TypeError(`Tripo ${requestKey} must be boolean.`);
|
|
391
|
+
}
|
|
392
|
+
options[payloadKey] = request[requestKey];
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (request.textureQuality !== undefined) {
|
|
396
|
+
if (!['standard', 'detailed', 'extreme'].includes(request.textureQuality)) {
|
|
397
|
+
throw new RangeError('Tripo textureQuality must be standard, detailed, or extreme.');
|
|
398
|
+
}
|
|
399
|
+
options.texture_quality = request.textureQuality;
|
|
400
|
+
}
|
|
401
|
+
if (request.textureAlignment !== undefined) {
|
|
402
|
+
if (!['original_image', 'geometry'].includes(request.textureAlignment)) {
|
|
403
|
+
throw new RangeError('Tripo textureAlignment must be original_image or geometry.');
|
|
404
|
+
}
|
|
405
|
+
options.texture_alignment = request.textureAlignment;
|
|
406
|
+
}
|
|
407
|
+
if (request.geometryQuality !== undefined) {
|
|
408
|
+
if (!['standard', 'detailed'].includes(request.geometryQuality)) {
|
|
409
|
+
throw new RangeError('Tripo geometryQuality must be standard or detailed.');
|
|
410
|
+
}
|
|
411
|
+
if (!['v3.0-20250812', 'v3.1-20260211'].includes(modelVersion)) {
|
|
412
|
+
throw new RangeError('Tripo geometryQuality is supported only for v3.0-20250812 and v3.1-20260211.');
|
|
413
|
+
}
|
|
414
|
+
options.geometry_quality = request.geometryQuality;
|
|
415
|
+
}
|
|
416
|
+
return options;
|
|
417
|
+
}
|
|
418
|
+
|
|
283
419
|
async function runTripo(request, key) {
|
|
284
420
|
let payload;
|
|
421
|
+
const modelVersion = tripoModelVersion(request);
|
|
285
422
|
if (request.kind === 'image_to_model') {
|
|
286
423
|
const reference = request.referenceImages?.[0];
|
|
287
424
|
if (!reference) throw new Error('Image-to-3D requires one reference image');
|
|
288
425
|
payload = {
|
|
289
426
|
type: 'image_to_model',
|
|
290
|
-
model_version:
|
|
427
|
+
model_version: modelVersion,
|
|
291
428
|
file: await uploadTripoImage(reference, key),
|
|
429
|
+
...tripoGenerationOptions(request, modelVersion),
|
|
292
430
|
};
|
|
293
431
|
} else if (request.kind === 'multiview_to_model') {
|
|
294
432
|
const views = request.viewImages ?? [];
|
|
@@ -297,10 +435,11 @@ async function runTripo(request, key) {
|
|
|
297
435
|
}
|
|
298
436
|
payload = {
|
|
299
437
|
type: 'multiview_to_model',
|
|
300
|
-
model_version:
|
|
438
|
+
model_version: modelVersion,
|
|
301
439
|
files: await Promise.all(
|
|
302
440
|
views.slice(0, 4).map((view) => view ? uploadTripoImage(view, key) : {}),
|
|
303
441
|
),
|
|
442
|
+
...tripoGenerationOptions(request, modelVersion),
|
|
304
443
|
};
|
|
305
444
|
} else if (request.kind === 'model_segment') {
|
|
306
445
|
if (!request.originalTaskId) throw new Error('Model segmentation requires the original Tripo task id');
|
|
@@ -312,8 +451,9 @@ async function runTripo(request, key) {
|
|
|
312
451
|
const styleSuffix = TRIPO_STYLES[request.style] ?? TRIPO_STYLES.stylized;
|
|
313
452
|
payload = {
|
|
314
453
|
type: 'text_to_model',
|
|
315
|
-
model_version:
|
|
454
|
+
model_version: modelVersion,
|
|
316
455
|
prompt: `${request.prompt ?? request.user ?? ''}${styleSuffix}`,
|
|
456
|
+
...tripoGenerationOptions(request, modelVersion),
|
|
317
457
|
};
|
|
318
458
|
}
|
|
319
459
|
const data = await tripoJson('/task', key, {
|
|
@@ -322,7 +462,12 @@ async function runTripo(request, key) {
|
|
|
322
462
|
method: 'POST',
|
|
323
463
|
});
|
|
324
464
|
if (!data.task_id) throw new Error('Tripo task creation returned no task id');
|
|
325
|
-
return {
|
|
465
|
+
return {
|
|
466
|
+
modelVersion: request.kind === 'model_segment' ? null : modelVersion,
|
|
467
|
+
pending: true,
|
|
468
|
+
provider: 'tripo',
|
|
469
|
+
taskId: data.task_id,
|
|
470
|
+
};
|
|
326
471
|
}
|
|
327
472
|
|
|
328
473
|
function meshyImageDataUri(reference) {
|
|
@@ -345,17 +490,49 @@ async function meshyJson(path, key, init = {}) {
|
|
|
345
490
|
return checkedJson(response, 'Meshy');
|
|
346
491
|
}
|
|
347
492
|
|
|
493
|
+
function meshyGenerationOptions(request) {
|
|
494
|
+
const textureResolution = request.textureResolution ?? '2k';
|
|
495
|
+
if (!['2k', '4k', '8k'].includes(textureResolution)) {
|
|
496
|
+
throw new RangeError('Meshy textureResolution must be 2k, 4k, or 8k.');
|
|
497
|
+
}
|
|
498
|
+
const options = {
|
|
499
|
+
alpha_thumbnail: request.alphaThumbnail ?? true,
|
|
500
|
+
enable_pbr: request.pbr ?? true,
|
|
501
|
+
image_enhancement: request.imageEnhancement ?? true,
|
|
502
|
+
remove_lighting: request.removeLighting ?? true,
|
|
503
|
+
should_remesh: request.shouldRemesh ?? false,
|
|
504
|
+
should_texture: request.texture ?? true,
|
|
505
|
+
target_formats: ['glb'],
|
|
506
|
+
texture_resolution: textureResolution,
|
|
507
|
+
};
|
|
508
|
+
for (const [requestKey, payloadKey] of [
|
|
509
|
+
['alphaThumbnail', 'alpha_thumbnail'],
|
|
510
|
+
['imageEnhancement', 'image_enhancement'],
|
|
511
|
+
['pbr', 'enable_pbr'],
|
|
512
|
+
['removeLighting', 'remove_lighting'],
|
|
513
|
+
['shouldRemesh', 'should_remesh'],
|
|
514
|
+
['texture', 'should_texture'],
|
|
515
|
+
]) {
|
|
516
|
+
if (request[requestKey] !== undefined && typeof request[requestKey] !== 'boolean') {
|
|
517
|
+
throw new TypeError(`Meshy ${requestKey} must be boolean.`);
|
|
518
|
+
}
|
|
519
|
+
if (request[requestKey] !== undefined) options[payloadKey] = request[requestKey];
|
|
520
|
+
}
|
|
521
|
+
if (request.texturePrompt !== undefined) {
|
|
522
|
+
if (typeof request.texturePrompt !== 'string' || request.texturePrompt.length > 600) {
|
|
523
|
+
throw new RangeError('Meshy texturePrompt must be a string of at most 600 characters.');
|
|
524
|
+
}
|
|
525
|
+
if (request.texturePrompt.trim()) options.texture_prompt = request.texturePrompt.trim();
|
|
526
|
+
}
|
|
527
|
+
return options;
|
|
528
|
+
}
|
|
529
|
+
|
|
348
530
|
async function runMeshy(request, key) {
|
|
349
531
|
let path;
|
|
350
532
|
let payload;
|
|
351
533
|
const shared = {
|
|
352
534
|
ai_model: MESHY_MODEL_VERSION,
|
|
353
|
-
|
|
354
|
-
enable_pbr: true,
|
|
355
|
-
should_remesh: false,
|
|
356
|
-
should_texture: true,
|
|
357
|
-
target_formats: ['glb'],
|
|
358
|
-
texture_resolution: '2k',
|
|
535
|
+
...meshyGenerationOptions(request),
|
|
359
536
|
};
|
|
360
537
|
if (request.kind === 'image_to_model') {
|
|
361
538
|
path = '/v1/image-to-3d';
|
|
@@ -382,6 +559,7 @@ async function runMeshy(request, key) {
|
|
|
382
559
|
});
|
|
383
560
|
if (!data?.result) throw new Error('Meshy task creation returned no task id');
|
|
384
561
|
return {
|
|
562
|
+
modelVersion: MESHY_MODEL_VERSION,
|
|
385
563
|
pending: true,
|
|
386
564
|
provider: 'meshy',
|
|
387
565
|
taskId: data.result,
|
|
@@ -390,6 +568,7 @@ async function runMeshy(request, key) {
|
|
|
390
568
|
|
|
391
569
|
export async function runProvider(provider, request) {
|
|
392
570
|
const key = providerKey(provider);
|
|
571
|
+
if (provider === 'fal') return runFalPatina(request, key);
|
|
393
572
|
if (provider === 'gemini') return runGemini(request, key);
|
|
394
573
|
if (provider === 'openai' || provider === 'ark') {
|
|
395
574
|
return runOpenAiOrArk(provider, request, key);
|