You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
2.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/** 报价完成信号等待上限(毫秒) */
export const RPA_QUOTE_CAPTURE_TIMEOUT_MS = 25_000;
/** 提交后额外收集契约响应的短暂窗口(毫秒) */
export const RPA_QUOTE_POST_SUBMIT_SETTLE_MS = 2_000;
/** sign-up-quote 结果页 widget 拉价等待(毫秒)— 须等 axel/quote 响应,不可盲目缩短 */
export const RPA_SIGN_UP_QUOTE_SETTLE_MS = 18_000;
const IGNORE_URL_FRAGMENTS = [
"segment.io",
"segment.com",
"google-analytics",
"googletagmanager",
"facebook.net",
"hotjar",
"sentry.io",
"fullstory",
"intercom",
".png",
".jpg",
".css",
".woff",
".woff2",
".js",
".map",
] as const;
function isJsonContentType(contentType: string): boolean {
const ct = contentType.toLowerCase();
return (
ct.includes("json") ||
ct.includes("application/graphql") ||
ct.includes("text/plain")
);
}
/** axel/quote 白名单阶段0 录证) */
export { AXEL_QUOTE_URL_FRAGMENT, isAxelQuoteResponseUrl } from "@/workers/rpa/quote-capture/axel-contract";
export function isJsonNetworkCandidate(url: string, contentType: string): boolean {
const lower = url.toLowerCase();
if (IGNORE_URL_FRAGMENTS.some((frag) => lower.includes(frag))) {
return false;
}
return isJsonContentType(contentType);
}
/** HAR 校准辅助:逗号分隔 URL 子串或 /regex/flags仅 telemetry不参与 runtime */
export function parsePinnedQuoteApiPatterns(): RegExp[] {
const raw = process.env.MOTHERSHIP_QUOTE_API_URL_PATTERNS?.trim();
if (!raw) {
return [];
}
const patterns: RegExp[] = [];
for (const part of raw.split(",").map((s) => s.trim()).filter(Boolean)) {
const slash = part.match(/^\/(.+)\/([a-z]*)$/i);
if (slash) {
patterns.push(new RegExp(slash[1], slash[2] || "i"));
continue;
}
const escaped = part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
patterns.push(new RegExp(escaped, "i"));
}
return patterns;
}
/** debug契约命中 URL 与 HAR pinned 是否一致(不参与决策) */
export function formatPinnedTelemetry(url: string): string {
const pinned = parsePinnedQuoteApiPatterns();
if (pinned.length === 0) {
return "pinned=未配置";
}
const matched = pinned.some((p) => p.test(url));
return matched ? "pinned=match" : "pinned=miss";
}