UNPKG

@ai2070/l0

Version:

L0: The Missing Reliability Substrate for AI

165 lines 5.54 kB
export class GuardrailEngine { rules; config; state; constructor(config) { this.rules = config.rules || []; this.config = { stopOnFatal: true, enableStreaming: true, checkInterval: 100, ...config, }; this.state = this.createInitialState(); } createInitialState() { return { violations: [], violationsByRule: new Map(), hasFatalViolations: false, hasErrorViolations: false, violationCount: 0, }; } check(context) { const violations = []; const timestamp = Date.now(); if (this.config.onPhaseStart) { this.config.onPhaseStart(context.content.length, this.rules.length); } let ruleIndex = 0; for (const rule of this.rules) { if (rule.streaming && !this.config.enableStreaming && !context.completed) { continue; } if (!rule.streaming && !context.completed) { continue; } if (this.config.onRuleStart) { this.config.onRuleStart(ruleIndex, rule.name); } try { const ruleViolations = rule.check({ ...context, previousViolations: this.state.violations, }); for (const violation of ruleViolations) { violations.push({ ...violation, timestamp: timestamp, }); } if (ruleViolations.length > 0) { const existing = this.state.violationsByRule.get(rule.name) || []; this.state.violationsByRule.set(rule.name, [ ...existing, ...ruleViolations, ]); } if (this.config.onRuleEnd) { this.config.onRuleEnd(ruleIndex, rule.name); } if (this.config.stopOnFatal && ruleViolations.some((v) => v.severity === "fatal")) { break; } } catch (error) { violations.push({ rule: rule.name, message: `Rule execution failed: ${error instanceof Error ? error.message : "Unknown error"}`, severity: "warning", recoverable: true, timestamp, }); if (this.config.onRuleEnd) { this.config.onRuleEnd(ruleIndex, rule.name); } } ruleIndex++; } if (this.config.onPhaseEnd) { this.config.onPhaseEnd(this.rules.length, violations.length); } this.state.violations.push(...violations); this.state.violationCount = this.state.violations.length; this.state.hasFatalViolations = violations.some((v) => v.severity === "fatal"); this.state.hasErrorViolations = violations.some((v) => v.severity === "error"); this.state.lastCheckTime = timestamp; if (this.config.onViolation) { for (const violation of violations) { this.config.onViolation(violation); } } const result = { passed: violations.length === 0, violations, shouldRetry: this.shouldRetry(violations), shouldHalt: this.shouldHalt(violations), summary: { total: violations.length, fatal: violations.filter((v) => v.severity === "fatal").length, errors: violations.filter((v) => v.severity === "error").length, warnings: violations.filter((v) => v.severity === "warning").length, }, }; return result; } shouldRetry(violations) { return violations.some((v) => v.recoverable && (v.severity === "error" || v.severity === "fatal")); } shouldHalt(violations) { if (violations.some((v) => v.severity === "fatal")) { return true; } if (violations.some((v) => !v.recoverable && v.severity === "error")) { return true; } return false; } getState() { return { ...this.state }; } reset() { this.state = this.createInitialState(); } addRule(rule) { this.rules.push(rule); } removeRule(ruleName) { const index = this.rules.findIndex((r) => r.name === ruleName); if (index !== -1) { this.rules.splice(index, 1); return true; } return false; } getViolationsByRule(ruleName) { return this.state.violationsByRule.get(ruleName) || []; } getAllViolations() { return [...this.state.violations]; } hasViolations() { return this.state.violationCount > 0; } hasFatalViolations() { return this.state.hasFatalViolations; } hasErrorViolations() { return this.state.hasErrorViolations; } } export function createGuardrailEngine(rules, options) { return new GuardrailEngine({ rules, ...options, }); } export function checkGuardrails(context, rules) { const engine = createGuardrailEngine(rules); return engine.check(context); } //# sourceMappingURL=engine.js.map