Add a languageDetectionMode setting (algo | laya | laya+algo) exposed in Settings with three engine choices. When Laya is enabled, a laya service (Dockerfile.laya, optional compose profile, models stored outside the repo under ./data/models/laya) can be started, with model download and deletion from the UI via /laya routes to manage disk space. Add a channelLanguageFusion service combining Laya results with the existing algorithm, and wire detection mode through grouping, channel list and player. Cover engine selection, fusion and laya service behavior with tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
45 lines
1.7 KiB
JavaScript
45 lines
1.7 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('fs/promises');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
const {
|
|
LayaRequestError,
|
|
LayaService,
|
|
clearDirectoryContents,
|
|
validateBatchPayload
|
|
} = require('../server/services/layaService');
|
|
|
|
test('status reports an unavailable runtime without throwing', async () => {
|
|
const modelDir = await fs.mkdtemp(path.join(os.tmpdir(), 'nodecast-laya-status-'));
|
|
const service = new LayaService({
|
|
modelDir,
|
|
cache: null,
|
|
fetch: async () => { throw new Error('connection refused'); }
|
|
});
|
|
const status = await service.status();
|
|
assert.equal(status.runtimeAvailable, false);
|
|
assert.equal(status.modelPresent, false);
|
|
});
|
|
|
|
test('model deletion remains limited to the configured model directory', async () => {
|
|
const parent = await fs.mkdtemp(path.join(os.tmpdir(), 'nodecast-laya-delete-'));
|
|
const modelDir = path.join(parent, 'models');
|
|
const sentinel = path.join(parent, 'keep.txt');
|
|
await fs.mkdir(path.join(modelDir, 'nested'), { recursive: true });
|
|
await fs.writeFile(path.join(modelDir, 'nested', 'model.bin'), 'model');
|
|
await fs.writeFile(sentinel, 'keep');
|
|
|
|
await clearDirectoryContents(modelDir);
|
|
|
|
assert.deepEqual(await fs.readdir(modelDir), []);
|
|
assert.equal(await fs.readFile(sentinel, 'utf8'), 'keep');
|
|
});
|
|
|
|
test('batch validation rejects oversized item counts', () => {
|
|
assert.throws(
|
|
() => validateBatchPayload({ items: Array.from({ length: 65 }, (_, id) => ({ id, text: 'channel' })) }),
|
|
error => error instanceof LayaRequestError && error.statusCode === 413
|
|
);
|
|
});
|