AUDIT / src /lib /agentSSEState.ts
Arypulka98's picture
feat(audit): deploy full backend cluster node (part 3)
95eb75a verified
Raw
History Blame Contribute Delete
4.67 kB
// agentSSEState.ts — P3-5: stato condiviso estratto da agentSSE.ts
// Esportato come modulo puro — zero importazioni da agentSSE.ts (no circular deps).
// Importato da agentSSE.ts (lifecycle) e agentSSEDispatch.ts (handleEvent).
// ─── Backoff schedule (delegato a USR) ────────────────────────────────────────
export const BACKOFF_MS = [1000, 2000, 4000, 8000, 16000, 30000];
// S346: timeout globale task SSE — se non completa in MAX_TASK_DURATION_MS,
// il task viene automaticamente cancellato con status ERROR.
export const MAX_TASK_DURATION_MS = 8 * 60 * 1000; // S701: 5→8min — MAX_ITER=16 + browser testing
// S399-GUARD: max task SSE concorrenti.
export const MAX_CONCURRENT_SSE = 1;
// ─── Params storage per retry/queue promotion ─────────────────────────────────
export interface TaskParams {
goal: string;
context: Array<{ role: string; content: string }>;
maxSteps: number;
resumeFromStep?: number; // P16-F3: propagato da agente:promote-queued per resume corretto
persona?: string; // P17-F5: expertise persona ("researcher"|"coder"|"architect"|"reasoner"|"analyst")
}
export const _taskParams = new Map<string, TaskParams>();
// S345: track task già avviati sul backend — evita double-POST su reconnect USR.
export const _taskStarted = new Set<string>();
// ─── TTFT tracking ────────────────────────────────────────────────────────────
export const _connectAt = new Map<string, number>();
// S420: streaming text buffer — accumula token per task attivo
// S758-P4.1: thinking timer — fires if no step_start within 3s after task_start
export const _thinkingTimers: Map<string, ReturnType<typeof setTimeout>> = new Map();
export const _streamingBuffer = new Map<string, string>();
// S422: TTL timestamps — previene memory leak su connessioni SSE interrotte senza task_done
export const _bufferTimestamps = new Map<string, number>();
const _BUFFER_TTL_MS = 5 * 60 * 1000; // 5 minuti
if (typeof window !== "undefined") {
setInterval(() => {
const _now = Date.now();
_bufferTimestamps.forEach((ts, id) => {
if (_now - ts > _BUFFER_TTL_MS) {
_streamingBuffer.delete(id);
_bufferTimestamps.delete(id);
}
});
}, 2 * 60 * 1000);
}
// S346: timer ID per task timeout — clearTimeout su cancel/done/error
export const _taskTimers = new Map<string, ReturnType<typeof setTimeout>>();
// A2-retry: tentativi residui di riavvio automatico dopo idle > 10min.
// P1-FIX (S493): persistiti in sessionStorage — sopravvivono al hard reload.
// Esposti come container mutabile per evitare ES module binding assignment error.
const _IDLE_RETRIES_KEY = "agente_idle_retries";
function _loadIdleRetries(): number {
try {
const s = sessionStorage.getItem(_IDLE_RETRIES_KEY);
return s !== null ? Math.max(0, Math.min(2, parseInt(s, 10) || 0)) : 2;
} catch { return 2; }
}
export function _saveIdleRetries(n: number): void {
try { sessionStorage.setItem(_IDLE_RETRIES_KEY, String(n)); } catch { /* non-blocking */ }
}
// P5-FIX (S497): recovery retry counter
const _RECOVERY_RETRIES_KEY = "agente_recovery_retries";
function _loadRecoveryRetries(): number {
try {
const s = sessionStorage.getItem(_RECOVERY_RETRIES_KEY);
return s !== null ? Math.max(0, Math.min(2, parseInt(s, 10) || 0)) : 2;
} catch { return 2; }
}
export function _saveRecoveryRetries(n: number): void {
try { sessionStorage.setItem(_RECOVERY_RETRIES_KEY, String(n)); } catch { /* non-blocking */ }
}
// Mutable retry counters exported as a container object to avoid ES module
// binding assignment errors (live bindings of `let` exports can't be reassigned
// by the importing module in strict ES module semantics).
export const _retryCounts = {
idleRetryLeft: (typeof window !== "undefined") ? _loadIdleRetries() : 2,
recoveryRetryLeft: (typeof window !== "undefined") ? _loadRecoveryRetries() : 2,
};
// Backward-compat shims: agentSSE.ts imports _idleRetryLeft and _recoveryRetryLeft
// as named bindings and assigns to them. Re-export as getters on _retryCounts.
// agentSSE.ts should use _retryCounts.idleRetryLeft directly for mutations.
// These read-only re-exports satisfy the import statement without runtime errors.
export const _idleRetryLeft = _retryCounts.idleRetryLeft;
export const _recoveryRetryLeft = _retryCounts.recoveryRetryLeft;