ai-chatbot/lib/ai/vip98k-reference-staging.ts

101 lines
2.7 KiB
TypeScript

import { isMediaInputFailure } from "@/lib/ai/runtime/request-failure-classification";
function parseUrl(value: string) {
try {
return new URL(String(value || "").trim());
} catch {
return null;
}
}
export function isUrlWithinPublicBase(mediaUrl: string, publicBaseUrl: string) {
const media = parseUrl(mediaUrl);
const base = parseUrl(publicBaseUrl);
if (!media || !base || media.host.toLowerCase() !== base.host.toLowerCase()) {
return false;
}
const basePath = base.pathname.replace(/\/+$/, "");
if (!basePath) return true;
return media.pathname === basePath || media.pathname.startsWith(`${basePath}/`);
}
export function shouldStageVip98kReferenceUrl(params: {
mediaUrl: string;
sourcePublicUrl: string;
targetPublicUrl?: string;
}) {
if (
params.targetPublicUrl &&
isUrlWithinPublicBase(params.mediaUrl, params.targetPublicUrl)
) {
return false;
}
return isUrlWithinPublicBase(params.mediaUrl, params.sourcePublicUrl);
}
export function getStorageObjectKeyFromPublicUrl(
mediaUrl: string,
publicBaseUrl: string,
) {
if (!isUrlWithinPublicBase(mediaUrl, publicBaseUrl)) return null;
const media = parseUrl(mediaUrl);
const base = parseUrl(publicBaseUrl);
if (!media || !base) return null;
const basePath = base.pathname.replace(/\/+$/, "");
const encodedKey = media.pathname.slice(basePath.length).replace(/^\/+/, "");
if (!encodedKey) return null;
try {
return decodeURIComponent(encodedKey);
} catch {
return encodedKey;
}
}
export function getVip98kStagedMediaRetryDelay(params: {
status: number;
message: string;
attempt: number;
maxAttempts: number;
stagedReferenceCount: number;
}) {
if (
params.status !== 400 ||
params.stagedReferenceCount < 1 ||
params.attempt >= params.maxAttempts ||
!isMediaInputFailure(params.message)
) {
return null;
}
return params.attempt * 20_000;
}
export function getVip98kSubmissionRetryDelay(params: {
status: number;
message: string;
attempt: number;
maxAttempts: number;
retryAfterMs?: number | null;
}) {
if (
params.status !== 503 ||
params.attempt >= params.maxAttempts ||
!/pending\s+safe\s+reconciliation/i.test(params.message)
) {
return null;
}
const providerDelay = Number(params.retryAfterMs);
if (Number.isFinite(providerDelay) && providerDelay > 0) {
return Math.min(Math.max(providerDelay, 1_000), 60_000);
}
return Math.min(params.attempt * 15_000, 30_000);
}
export function addVip98kReferenceRetryToken(mediaUrl: string, token: string) {
const parsed = parseUrl(mediaUrl);
if (!parsed) return mediaUrl;
parsed.searchParams.set("sg_media_retry", token);
return parsed.toString();
}