UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

119 lines (118 loc) 5.37 kB
import { C as parseStrictNonNegativeInteger, c as asFiniteNumberInRange } from "./number-coercion-CLj0HTDM.js"; //#region packages/ai/src/internal/retry-after.ts const HTTP_DATE_MONTH_INDEX = new Map([ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ].map((month, index) => [month, index])); const HTTP_DATE_SHORT_WEEKDAY_INDEX = new Map([ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ].map((weekday, index) => [weekday, index])); const HTTP_DATE_LONG_WEEKDAY_INDEX = new Map([ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ].map((weekday, index) => [weekday, index])); const IMF_FIXDATE_RE = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{2}):(\d{2}):(\d{2}) GMT$/; const OBSOLETE_RFC850_DATE_RE = /^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{2}):(\d{2}):(\d{2}) GMT$/; const OBSOLETE_ASCTIME_DATE_RE = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{2}| \d) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/; /** Parses the three HTTP-date forms accepted for Retry-After without Date.parse normalization. */ function parseRetryAfterHttpDateMs(value, nowMs = Date.now()) { const imfFixdate = IMF_FIXDATE_RE.exec(value); if (imfFixdate) return parseHttpDateComponentsMs({ weekday: HTTP_DATE_SHORT_WEEKDAY_INDEX.get(imfFixdate[1] ?? ""), year: Number.parseInt(imfFixdate[4] ?? "", 10), month: HTTP_DATE_MONTH_INDEX.get(imfFixdate[3] ?? ""), day: Number.parseInt(imfFixdate[2] ?? "", 10), hours: Number.parseInt(imfFixdate[5] ?? "", 10), minutes: Number.parseInt(imfFixdate[6] ?? "", 10), seconds: Number.parseInt(imfFixdate[7] ?? "", 10) }); const rfc850Date = OBSOLETE_RFC850_DATE_RE.exec(value); if (rfc850Date) { const now = new Date(nowMs); if (Number.isNaN(now.getTime())) return; const shortYear = Number.parseInt(rfc850Date[4] ?? "", 10); const candidateYear = Math.floor(now.getUTCFullYear() / 100) * 100 + shortYear; const components = { weekday: HTTP_DATE_LONG_WEEKDAY_INDEX.get(rfc850Date[1] ?? ""), month: HTTP_DATE_MONTH_INDEX.get(rfc850Date[3] ?? ""), day: Number.parseInt(rfc850Date[2] ?? "", 10), hours: Number.parseInt(rfc850Date[5] ?? "", 10), minutes: Number.parseInt(rfc850Date[6] ?? "", 10), seconds: Number.parseInt(rfc850Date[7] ?? "", 10) }; const candidate = parseHttpDateCalendarMs({ year: candidateYear, ...components }); if (candidate === void 0) return; return parseHttpDateComponentsMs({ year: candidate > Date.UTC(now.getUTCFullYear() + 50, now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds()) ? candidateYear - 100 : candidateYear, ...components }); } const asctimeDate = OBSOLETE_ASCTIME_DATE_RE.exec(value); if (asctimeDate) return parseHttpDateComponentsMs({ weekday: HTTP_DATE_SHORT_WEEKDAY_INDEX.get(asctimeDate[1] ?? ""), year: Number.parseInt(asctimeDate[7] ?? "", 10), month: HTTP_DATE_MONTH_INDEX.get(asctimeDate[2] ?? ""), day: Number.parseInt((asctimeDate[3] ?? "").trim(), 10), hours: Number.parseInt(asctimeDate[4] ?? "", 10), minutes: Number.parseInt(asctimeDate[5] ?? "", 10), seconds: Number.parseInt(asctimeDate[6] ?? "", 10) }); } function parseHttpDateComponentsMs(components) { const timestamp = parseHttpDateCalendarMs(components); if (timestamp === void 0) return; const weekdayTimestamp = components.seconds === 60 ? timestamp - 1e3 : timestamp; if (new Date(weekdayTimestamp).getUTCDay() !== components.weekday) return; return timestamp; } function parseHttpDateCalendarMs(components) { const { year, month, day, hours, minutes, seconds } = components; if (month === void 0 || !Number.isInteger(year) || year < 1900 || !Number.isInteger(day) || day < 1 || day > 31 || !Number.isInteger(hours) || hours < 0 || hours > 23 || !Number.isInteger(minutes) || minutes < 0 || minutes > 59 || !Number.isInteger(seconds) || seconds < 0 || seconds > 60) return; const calendarSecond = Math.min(seconds, 59); const timestamp = Date.UTC(year, month, day, hours, minutes, calendarSecond); const parsedDate = new Date(timestamp); if (parsedDate.getUTCFullYear() !== year || parsedDate.getUTCMonth() !== month || parsedDate.getUTCDate() !== day || parsedDate.getUTCHours() !== hours || parsedDate.getUTCMinutes() !== minutes || parsedDate.getUTCSeconds() !== calendarSecond) return; return seconds === 60 ? timestamp + 1e3 : timestamp; } //#endregion //#region src/infra/retry-after.ts const RETRY_AFTER_HEADER_DELAY_RE = /^\d+$/; const MAX_SAFE_RETRY_AFTER_SECONDS = Number.MAX_SAFE_INTEGER / 1e3; /** Parses an RFC Retry-After header as delay seconds or any valid HTTP-date form. */ function parseRetryAfterHeaderSeconds(value, now = Date.now()) { if (!value) return; const trimmed = value.trim(); if (RETRY_AFTER_HEADER_DELAY_RE.test(trimmed)) return asFiniteNumberInRange(parseStrictNonNegativeInteger(trimmed), { min: 0, max: MAX_SAFE_RETRY_AFTER_SECONDS }); if (!Number.isFinite(now)) return; const retryAt = parseRetryAfterHttpDateMs(trimmed, now); return retryAt === void 0 ? void 0 : Math.max(0, (retryAt - now) / 1e3); } //#endregion export { parseRetryAfterHeaderSeconds as t };