UNPKG

@ai2070/l0

Version:

L0: The Missing Reliability Substrate for AI

307 lines 10.5 kB
import { EventType } from "../types/observability"; export class L0Sentry { sentry; config; constructor(config) { this.sentry = config.sentry; this.config = { captureNetworkErrors: config.captureNetworkErrors ?? true, captureGuardrailViolations: config.captureGuardrailViolations ?? true, minGuardrailSeverity: config.minGuardrailSeverity ?? "error", breadcrumbsForTokens: config.breadcrumbsForTokens ?? false, enableTracing: config.enableTracing ?? true, tags: config.tags, environment: config.environment, }; if (this.config.tags) { for (const [key, value] of Object.entries(this.config.tags)) { this.sentry.setTag(key, value); } } if (this.config.environment) { this.sentry.setTag("environment", this.config.environment); } } startExecution(name = "l0.execution", metadata) { this.sentry.addBreadcrumb({ type: "info", category: "l0", message: "L0 execution started", data: metadata, level: "info", timestamp: Date.now() / 1000, }); if (this.config.enableTracing && this.sentry.startSpan) { let finishSpan; this.sentry.startSpan({ name, op: "l0.execution", attributes: metadata, }, (span) => { finishSpan = () => span?.end(); }); return finishSpan; } return undefined; } startStream() { this.sentry.addBreadcrumb({ type: "info", category: "l0.stream", message: "Stream started", level: "info", timestamp: Date.now() / 1000, }); } recordToken(token) { if (this.config.breadcrumbsForTokens) { this.sentry.addBreadcrumb({ type: "debug", category: "l0.token", message: token ? `Token: ${token.slice(0, 50)}` : "Token received", level: "debug", timestamp: Date.now() / 1000, }); } } recordFirstToken(ttft) { this.sentry.addBreadcrumb({ type: "info", category: "l0.stream", message: `First token received`, data: { ttft_ms: ttft }, level: "info", timestamp: Date.now() / 1000, }); } recordNetworkError(error, errorType, retried) { this.sentry.addBreadcrumb({ type: "error", category: "l0.network", message: `Network error: ${errorType}`, data: { error_type: errorType, message: error.message, retried, }, level: "error", timestamp: Date.now() / 1000, }); if (this.config.captureNetworkErrors && !retried) { this.sentry.captureException(error, { tags: { error_type: errorType, component: "l0.network", }, extra: { retried, }, }); } } recordRetry(attempt, reason, isNetworkError) { this.sentry.addBreadcrumb({ type: "info", category: "l0.retry", message: `Retry attempt ${attempt}`, data: { attempt, reason, is_network_error: isNetworkError, }, level: "warning", timestamp: Date.now() / 1000, }); } recordGuardrailViolations(violations) { for (const violation of violations) { this.sentry.addBreadcrumb({ type: "error", category: "l0.guardrail", message: `Guardrail violation: ${violation.rule}`, data: { rule: violation.rule, severity: violation.severity, message: violation.message, recoverable: violation.recoverable, }, level: this.mapSeverity(violation.severity), timestamp: Date.now() / 1000, }); if (this.config.captureGuardrailViolations && this.shouldCapture(violation.severity)) { this.sentry.captureMessage(`Guardrail violation: ${violation.message}`, this.mapSeverity(violation.severity)); } } } recordDrift(detected, types) { if (detected) { this.sentry.addBreadcrumb({ type: "error", category: "l0.drift", message: `Drift detected: ${types.join(", ")}`, data: { types }, level: "warning", timestamp: Date.now() / 1000, }); } } completeStream(tokenCount) { this.sentry.addBreadcrumb({ type: "info", category: "l0.stream", message: "Stream completed", data: { token_count: tokenCount }, level: "info", timestamp: Date.now() / 1000, }); } completeExecution(telemetry) { this.sentry.setContext("l0_telemetry", { session_id: telemetry.sessionId, duration_ms: telemetry.duration, tokens: telemetry.metrics.totalTokens, tokens_per_second: telemetry.metrics.tokensPerSecond, ttft_ms: telemetry.metrics.timeToFirstToken, retries: telemetry.metrics.totalRetries, network_errors: telemetry.network.errorCount, guardrail_violations: telemetry.guardrails?.violationCount ?? 0, }); this.sentry.addBreadcrumb({ type: "info", category: "l0", message: "L0 execution completed", data: { duration_ms: telemetry.duration, tokens: telemetry.metrics.totalTokens, retries: telemetry.metrics.totalRetries, }, level: "info", timestamp: Date.now() / 1000, }); } recordFailure(error, telemetry) { if (telemetry) { this.sentry.setContext("l0_telemetry", { session_id: telemetry.sessionId, duration_ms: telemetry.duration, tokens: telemetry.metrics.totalTokens, retries: telemetry.metrics.totalRetries, network_errors: telemetry.network.errorCount, }); } this.sentry.captureException(error, { tags: { component: "l0", }, extra: { telemetry: telemetry ? { session_id: telemetry.sessionId, duration_ms: telemetry.duration, tokens: telemetry.metrics.totalTokens, } : undefined, }, }); } recordFromMonitor(monitor) { const telemetry = monitor.getTelemetry(); if (telemetry) { this.completeExecution(telemetry); } } mapSeverity(severity) { switch (severity) { case "fatal": return "fatal"; case "error": return "error"; case "warning": return "warning"; default: return "info"; } } shouldCapture(severity) { const levels = ["warning", "error", "fatal"]; const minIndex = levels.indexOf(this.config.minGuardrailSeverity); const currentIndex = levels.indexOf(severity); return currentIndex >= minIndex; } } export function createSentryIntegration(config) { return new L0Sentry(config); } export function createSentryHandler(config) { const integration = createSentryIntegration(config); let finishSpan; return (event) => { switch (event.type) { case EventType.SESSION_START: { const e = event; finishSpan = integration.startExecution("l0.execution", { attempt: e.attempt, isRetry: e.isRetry, isFallback: e.isFallback, }); integration.startStream(); break; } case EventType.RETRY_ATTEMPT: { const e = event; integration.recordRetry(e.attempt, e.reason, e.isNetwork ?? false); break; } case EventType.NETWORK_ERROR: { const e = event; integration.recordNetworkError(new Error(e.error), e.category || "unknown", e.retryable ?? false); break; } case EventType.ERROR: { const e = event; integration.recordNetworkError(new Error(e.error), e.failureType || "unknown", e.recoveryStrategy === "retry"); break; } case EventType.GUARDRAIL_RULE_RESULT: { const e = event; if (e.violation) { integration.recordGuardrailViolations([e.violation]); } break; } case EventType.DRIFT_CHECK_RESULT: { const e = event; if (e.detected) { integration.recordDrift(true, e.types); } break; } case EventType.COMPLETE: { const e = event; integration.completeStream(e.tokenCount); finishSpan?.(); finishSpan = undefined; break; } default: break; } }; } export async function withSentry(config, fn) { const integration = createSentryIntegration(config); integration.startExecution(); try { const result = await fn(); if (result.telemetry) { integration.completeExecution(result.telemetry); } return result; } catch (error) { integration.recordFailure(error instanceof Error ? error : new Error(String(error))); throw error; } } //# sourceMappingURL=sentry.js.map