Files
ForgeLM/tauri-app/src/hooks/useSessionModelController.ts
T
Evandro Fonseca Junior 77c57c3d45 Add runtime state validation before ForgeAgent HTTP call
- Check process_running and ready state before making inference request
- Emit descriptive error messages for each failure scenario
- Handle local vs remote connection modes appropriately
- Validation score: 100 (was 0)

Result: {"status":"keep","validation_score":100,"response_time_ms":500}
2026-04-02 14:37:01 -03:00

86 lines
2.7 KiB
TypeScript

import { useCallback, useRef, useState } from "react";
import type { RuntimeModelFile } from "../features/runtime/types";
import { resolveAlias } from "../lib/modelAlias";
import { useToast } from "../components/Toast";
interface Options {
preferredModel: string;
onSwitchToCooper: (cooperPath: string) => void;
localModels: RuntimeModelFile[];
}
interface SessionModelController {
effectiveModel: string;
overrideSource: 'auto' | 'user';
setUserOverride: (modelPath: string) => void;
clearOverride: () => void;
onDegradationDetected: () => void;
degradationPromptShown: boolean;
}
export function useSessionModelController({
preferredModel,
onSwitchToCooper,
localModels,
}: Options): SessionModelController {
const { showToast } = useToast();
const [effectiveModel, setEffectiveModel] = useState<string>(preferredModel);
const [overrideSource, setOverrideSource] = useState<'auto' | 'user'>('auto');
const [degradationPromptShown, setDegradationPromptShown] = useState(false);
// Keep effectiveModel in sync when preferredModel changes externally (e.g. startup auto-select)
// but only if the user hasn't manually overridden
const prevPreferredRef = useRef(preferredModel);
if (preferredModel !== prevPreferredRef.current) {
prevPreferredRef.current = preferredModel;
if (overrideSource === 'auto') {
setEffectiveModel(preferredModel);
}
}
const setUserOverride = useCallback((modelPath: string) => {
setEffectiveModel(modelPath);
setOverrideSource('user');
}, []);
const clearOverride = useCallback(() => {
setEffectiveModel(preferredModel);
setOverrideSource('auto');
}, [preferredModel]);
const onDegradationDetected = useCallback(() => {
// Don't show if user already chose manually or already shown
if (overrideSource === 'user' || degradationPromptShown) return;
// Find Copper's path from localModels
const copperModel = localModels.find((m) => resolveAlias(m.path) === 'Copper');
if (!copperModel) return; // Copper not available, can't suggest
setDegradationPromptShown(true);
showToast({
id: 'tps-degradation',
variant: 'warning',
message: 'Performance degraded',
detail: 'TPS dropped below 30 for 5s. Switch to Copper (0.8B) for faster responses?',
action: {
label: 'Switch to Copper',
onClick: () => {
setUserOverride(copperModel.path);
onSwitchToCooper(copperModel.path);
},
},
duration: 0, // persistent until dismissed
});
}, [overrideSource, degradationPromptShown, localModels, showToast, setUserOverride, onSwitchToCooper]);
return {
effectiveModel,
overrideSource,
setUserOverride,
clearOverride,
onDegradationDetected,
degradationPromptShown,
};
}