切换 Tiantoken 并删除旧 Vidu 音效
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 5m31s
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 5m31s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 5m47s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 5m48s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m43s
Project CI / AI game creator shell Rust crates (push) Successful in 2m3s
Project CI / Repository checks (push) Successful in 3m43s
Project CI / Frontend tests (push) Successful in 4m53s
Project CI / Native shell tests (push) Successful in 6m35s
Project CI / Backend tests (push) Successful in 7m25s
Project CI / AI game creator shell web tests (push) Successful in 2m35s

新增 TIANTOKEN_BASE_URL / TIANTOKEN_API_KEY 配置并切换文本与图片链路

保留 Suno VectorEngine 路径,删除旧 Vidu submit/poll/builder 实现

同步脚本、文档、测试与运行时 provider 路由
This commit is contained in:
2026-09-15 19:43:35 +08:00
parent 687bad0adf
commit 29e84a77d1
32 changed files with 217 additions and 843 deletions
+3 -3
View File
@@ -24,7 +24,7 @@ describe('bgfilter worker smoke harness', () => {
GENARRATIVE_BGFILTER_INTERNAL_TOKEN: 'real-internal-token',
GENARRATIVE_EDITOR_BGFILTER_TOKEN: 'real-provider-token',
PATH: '/safe/bin',
VECTOR_ENGINE_API_KEY: 'real-vector-secret',
TIANTOKEN_API_KEY: 'real-tiantoken-secret',
},
providerBaseUrl: 'http://127.0.0.1:19001',
tempRoot: '/tmp/bgfilter-load-smoke-test',
@@ -40,10 +40,10 @@ describe('bgfilter worker smoke harness', () => {
assert.equal(env.ALIYUN_OSS_ENDPOINT, 'oss-cn-shanghai.invalid');
assert.notEqual(env.ALIYUN_OSS_ACCESS_KEY_SECRET, 'real-oss-secret');
assert.equal(env.GENARRATIVE_EDITOR_BGFILTER_TOKEN, undefined);
assert.equal(env.VECTOR_ENGINE_API_KEY, undefined);
assert.equal(env.TIANTOKEN_API_KEY, undefined);
assert.ok(!Object.values(env).includes('real-internal-token'));
assert.ok(!Object.values(env).includes('real-provider-token'));
assert.ok(!Object.values(env).includes('real-vector-secret'));
assert.ok(!Object.values(env).includes('real-tiantoken-secret'));
});
test('loopback mock 完整读取 multipart 后记录并发并返回合法 PNG 字节', async () => {
+2 -2
View File
@@ -1,8 +1,8 @@
import { mergeApiServerEnv } from './dev-utils.mjs';
const REQUIRED_FOR_PUZZLE_GENERATION = [
'VECTOR_ENGINE_BASE_URL',
'VECTOR_ENGINE_API_KEY',
'TIANTOKEN_BASE_URL',
'TIANTOKEN_API_KEY',
'ALIYUN_OSS_BUCKET',
'ALIYUN_OSS_ENDPOINT',
'ALIYUN_OSS_ACCESS_KEY_ID',
+3 -3
View File
@@ -514,11 +514,11 @@ GENARRATIVE_SPACETIME_POOL_SIZE=2
GENARRATIVE_SPACETIME_PROCEDURE_TIMEOUT_SECONDS=15
GENARRATIVE_LLM_PROVIDER=openai-compatible
GENARRATIVE_LLM_BASE_URL=https://api.vectorengine.cn/v1
GENARRATIVE_LLM_BASE_URL=https://api.tiantoken.com/v1
GENARRATIVE_LLM_API_KEY=
GENARRATIVE_LLM_MODEL=gpt-5.4-mini
VECTOR_ENGINE_BASE_URL=
VECTOR_ENGINE_API_KEY=
TIANTOKEN_BASE_URL=
TIANTOKEN_API_KEY=
ALIYUN_OSS_BUCKET=
ALIYUN_OSS_ENDPOINT=oss-cn-shanghai.aliyuncs.com
ALIYUN_OSS_ACCESS_KEY_ID=
+8 -8
View File
@@ -52,12 +52,12 @@ function timestamp() {
function resolveEnv() {
const env = mergeApiServerEnv(repoRoot, process.env);
return {
baseUrl: String(env.VECTOR_ENGINE_BASE_URL || '')
baseUrl: String(env.TIANTOKEN_BASE_URL || '')
.trim()
.replace(/\/+$/u, ''),
apiKey: String(env.VECTOR_ENGINE_API_KEY || '').trim(),
apiKey: String(env.TIANTOKEN_API_KEY || '').trim(),
timeoutMs: Number.parseInt(
String(env.VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS || defaultTimeoutMs),
String(env.TIANTOKEN_IMAGE_REQUEST_TIMEOUT_MS || defaultTimeoutMs),
10,
),
};
@@ -160,12 +160,12 @@ async function fetchJson(url, options, timeoutMs) {
});
const text = await response.text();
if (!response.ok) {
throw new Error(`VectorEngine ${response.status}: ${text.slice(0, 600)}`);
throw new Error(`Tiantoken ${response.status}: ${text.slice(0, 600)}`);
}
return JSON.parse(text);
} catch (error) {
if (error?.name === 'AbortError') {
throw new Error(`VectorEngine request timed out after ${timeoutMs}ms`);
throw new Error(`Tiantoken request timed out after ${timeoutMs}ms`);
}
throw error;
} finally {
@@ -202,7 +202,7 @@ async function imageBytesFromPayload(payload, env) {
if (b64Images[0]) {
return Buffer.from(b64Images[0], 'base64');
}
throw new Error('VectorEngine returned no image');
throw new Error('Tiantoken returned no image');
}
async function generateImage(env, { prompt, negativePrompt, size, outPath }) {
@@ -320,7 +320,7 @@ async function main() {
{
mode: 'dry-run',
outDir,
message: '加 --live 才会真实调用 VectorEngine。',
message: '加 --live 才会真实调用 Tiantoken。',
prompts,
},
null,
@@ -332,7 +332,7 @@ async function main() {
const env = resolveEnv();
if (!env.baseUrl || !env.apiKey) {
throw new Error('Missing VECTOR_ENGINE_BASE_URL or VECTOR_ENGINE_API_KEY');
throw new Error('Missing TIANTOKEN_BASE_URL or TIANTOKEN_API_KEY');
}
console.log(`[match3d-export] 1/4 生成关卡整图 -> ${outDir}`);
@@ -127,12 +127,12 @@ function resolveEnv() {
...process.env,
};
return {
baseUrl: String(loaded.VECTOR_ENGINE_BASE_URL || '')
baseUrl: String(loaded.TIANTOKEN_BASE_URL || '')
.trim()
.replace(/\/+$/u, ''),
apiKey: String(loaded.VECTOR_ENGINE_API_KEY || '').trim(),
apiKey: String(loaded.TIANTOKEN_API_KEY || '').trim(),
timeoutMs: Number.parseInt(
String(loaded.VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS || defaultTimeoutMs),
String(loaded.TIANTOKEN_IMAGE_REQUEST_TIMEOUT_MS || defaultTimeoutMs),
10,
),
};
@@ -249,12 +249,12 @@ async function fetchJson(url, options, timeoutMs) {
});
const text = await response.text();
if (!response.ok) {
throw new Error(`VectorEngine ${response.status}: ${text.slice(0, 600)}`);
throw new Error(`Tiantoken ${response.status}: ${text.slice(0, 600)}`);
}
return JSON.parse(text);
} catch (error) {
if (error?.name === 'AbortError') {
throw new Error(`VectorEngine request timed out after ${timeoutMs}ms`);
throw new Error(`Tiantoken request timed out after ${timeoutMs}ms`);
}
throw error;
} finally {
@@ -335,7 +335,7 @@ async function generateOne(env, concept, size, references) {
extension: inferExtensionFromBytes(bytes),
};
} else {
throw new Error(`VectorEngine returned no image for ${concept.id}`);
throw new Error(`Tiantoken returned no image for ${concept.id}`);
}
mkdirSync(outDir, { recursive: true });
@@ -401,7 +401,7 @@ if (!env.baseUrl || !env.apiKey) {
console.error(
JSON.stringify({
ok: false,
error: 'Missing VECTOR_ENGINE_BASE_URL or VECTOR_ENGINE_API_KEY',
error: 'Missing TIANTOKEN_BASE_URL or TIANTOKEN_API_KEY',
hasBaseUrl: Boolean(env.baseUrl),
hasApiKey: Boolean(env.apiKey),
}),
@@ -107,12 +107,12 @@ function resolveEnv() {
...process.env,
};
return {
baseUrl: String(loaded.VECTOR_ENGINE_BASE_URL || '')
baseUrl: String(loaded.TIANTOKEN_BASE_URL || '')
.trim()
.replace(/\/+$/u, ''),
apiKey: String(loaded.VECTOR_ENGINE_API_KEY || '').trim(),
apiKey: String(loaded.TIANTOKEN_API_KEY || '').trim(),
timeoutMs: Number.parseInt(
String(loaded.VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS || defaultTimeoutMs),
String(loaded.TIANTOKEN_IMAGE_REQUEST_TIMEOUT_MS || defaultTimeoutMs),
10,
),
};
@@ -226,12 +226,12 @@ async function fetchJson(url, options, timeoutMs) {
});
const text = await response.text();
if (!response.ok) {
throw new Error(`VectorEngine ${response.status}: ${text.slice(0, 600)}`);
throw new Error(`Tiantoken ${response.status}: ${text.slice(0, 600)}`);
}
return JSON.parse(text);
} catch (error) {
if (error?.name === 'AbortError') {
throw new Error(`VectorEngine request timed out after ${timeoutMs}ms`);
throw new Error(`Tiantoken request timed out after ${timeoutMs}ms`);
}
throw error;
} finally {
@@ -314,7 +314,7 @@ async function generateOne(env, concept, size) {
extension: inferExtensionFromBytes(bytes),
};
} else {
throw new Error(`VectorEngine returned no image for ${concept.id}`);
throw new Error(`Tiantoken returned no image for ${concept.id}`);
}
mkdirSync(outDir, { recursive: true });
@@ -375,7 +375,7 @@ if (!env.baseUrl || !env.apiKey) {
console.error(
JSON.stringify({
ok: false,
error: 'Missing VECTOR_ENGINE_BASE_URL or VECTOR_ENGINE_API_KEY',
error: 'Missing TIANTOKEN_BASE_URL or TIANTOKEN_API_KEY',
hasBaseUrl: Boolean(env.baseUrl),
hasApiKey: Boolean(env.apiKey),
}),
@@ -87,12 +87,12 @@ function resolveEnv() {
...process.env,
};
return {
baseUrl: String(loaded.VECTOR_ENGINE_BASE_URL || '')
baseUrl: String(loaded.TIANTOKEN_BASE_URL || '')
.trim()
.replace(/\/+$/u, ''),
apiKey: String(loaded.VECTOR_ENGINE_API_KEY || '').trim(),
apiKey: String(loaded.TIANTOKEN_API_KEY || '').trim(),
timeoutMs: Number.parseInt(
String(loaded.VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS || timeoutMsDefault),
String(loaded.TIANTOKEN_IMAGE_REQUEST_TIMEOUT_MS || timeoutMsDefault),
10,
),
};
@@ -180,12 +180,12 @@ async function fetchJson(url, options, timeoutMs) {
});
const text = await response.text();
if (!response.ok) {
throw new Error(`VectorEngine ${response.status}: ${text.slice(0, 600)}`);
throw new Error(`Tiantoken ${response.status}: ${text.slice(0, 600)}`);
}
return JSON.parse(text);
} catch (error) {
if (error?.name === 'AbortError') {
throw new Error(`VectorEngine request timed out after ${timeoutMs}ms`);
throw new Error(`Tiantoken request timed out after ${timeoutMs}ms`);
}
throw error;
} finally {
@@ -235,7 +235,7 @@ async function generateChromaSource() {
throw new Error(
JSON.stringify({
ok: false,
error: 'Missing VECTOR_ENGINE_BASE_URL or VECTOR_ENGINE_API_KEY',
error: 'Missing TIANTOKEN_BASE_URL or TIANTOKEN_API_KEY',
hasBaseUrl: Boolean(env.baseUrl),
hasApiKey: Boolean(env.apiKey),
}),
@@ -263,7 +263,7 @@ async function generateChromaSource() {
} else if (b64Images[0]) {
bytes = Buffer.from(b64Images[0], 'base64');
} else {
throw new Error('VectorEngine returned no image');
throw new Error('Tiantoken returned no image');
}
mkdirSync(outputDir, { recursive: true });
+7 -8
View File
@@ -28,12 +28,11 @@ function loadEnv(path) {
const env = loadEnv(resolve(root, '.env.secrets.local'));
const BASE =
env.VECTOR_ENGINE_BASE_URL?.replace(/\/+$/, '') ||
'https://api.vectorengine.cn';
const KEY = env.VECTOR_ENGINE_API_KEY || '';
env.TIANTOKEN_BASE_URL?.replace(/\/+$/, '') || 'https://api.tiantoken.com';
const KEY = env.TIANTOKEN_API_KEY || '';
if (!KEY) {
console.error('未找到 VECTOR_ENGINE_API_KEY');
console.error('未找到 TIANTOKEN_API_KEY');
process.exit(1);
}
@@ -90,7 +89,7 @@ async function test(name, method, path, body = null) {
}
}
console.log(`VectorEngine LLM 能力探测`);
console.log(`Tiantoken LLM 能力探测`);
console.log(`目标: ${BASE}\n`);
const tests = [
@@ -185,12 +184,12 @@ console.log(
// 结论
if (pass >= 3) {
console.log('\n✅ VectorEngine 支持 LLM 文本调用,可替代 Apimart。');
console.log('\n✅ Tiantoken 支持 LLM 文本调用,可替代 Apimart。');
console.log(
' 将 .env.secrets.local 中 VECTOR_ENGINE_BASE_URL / VECTOR_ENGINE_API_KEY 配好即可。',
' 将 .env.secrets.local 中 TIANTOKEN_BASE_URL / TIANTOKEN_API_KEY 配好即可。',
);
} else if (pass <= 1) {
console.log('\n❌ VectorEngine 不支持 LLM 文本调用。');
console.log('\n❌ Tiantoken 不支持 LLM 文本调用。');
} else {
console.log('\n⚠️ 部分支持,需进一步评估。');
}