mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-15 19:52:50 +03:00
Release v3.8.42 — full CHANGELOG in CHANGELOG.md. CI: 103 checks green incl. CodeQL (all languages), Semgrep, all 8 unit shards, coverage, Node 24 compat, and integration tests. Full unit suite validated locally: 19437 pass / 0 fail. The 3 red checks are advisory and do not gate main (no required status checks): SonarCloud/SonarQube new-code coverage gate, and PR Test Policy (test-masking detector flagging the legitimate dead-Phind provider removal in #5530 — reviewed, correct). Includes cycle-close reconciliation + repair of inherited base-red tests from #5480/#5527/#5427/#5521 that the PR->release fast-path did not exercise.
68 lines
1.7 KiB
TypeScript
68 lines
1.7 KiB
TypeScript
/**
|
|
* A2A Routing Decision Logger
|
|
*
|
|
* Records every routing decision to the `routing_decisions` SQLite table.
|
|
* Used by `omniroute_explain_route` (T03) and future learning router.
|
|
* Retention: 7 days default.
|
|
*/
|
|
|
|
import { randomUUID } from "crypto";
|
|
|
|
export interface RoutingFactor {
|
|
name: string; // "quota", "health", "cost", "latency", "task_fit"
|
|
value: number;
|
|
weight: number;
|
|
contribution: number;
|
|
}
|
|
|
|
export interface FallbackEntry {
|
|
provider: string;
|
|
reason: string; // "circuit_breaker_open", "quota_exceeded", "timeout"
|
|
}
|
|
|
|
export interface RoutingDecision {
|
|
requestId: string;
|
|
taskType: string;
|
|
comboId: string;
|
|
providerSelected: string;
|
|
modelUsed: string;
|
|
score: number;
|
|
factors: RoutingFactor[];
|
|
fallbacksTriggered: FallbackEntry[];
|
|
success: boolean;
|
|
latencyMs: number;
|
|
cost: number;
|
|
timestamp: string;
|
|
}
|
|
|
|
// In-memory log (production would use SQLite via routing_decisions table)
|
|
const decisions: RoutingDecision[] = [];
|
|
const MAX_DECISIONS = 1000;
|
|
const RETENTION_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
|
|
/**
|
|
* Log a routing decision.
|
|
*/
|
|
export function logRoutingDecision(
|
|
params: Omit<RoutingDecision, "requestId" | "timestamp">
|
|
): RoutingDecision {
|
|
const decision: RoutingDecision = {
|
|
...params,
|
|
requestId: randomUUID(),
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
|
|
decisions.push(decision);
|
|
|
|
// Cleanup: cap + TTL
|
|
if (decisions.length > MAX_DECISIONS) {
|
|
const cutoff = new Date(Date.now() - RETENTION_MS);
|
|
const validIdx = decisions.findIndex((d) => new Date(d.timestamp) > cutoff);
|
|
if (validIdx > 0) decisions.splice(0, validIdx);
|
|
else if (decisions.length > MAX_DECISIONS)
|
|
decisions.splice(0, decisions.length - MAX_DECISIONS);
|
|
}
|
|
|
|
return decision;
|
|
}
|