mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 20:32:20 +03:00
OmniRoute v3.8.26 — see CHANGELOG.md [3.8.26] for the full notes. Highlights: Vertex AI media generation (#3929), GLM-5.2 effort-tier routing (#3885), sticky round-robin combos (#3846), OpenRouter connection presets (#3878), compression prompt-cache fix (#3936/#3890), and a security pass (form-data/vite + workflow hardening, #3949). Co-authored-by: artickc <artickc@users.noreply.github.com> Co-authored-by: rdself <rdself@users.noreply.github.com> Co-authored-by: herjarsa <herjarsa@users.noreply.github.com> Co-authored-by: Jack Smith <16862258+YunyunZhai@users.noreply.github.com> Co-authored-by: dhaern <dhaern@users.noreply.github.com> Co-authored-by: adivekar-utexas <adivekar-utexas@users.noreply.github.com> Co-authored-by: megamen32 <megamen32@users.noreply.github.com> Co-authored-by: zhiru <zhiru@users.noreply.github.com> Co-authored-by: insoln <insoln@users.noreply.github.com> Co-authored-by: diego-anselmo <diego-anselmo@users.noreply.github.com>
152 lines
3.8 KiB
TypeScript
152 lines
3.8 KiB
TypeScript
import {
|
|
finalizeMostRecentPendingRequest,
|
|
finalizePendingRequestById,
|
|
} from "@/lib/usage/usageHistory.ts";
|
|
|
|
import { HTTP_STATUS } from "../config/constants.ts";
|
|
import { buildErrorBody } from "./error.ts";
|
|
|
|
export type StreamCompletionPayload = {
|
|
status: number;
|
|
usage: unknown;
|
|
responseBody?: unknown;
|
|
providerPayload?: unknown;
|
|
clientPayload?: unknown;
|
|
error?: string | null;
|
|
errorCode?: string | null;
|
|
ttft?: number | null;
|
|
};
|
|
|
|
export type StreamFailurePayload = {
|
|
status: number;
|
|
message: string;
|
|
code?: string;
|
|
type?: string;
|
|
};
|
|
|
|
export type PipelineStreamErrorHandler = (event: {
|
|
message: string;
|
|
statusCode: number;
|
|
}) => boolean;
|
|
|
|
export function finalizeStreamRequestLog({
|
|
pendingRequestId,
|
|
model,
|
|
provider,
|
|
connectionId,
|
|
providerResponse,
|
|
clientResponse,
|
|
status,
|
|
error,
|
|
errorCode,
|
|
onWarn,
|
|
}: {
|
|
pendingRequestId: string;
|
|
model: string;
|
|
provider: string;
|
|
connectionId: string | null;
|
|
providerResponse?: unknown;
|
|
clientResponse?: unknown;
|
|
status: number;
|
|
error?: string | null;
|
|
errorCode?: string | null;
|
|
onWarn?: (error: unknown) => void;
|
|
}) {
|
|
try {
|
|
const completedById = finalizePendingRequestById(pendingRequestId, {
|
|
providerResponse,
|
|
clientResponse,
|
|
status,
|
|
error: error || null,
|
|
errorCode: errorCode || null,
|
|
});
|
|
if (!completedById) {
|
|
finalizeMostRecentPendingRequest(model, provider, connectionId, {
|
|
providerResponse,
|
|
clientResponse,
|
|
status,
|
|
error: error || null,
|
|
errorCode: errorCode || null,
|
|
});
|
|
}
|
|
} catch (error) {
|
|
try {
|
|
if (onWarn) {
|
|
onWarn(error);
|
|
} else {
|
|
console.warn(
|
|
"finalizeMostRecentPendingRequest failed:",
|
|
error && typeof error === "object" && "message" in error
|
|
? (error as { message?: unknown }).message
|
|
: error
|
|
);
|
|
}
|
|
} catch {}
|
|
}
|
|
}
|
|
|
|
export function createStreamFailureFinalizers({
|
|
isFailureCompletionRecorded,
|
|
onStreamComplete,
|
|
persistFailureUsage,
|
|
onStreamFailure,
|
|
}: {
|
|
isFailureCompletionRecorded: () => boolean;
|
|
onStreamComplete: (payload: StreamCompletionPayload) => void;
|
|
persistFailureUsage: (status: number, errorCode?: string) => void;
|
|
onStreamFailure?: ((failure: StreamFailurePayload) => void) | null;
|
|
}) {
|
|
const handleStreamFailure = (failure: StreamFailurePayload) => {
|
|
const status = failure.status || HTTP_STATUS.BAD_GATEWAY;
|
|
const message = failure.message || "Upstream stream error";
|
|
const code = failure.code || failure.type || String(status);
|
|
|
|
if (!isFailureCompletionRecorded()) {
|
|
const errorBody = buildErrorBody(status, message);
|
|
onStreamComplete({
|
|
status,
|
|
usage: null,
|
|
responseBody: errorBody,
|
|
providerPayload: errorBody,
|
|
clientPayload: errorBody,
|
|
error: message,
|
|
errorCode: code,
|
|
ttft: 0,
|
|
});
|
|
}
|
|
|
|
persistFailureUsage(status, code);
|
|
try {
|
|
onStreamFailure?.(failure);
|
|
} catch {
|
|
// Best-effort fallback state update only.
|
|
}
|
|
return true;
|
|
};
|
|
|
|
let pipelineStreamFailureFinalized = false;
|
|
const onPipelineStreamError: PipelineStreamErrorHandler = ({ message, statusCode }) => {
|
|
if (pipelineStreamFailureFinalized) return true;
|
|
pipelineStreamFailureFinalized = true;
|
|
|
|
const status =
|
|
Number.isFinite(statusCode) && statusCode >= 400 && statusCode <= 599
|
|
? statusCode
|
|
: HTTP_STATUS.BAD_GATEWAY;
|
|
const normalizedMessage = message || "Upstream stream error";
|
|
const code = normalizedMessage.toLowerCase().includes("terminated")
|
|
? "stream_terminated"
|
|
: "stream_pipeline_error";
|
|
|
|
handleStreamFailure({
|
|
status,
|
|
message: normalizedMessage,
|
|
code,
|
|
type: "stream_error",
|
|
});
|
|
return true;
|
|
};
|
|
|
|
return { handleStreamFailure, onPipelineStreamError };
|
|
}
|