|
|
@@ -1,10 +1,26 @@
|
|
|
import { activeProcessingState } from '$lib/stores/chat.svelte';
|
|
|
import { config } from '$lib/stores/settings.svelte';
|
|
|
|
|
|
+export interface LiveProcessingStats {
|
|
|
+ tokensProcessed: number;
|
|
|
+ totalTokens: number;
|
|
|
+ timeMs: number;
|
|
|
+ tokensPerSecond: number;
|
|
|
+}
|
|
|
+
|
|
|
+export interface LiveGenerationStats {
|
|
|
+ tokensGenerated: number;
|
|
|
+ timeMs: number;
|
|
|
+ tokensPerSecond: number;
|
|
|
+}
|
|
|
+
|
|
|
export interface UseProcessingStateReturn {
|
|
|
readonly processingState: ApiProcessingState | null;
|
|
|
getProcessingDetails(): string[];
|
|
|
getProcessingMessage(): string;
|
|
|
+ getPromptProgressText(): string | null;
|
|
|
+ getLiveProcessingStats(): LiveProcessingStats | null;
|
|
|
+ getLiveGenerationStats(): LiveGenerationStats | null;
|
|
|
shouldShowDetails(): boolean;
|
|
|
startMonitoring(): void;
|
|
|
stopMonitoring(): void;
|
|
|
@@ -29,6 +45,7 @@ export interface UseProcessingStateReturn {
|
|
|
export function useProcessingState(): UseProcessingStateReturn {
|
|
|
let isMonitoring = $state(false);
|
|
|
let lastKnownState = $state<ApiProcessingState | null>(null);
|
|
|
+ let lastKnownProcessingStats = $state<LiveProcessingStats | null>(null);
|
|
|
|
|
|
// Derive processing state reactively from chatStore's direct state
|
|
|
const processingState = $derived.by(() => {
|
|
|
@@ -46,6 +63,25 @@ export function useProcessingState(): UseProcessingStateReturn {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+ // Track last known processing stats for when promptProgress disappears
|
|
|
+ $effect(() => {
|
|
|
+ if (processingState?.promptProgress) {
|
|
|
+ const { processed, total, time_ms, cache } = processingState.promptProgress;
|
|
|
+ const actualProcessed = processed - cache;
|
|
|
+ const actualTotal = total - cache;
|
|
|
+
|
|
|
+ if (actualProcessed > 0 && time_ms > 0) {
|
|
|
+ const tokensPerSecond = actualProcessed / (time_ms / 1000);
|
|
|
+ lastKnownProcessingStats = {
|
|
|
+ tokensProcessed: actualProcessed,
|
|
|
+ totalTokens: actualTotal,
|
|
|
+ timeMs: time_ms,
|
|
|
+ tokensPerSecond
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
function startMonitoring(): void {
|
|
|
if (isMonitoring) return;
|
|
|
isMonitoring = true;
|
|
|
@@ -59,28 +95,25 @@ export function useProcessingState(): UseProcessingStateReturn {
|
|
|
const currentConfig = config();
|
|
|
if (!currentConfig.keepStatsVisible) {
|
|
|
lastKnownState = null;
|
|
|
+ lastKnownProcessingStats = null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function getProcessingMessage(): string {
|
|
|
- const state = processingState;
|
|
|
- if (!state) {
|
|
|
+ if (!processingState) {
|
|
|
return 'Processing...';
|
|
|
}
|
|
|
|
|
|
- switch (state.status) {
|
|
|
+ switch (processingState.status) {
|
|
|
case 'initializing':
|
|
|
return 'Initializing...';
|
|
|
case 'preparing':
|
|
|
- if (state.progressPercent !== undefined) {
|
|
|
- return `Processing (${state.progressPercent}%)`;
|
|
|
+ if (processingState.progressPercent !== undefined) {
|
|
|
+ return `Processing (${processingState.progressPercent}%)`;
|
|
|
}
|
|
|
return 'Preparing response...';
|
|
|
case 'generating':
|
|
|
- if (state.tokensDecoded > 0) {
|
|
|
- return `Generating... (${state.tokensDecoded} tokens)`;
|
|
|
- }
|
|
|
- return 'Generating...';
|
|
|
+ return '';
|
|
|
default:
|
|
|
return 'Processing...';
|
|
|
}
|
|
|
@@ -131,8 +164,70 @@ export function useProcessingState(): UseProcessingStateReturn {
|
|
|
}
|
|
|
|
|
|
function shouldShowDetails(): boolean {
|
|
|
- const state = processingState;
|
|
|
- return state !== null && state.status !== 'idle';
|
|
|
+ return processingState !== null && processingState.status !== 'idle';
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns a short progress message with percent
|
|
|
+ */
|
|
|
+ function getPromptProgressText(): string | null {
|
|
|
+ if (!processingState?.promptProgress) return null;
|
|
|
+
|
|
|
+ const { processed, total, cache } = processingState.promptProgress;
|
|
|
+
|
|
|
+ const actualProcessed = processed - cache;
|
|
|
+ const actualTotal = total - cache;
|
|
|
+ const percent = Math.round((actualProcessed / actualTotal) * 100);
|
|
|
+
|
|
|
+ return `Processing ${percent}%`;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns live processing statistics for display (prompt processing phase)
|
|
|
+ * Returns last known stats when promptProgress becomes unavailable
|
|
|
+ */
|
|
|
+ function getLiveProcessingStats(): LiveProcessingStats | null {
|
|
|
+ if (processingState?.promptProgress) {
|
|
|
+ const { processed, total, time_ms, cache } = processingState.promptProgress;
|
|
|
+
|
|
|
+ const actualProcessed = processed - cache;
|
|
|
+ const actualTotal = total - cache;
|
|
|
+
|
|
|
+ if (actualProcessed > 0 && time_ms > 0) {
|
|
|
+ const tokensPerSecond = actualProcessed / (time_ms / 1000);
|
|
|
+
|
|
|
+ return {
|
|
|
+ tokensProcessed: actualProcessed,
|
|
|
+ totalTokens: actualTotal,
|
|
|
+ timeMs: time_ms,
|
|
|
+ tokensPerSecond
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Return last known stats if promptProgress is no longer available
|
|
|
+ return lastKnownProcessingStats;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns live generation statistics for display (token generation phase)
|
|
|
+ */
|
|
|
+ function getLiveGenerationStats(): LiveGenerationStats | null {
|
|
|
+ if (!processingState) return null;
|
|
|
+
|
|
|
+ const { tokensDecoded, tokensPerSecond } = processingState;
|
|
|
+
|
|
|
+ if (tokensDecoded <= 0) return null;
|
|
|
+
|
|
|
+ // Calculate time from tokens and speed
|
|
|
+ const timeMs =
|
|
|
+ tokensPerSecond && tokensPerSecond > 0 ? (tokensDecoded / tokensPerSecond) * 1000 : 0;
|
|
|
+
|
|
|
+ return {
|
|
|
+ tokensGenerated: tokensDecoded,
|
|
|
+ timeMs,
|
|
|
+ tokensPerSecond: tokensPerSecond || 0
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
@@ -141,6 +236,9 @@ export function useProcessingState(): UseProcessingStateReturn {
|
|
|
},
|
|
|
getProcessingDetails,
|
|
|
getProcessingMessage,
|
|
|
+ getPromptProgressText,
|
|
|
+ getLiveProcessingStats,
|
|
|
+ getLiveGenerationStats,
|
|
|
shouldShowDetails,
|
|
|
startMonitoring,
|
|
|
stopMonitoring
|