fix: restore Laya language analysis and stream variants

Run Local AI language detection during full rebuilds after identity classification and restore variant expansion with a visible playing stream indicator.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
blomios
2026-10-08 00:14:10 +02:00
parent 240b26536e
commit a447d0dfe3
5 changed files with 300 additions and 5 deletions

View File

@ -218,6 +218,55 @@ async function collectOptionalIdentityHints(items, mode, layaClient, options = {
}
}
function analysisScopeItems(items, options = {}) {
if (options.analyzeAll === true) return items;
if (Object.hasOwn(options, 'scopeItemIds')) {
const ids = new Set(Array.from(options.scopeItemIds || [], String));
return items.filter(item => ids.has(String(item.id)) || ids.has(String(item.item_id)));
}
return items.filter(item => !hasPersistedLanguage(item));
}
function languageDescriptor(item) {
const parts = [item.name, item.category_name, item.tvg_id].filter(Boolean).map(String);
return { id: item.id, text: parts.join(' | ').slice(0, 4096) || String(item.id) };
}
async function collectOptionalLayaLanguages(items, layaClient, options = {}) {
if (!layaClient?.detectBatch || items.length === 0) return;
const total = Math.ceil(items.length / 64);
let processed = 0;
options.onProgress?.({ processed, total });
try {
for (let index = 0; index < items.length; index += 64) {
const batch = items.slice(index, index + 64);
const response = await layaClient.detectBatch({
items: batch.map(languageDescriptor),
model: 'multilingual'
});
const results = new Map((response?.results || []).map(result => [String(result.id), result]));
for (const item of batch) {
const result = results.get(String(item.id));
const code = String(result?.language || '').toLowerCase();
if (!/^[a-z]{2,3}$/.test(code) || code === 'und') continue;
const confidence = Number(result.confidence) || 0;
item.language_code = code;
item.language_confidence = confidence;
item.language_scores = JSON.stringify({ [code]: confidence });
item.language_evidence = JSON.stringify([
{ code, weight: confidence, type: 'laya', value: 'Local AI model' }
]);
item.language_detector = 'laya';
item.language_input_hash = languageInputHash(item);
}
processed += 1;
options.onProgress?.({ processed, total });
}
} catch (error) {
console.warn('[LiveProjection] Laya language detection unavailable; keeping persisted or algorithmic languages');
}
}
function catalogInputHash(items) {
return stableHash(items
.map(item => `${item.id}\0${item.name}\0${item.category_id || ''}`)
@ -359,11 +408,12 @@ async function rebuildWithSignals(database = null, options = {}) {
let identityHints = new Map();
if (mode !== 'algo') {
const layaClient = options.layaClient || new (require('./layaService').LayaService)();
const scopedItems = analysisScopeItems(items, options);
const identityOptions = options.analyzeAll === true
? {}
: Object.hasOwn(options, 'scopeItemIds')
? { scopeItemIds: options.scopeItemIds }
: { scopeItemIds: items.filter(item => !hasPersistedLanguage(item)).map(item => item.id) };
: { scopeItemIds: scopedItems.map(item => item.id) };
identityHints = await collectOptionalIdentityHints(items, mode, layaClient, {
...identityOptions,
onProgress: ({ processed, total }) => updateProjectionProgress(database, 'laya_identity', {
@ -371,6 +421,12 @@ async function rebuildWithSignals(database = null, options = {}) {
layaTotal: total
})
});
await collectOptionalLayaLanguages(scopedItems, layaClient, {
onProgress: ({ processed, total }) => updateProjectionProgress(database, 'laya_language', {
layaProcessed: processed,
layaTotal: total
})
});
}
return rebuild(database, { ...options, items, mode, identityHints });
}