update embedding stats every 5s for user

This commit is contained in:
perf3ct
2025-03-08 23:19:41 +00:00
parent 0cd1be5568
commit 1ca98e2fc2
2 changed files with 69 additions and 11 deletions

View File

@@ -31,6 +31,9 @@ interface EmbeddingStats {
} }
export default class AiSettingsWidget extends OptionsWidget { export default class AiSettingsWidget extends OptionsWidget {
private statsRefreshInterval: NodeJS.Timeout | null = null;
private readonly STATS_REFRESH_INTERVAL = 5000; // 5 seconds
doRender() { doRender() {
this.$widget = $(` this.$widget = $(`
<div class="options-section"> <div class="options-section">
@@ -203,12 +206,15 @@ export default class AiSettingsWidget extends OptionsWidget {
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div> aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
</div> </div>
</div> </div>
<button class="btn btn-sm btn-outline-secondary embedding-refresh-stats mt-2"> <div class="mt-2">
<span class="text-muted small">${t("ai_llm.auto_refresh_notice", { seconds: this.STATS_REFRESH_INTERVAL/1000 })}</span>
<button class="btn btn-sm btn-outline-secondary embedding-refresh-stats ml-2">
${t("ai_llm.refresh_stats")} ${t("ai_llm.refresh_stats")}
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>`); </div>`);
const $aiEnabled = this.$widget.find('.ai-enabled'); const $aiEnabled = this.$widget.find('.ai-enabled');
@@ -385,18 +391,51 @@ export default class AiSettingsWidget extends OptionsWidget {
// Initial fetch of embedding stats // Initial fetch of embedding stats
setTimeout(async () => { setTimeout(async () => {
await this.refreshEmbeddingStats(); await this.refreshEmbeddingStats();
// Start polling for stats updates
this.startStatsPolling();
}, 500); }, 500);
return this.$widget; return this.$widget;
} }
async refreshEmbeddingStats() { /**
* Start automatic polling for embedding statistics
*/
startStatsPolling() {
// Clear any existing interval first
this.stopStatsPolling();
// Set up new polling interval
this.statsRefreshInterval = setInterval(async () => {
// Only refresh if this widget is still visible
if (this.$widget && this.$widget.is(':visible') &&
this.$widget.find('.embedding-section').is(':visible')) {
await this.refreshEmbeddingStats(true);
}
}, this.STATS_REFRESH_INTERVAL);
}
/**
* Stop automatic polling for embedding statistics
*/
stopStatsPolling() {
if (this.statsRefreshInterval) {
clearInterval(this.statsRefreshInterval);
this.statsRefreshInterval = null;
}
}
async refreshEmbeddingStats(silent = false) {
if (!this.$widget) return; if (!this.$widget) return;
try { try {
const $refreshButton = this.$widget.find('.embedding-refresh-stats'); const $refreshButton = this.$widget.find('.embedding-refresh-stats');
// Only update button state if not in silent mode
if (!silent) {
$refreshButton.prop('disabled', true); $refreshButton.prop('disabled', true);
$refreshButton.text(t("ai_llm.refreshing")); $refreshButton.text(t("ai_llm.refreshing"));
}
const response = await server.get<EmbeddingStats>('embeddings/stats'); const response = await server.get<EmbeddingStats>('embeddings/stats');
@@ -420,13 +459,18 @@ export default class AiSettingsWidget extends OptionsWidget {
} }
} catch (error) { } catch (error) {
console.error("Error fetching embedding stats:", error); console.error("Error fetching embedding stats:", error);
if (!silent) {
toastService.showError(t("ai_llm.stats_error")); toastService.showError(t("ai_llm.stats_error"));
}
} finally { } finally {
// Only update button state if not in silent mode
if (!silent) {
const $refreshButton = this.$widget.find('.embedding-refresh-stats'); const $refreshButton = this.$widget.find('.embedding-refresh-stats');
$refreshButton.prop('disabled', false); $refreshButton.prop('disabled', false);
$refreshButton.text(t("ai_llm.refresh_stats")); $refreshButton.text(t("ai_llm.refresh_stats"));
} }
} }
}
updateAiSectionVisibility() { updateAiSectionVisibility() {
if (!this.$widget) return; if (!this.$widget) return;
@@ -435,6 +479,19 @@ export default class AiSettingsWidget extends OptionsWidget {
this.$widget.find('.ai-providers-section').toggle(aiEnabled); this.$widget.find('.ai-providers-section').toggle(aiEnabled);
this.$widget.find('.ai-provider').toggle(aiEnabled); this.$widget.find('.ai-provider').toggle(aiEnabled);
this.$widget.find('.embedding-section').toggle(aiEnabled); this.$widget.find('.embedding-section').toggle(aiEnabled);
// Start or stop polling based on visibility
if (aiEnabled && this.$widget.find('.embedding-section').is(':visible')) {
this.startStatsPolling();
} else {
this.stopStatsPolling();
}
}
// Clean up when the widget is removed
cleanup() {
this.stopStatsPolling();
super.cleanup();
} }
optionsLoaded(options: OptionMap) { optionsLoaded(options: OptionMap) {

View File

@@ -1176,7 +1176,8 @@
"never": "Never", "never": "Never",
"refresh_stats": "Refresh Stats", "refresh_stats": "Refresh Stats",
"refreshing": "Refreshing...", "refreshing": "Refreshing...",
"stats_error": "Error fetching embedding statistics" "stats_error": "Error fetching embedding statistics",
"auto_refresh_notice": "Auto-refreshes every {{seconds}} seconds"
}, },
"zoom_factor": { "zoom_factor": {
"title": "Zoom Factor (desktop build only)", "title": "Zoom Factor (desktop build only)",