feat(laya): clarify unavailable runtime download flow (#28)
Explain how to start the optional Laya runtime when model download fails because the service is unavailable, while keeping generic failures concise. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1212,7 +1212,7 @@
|
|||||||
<script src="/js/components/VideoPlayer.js?v=5"></script>
|
<script src="/js/components/VideoPlayer.js?v=5"></script>
|
||||||
<script src="/js/services/channelLanguageDetection.js?v=1"></script>
|
<script src="/js/services/channelLanguageDetection.js?v=1"></script>
|
||||||
<script src="/js/services/channelLanguageFusion.js?v=1"></script>
|
<script src="/js/services/channelLanguageFusion.js?v=1"></script>
|
||||||
<script src="/js/services/layaStatusPresentation.js?v=5"></script>
|
<script src="/js/services/layaStatusPresentation.js?v=6"></script>
|
||||||
<script src="/js/services/liveAnalysisPresentation.js?v=1"></script>
|
<script src="/js/services/liveAnalysisPresentation.js?v=1"></script>
|
||||||
<script src="/js/services/liveChannelProjection.js?v=5"></script>
|
<script src="/js/services/liveChannelProjection.js?v=5"></script>
|
||||||
<script src="/js/services/channelVariantGrouping.js?v=7"></script>
|
<script src="/js/services/channelVariantGrouping.js?v=7"></script>
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
if (typeof module === 'object' && module.exports) module.exports = service;
|
if (typeof module === 'object' && module.exports) module.exports = service;
|
||||||
if (root) root.LayaStatusPresentation = service;
|
if (root) root.LayaStatusPresentation = service;
|
||||||
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
|
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
|
||||||
|
const START_COMMAND = 'docker compose --profile laya up -d';
|
||||||
const PHASE_LABELS = {
|
const PHASE_LABELS = {
|
||||||
idle: 'Model not downloaded',
|
idle: 'Model not downloaded',
|
||||||
checking: 'Checking local AI model…',
|
checking: 'Checking local AI model…',
|
||||||
@ -39,6 +40,10 @@
|
|||||||
const failed = phase === 'failed';
|
const failed = phase === 'failed';
|
||||||
const modelPresent = status.modelPresent === true;
|
const modelPresent = status.modelPresent === true;
|
||||||
const runtimeAvailable = status.runtimeAvailable === true;
|
const runtimeAvailable = status.runtimeAvailable === true;
|
||||||
|
const runtimeUnavailable = status.runtimeAvailable === false;
|
||||||
|
const runtimeHelp = runtimeUnavailable
|
||||||
|
? `Nodecast cannot reach the optional Laya runtime. Standard matching remains available.\nStart the Laya service, then try again:\n${START_COMMAND}`
|
||||||
|
: '';
|
||||||
const ready = modelPresent && runtimeAvailable && !busy && !failed;
|
const ready = modelPresent && runtimeAvailable && !busy && !failed;
|
||||||
const statusLabel = ready
|
const statusLabel = ready
|
||||||
? 'Ready'
|
? 'Ready'
|
||||||
@ -64,13 +69,13 @@
|
|||||||
totalBytes: status.totalBytes !== null && status.totalBytes !== undefined && Number.isFinite(Number(status.totalBytes))
|
totalBytes: status.totalBytes !== null && status.totalBytes !== undefined && Number.isFinite(Number(status.totalBytes))
|
||||||
? Number(status.totalBytes) : null,
|
? Number(status.totalBytes) : null,
|
||||||
errorMessage: failed ? (error.message || 'The local AI model could not be downloaded.') : '',
|
errorMessage: failed ? (error.message || 'The local AI model could not be downloaded.') : '',
|
||||||
errorDetail: failed ? error.detail : '',
|
errorDetail: failed ? [error.detail, runtimeHelp].filter(Boolean).join('\n\n') : '',
|
||||||
downloadLabel: failed ? 'Retry download' : 'Download model',
|
downloadLabel: failed ? 'Retry download' : 'Download model',
|
||||||
showDownload: !busy && !modelPresent && (phase === 'idle' || failed),
|
showDownload: !busy && !modelPresent && (phase === 'idle' || failed),
|
||||||
showRemove: !busy && modelPresent,
|
showRemove: !busy && modelPresent,
|
||||||
showUseStandard: failed && mode !== 'algo',
|
showUseStandard: failed && mode !== 'algo',
|
||||||
showCheckAgain: !busy && modelPresent && !runtimeAvailable,
|
showCheckAgain: !busy && modelPresent && !runtimeAvailable,
|
||||||
showStartCommand: !busy && modelPresent && !runtimeAvailable,
|
showStartCommand: !busy && runtimeUnavailable,
|
||||||
availabilityMessage: modelPresent && !runtimeAvailable
|
availabilityMessage: modelPresent && !runtimeAvailable
|
||||||
? 'The model is installed, but the Local AI service is not running. Standard channel matching is being used.'
|
? 'The model is installed, but the Local AI service is not running. Standard channel matching is being used.'
|
||||||
: ''
|
: ''
|
||||||
|
|||||||
@ -36,6 +36,31 @@ test('failed downloads expose retry, safe details and Standard fallback', () =>
|
|||||||
assert.equal(view.errorDetail, 'The optional Laya runtime is unavailable.');
|
assert.equal(view.errorDetail, 'The optional Laya runtime is unavailable.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('failed Laya downloads explain how to start the unavailable runtime', () => {
|
||||||
|
const view = presentLayaStatus({
|
||||||
|
phase: 'failed',
|
||||||
|
modelPresent: false,
|
||||||
|
runtimeAvailable: false,
|
||||||
|
error: { message: 'Model download failed', detail: 'The optional Laya runtime is unavailable.' }
|
||||||
|
}, 'hybrid');
|
||||||
|
assert.match(view.errorDetail, /Nodecast cannot reach the optional Laya runtime/);
|
||||||
|
assert.match(view.errorDetail, /Standard matching remains available/);
|
||||||
|
assert.match(view.errorDetail, /Start the Laya service, then try again:/);
|
||||||
|
assert.match(view.errorDetail, /docker compose --profile laya up -d/);
|
||||||
|
assert.equal(view.showStartCommand, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('generic Laya failures do not suggest Docker Compose', () => {
|
||||||
|
const view = presentLayaStatus({
|
||||||
|
phase: 'failed',
|
||||||
|
modelPresent: false,
|
||||||
|
runtimeAvailable: true,
|
||||||
|
error: { message: 'Model download failed', detail: 'Laya model operation failed (HTTP 500).' }
|
||||||
|
}, 'hybrid');
|
||||||
|
assert.doesNotMatch(view.errorDetail, /docker compose/);
|
||||||
|
assert.equal(view.showStartCommand, false);
|
||||||
|
});
|
||||||
|
|
||||||
test('ready models expose removal without download actions', () => {
|
test('ready models expose removal without download actions', () => {
|
||||||
const view = presentLayaStatus({ phase: 'idle', modelPresent: true, runtimeAvailable: true, sizeBytes: 678323814 });
|
const view = presentLayaStatus({ phase: 'idle', modelPresent: true, runtimeAvailable: true, sizeBytes: 678323814 });
|
||||||
assert.equal(view.statusLabel, 'Ready');
|
assert.equal(view.statusLabel, 'Ready');
|
||||||
|
|||||||
Reference in New Issue
Block a user