AUDIT / src /lib /browserLLM.ts
Arypulka98's picture
feat(audit): deploy full backend cluster node (part 3)
95eb75a verified
Raw
History Blame Contribute Delete
2.9 kB
/**
* browserLLM.ts
* Infrastruttura per AI locale browser-side (WebGPU / transformers.js).
*
* STATO: nessun modello locale è integrato (WebLLM/transformers.js richiedono
* ~3–4 GB di download, non adatti a iPhone). browserGenerate() ora lancia un
* errore esplicito (Gap 1 fix S483) invece di simulare una risposta falsa.
* providerChain.ts cattura l'errore (non-AbortError) e cade sull'esaurimento
* provider, mostrando un messaggio onesto all'utente.
*
* Compatibile con: ProviderIndicator · consensusMode · providerChain
*/
import type { ChatMessage } from "./types";
export type BrowserLLMPhase =
| { phase: "idle" }
| { phase: "loading"; progress: number; text: string }
| { phase: "ready"; model: string }
| { phase: "generating"; model: string }
| { phase: "error"; message: string }
| { phase: "unsupported"; reason: string };
export interface BrowserModel {
id: string;
name: string;
desc: string;
}
export const BROWSER_MODELS: BrowserModel[] = [
{
id: "local-small",
name: "Locale piccolo",
desc: "Fallback offline leggero",
},
];
let currentPhase: BrowserLLMPhase = { phase: "idle" };
const listeners = new Set<(s: BrowserLLMPhase) => void>();
function emit(status: BrowserLLMPhase) {
currentPhase = status;
listeners.forEach(fn => fn(status));
}
export function onBrowserLLMStatus(
cb: (status: BrowserLLMPhase) => void,
): () => void {
listeners.add(cb);
cb(currentPhase);
return () => {
listeners.delete(cb);
};
}
export function isWebGPUSupported(): boolean {
return typeof navigator !== "undefined" && "gpu" in navigator;
}
let ready = false;
export async function loadBrowserModel(
_modelId = "local-small",
): Promise<void> {
// Nessun modello locale integrato — segnala unsupported senza simulare loading.
emit({
phase: "unsupported",
reason: "Nessun modello locale disponibile. Usa i provider cloud.",
});
}
export function isModelReady(): boolean {
return ready;
}
/**
* Gap 1 fix (S483): invece di restituire un echo formattato della domanda
* dell'utente (che sembrava una risposta AI ma non lo era), lancia un errore
* esplicito. providerChain.ts cattura questo errore (non-AbortError) e
* prosegue verso il messaggio di esaurimento provider, che è onesto e utile.
*/
export async function browserGenerate(
_messages: ChatMessage[],
_onChunk?: (chunk: string) => void,
signal?: AbortSignal,
): Promise<string> {
if (signal?.aborted) {
throw new DOMException("Operazione interrotta", "AbortError");
}
emit({ phase: "unsupported", reason: "Nessun modello LLM locale integrato." });
throw new Error(
"BrowserLLM_UNAVAILABLE: nessun modello LLM locale è integrato. " +
"Tutti i provider cloud sono temporaneamente esauriti.",
);
}
export function unloadBrowserModel(): void {
ready = false;
emit({
phase: "idle",
});
}