| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- 'use strict';
- const assert = require('assert/strict');
- const fs = require('fs');
- const os = require('os');
- const path = require('path');
- const {
- VoiceCloneService,
- } = require('../mcp/src/core/voice-clone-service');
- const {
- readFmodeVoiceToken,
- readFmodeVoiceTokenStatus,
- saveFmodeVoiceToken,
- } = require('../mcp/src/core/credentials');
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'qiwei-voice-token-smoke-'));
- const envSnapshot = {
- QIWEI_WORKSPACE_ROOT: process.env.QIWEI_WORKSPACE_ROOT,
- QIWEI_PACKAGE_ROOT: process.env.QIWEI_PACKAGE_ROOT,
- QIWEI_VOICE_AUTH_TOKEN: process.env.QIWEI_VOICE_AUTH_TOKEN,
- };
- function restoreEnv() {
- for (const [key, value] of Object.entries(envSnapshot)) {
- if (value === undefined) delete process.env[key];
- else process.env[key] = value;
- }
- fs.rmSync(root, { recursive: true, force: true });
- }
- async function main() {
- const validToken = 'sk-test-voice-token-0123456789';
- const sessionToken = 'r:test-session-token';
- const envPath = path.join(root, '.env.local');
- fs.writeFileSync(envPath, 'KEEP_ME=preserved\n# existing setting\n', 'utf8');
- process.env.QIWEI_WORKSPACE_ROOT = root;
- delete process.env.QIWEI_PACKAGE_ROOT;
- delete process.env.QIWEI_VOICE_AUTH_TOKEN;
- const saved = saveFmodeVoiceToken({ token: validToken, envRoot: root });
- assert.equal(saved.configured, true);
- assert.equal(saved.path, envPath);
- const persisted = fs.readFileSync(envPath, 'utf8');
- assert.match(persisted, /^KEEP_ME=preserved$/m);
- assert.match(persisted, /^QIWEI_VOICE_AUTH_TOKEN=sk-/m);
- assert.doesNotMatch(JSON.stringify(saved), new RegExp(validToken));
- const status = readFmodeVoiceTokenStatus({}, {
- processEnv: {},
- fileEnv: { QIWEI_VOICE_AUTH_TOKEN: validToken },
- claudeEnv: {},
- fmodeConfig: {},
- });
- assert.equal(status.configured, true);
- assert.equal(status.format, 'fmode-sk');
- assert.notEqual(status.masked, validToken);
- assert.doesNotMatch(JSON.stringify(status), new RegExp(validToken));
- assert.equal(readFmodeVoiceToken({ authToken: validToken }, {
- processEnv: {}, fileEnv: {}, claudeEnv: {}, fmodeConfig: {},
- }), validToken);
- assert.equal(readFmodeVoiceToken({}, {
- processEnv: {},
- fileEnv: { QIWEI_VOICE_AUTH_TOKEN: sessionToken },
- claudeEnv: {},
- fmodeConfig: {},
- }), '');
- assert.throws(() => saveFmodeVoiceToken({ token: sessionToken, envRoot: root }), /sk-/);
- let dynamicToken = '';
- const dynamicStatus = () => readFmodeVoiceTokenStatus({}, {
- processEnv: dynamicToken ? { QIWEI_VOICE_AUTH_TOKEN: dynamicToken } : {},
- fileEnv: {},
- claudeEnv: {},
- fmodeConfig: {},
- });
- const service = new VoiceCloneService({
- config: {
- endpoint: 'https://server.fmode.cn/api/voice/indextts2',
- authTokenResolver: () => dynamicToken,
- authTokenStatusResolver: dynamicStatus,
- },
- qiwei: {},
- });
- assert.equal(service.status().configured, false);
- dynamicToken = validToken;
- const configured = service.status();
- assert.equal(configured.configured, true);
- assert.equal(configured.authTokenConfigured, true);
- assert.notEqual(configured.authTokenMasked, validToken);
- assert.doesNotMatch(JSON.stringify(configured), new RegExp(validToken));
- assert.throws(() => service.requireReady(), /尚未初始化本人声音/);
- console.log('[ok] voice token fallback persistence, masking, validation, and hot reload');
- }
- main()
- .catch(error => {
- console.error(error.message || 'voice token smoke failed');
- process.exitCode = 1;
- })
- .finally(restoreEnv);
|