mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
# v0.4.62 (2026-05-26)
## Fixes - Codex: auto-retry when upstream drops mid-stream (no more hangs) - Codex: fix random 400/404 errors, tool-calling failures, and unstable prompt cache - MITM: support Antigravity 2.x (updated IDE version detection and DNS/cert flow) - Sanitize Read tool args to prevent retry loops from non-Anthropic models (#1144) - Implement json_schema fallback for OpenAI-compatible providers without native Structured Output (#1343) - Strip empty Read pages argument in OpenAI-to-Claude translator (#1354) - Forward Gemini output dimensions for embeddings (#1366) - Resolve setState-in-effect errors in dashboard components (#1362) - Gemini CLI: reuse stored OAuth project IDs for quota checks and show clearer setup guidance when the project is missing (#1271, #1428)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Readable } from "stream";
|
||||
// import { Readable } from "stream"; // unused — re-enable with got-scraping block below
|
||||
import { MEMORY_CONFIG } from "../config/runtimeConfig.js";
|
||||
import { dbg } from "./debugLog.js";
|
||||
|
||||
@@ -6,8 +6,9 @@ const originalFetch = globalThis.fetch;
|
||||
const proxyDispatchers = new Map();
|
||||
|
||||
// ─── TLS fingerprinting via got-scraping (browser-like JA3) ───────────────
|
||||
// Lazy-loaded once; if import fails (missing optional native deps in some
|
||||
// envs) we silently fall back to native fetch — no behavioral change.
|
||||
// Disabled: not in use. Kept commented for future re-enable.
|
||||
// Restore the original block to re-enable per-host JA3 spoofing.
|
||||
/*
|
||||
let _gotScraping = null;
|
||||
let _gotScrapingChecked = false;
|
||||
const _gotScrapingLoggedHosts = new Set();
|
||||
@@ -26,7 +27,6 @@ async function getGotScraping() {
|
||||
return _gotScraping;
|
||||
}
|
||||
|
||||
// Run a request through got-scraping streaming, return a fetch-compatible Response
|
||||
async function gotScrapingFetch(url, options) {
|
||||
const gs = await getGotScraping();
|
||||
if (!gs) return null;
|
||||
@@ -46,13 +46,13 @@ async function gotScrapingFetch(url, options) {
|
||||
body: method === "GET" || method === "HEAD" ? undefined : options.body,
|
||||
throwHttpErrors: false,
|
||||
retry: { limit: 0 },
|
||||
timeout: { request: undefined }, // streaming → no overall timeout
|
||||
timeout: { request: undefined },
|
||||
followRedirect: false,
|
||||
decompress: true,
|
||||
});
|
||||
|
||||
if (options.signal) {
|
||||
const onAbort = () => { try { stream.destroy(new Error("aborted")); } catch { /* noop */ } };
|
||||
const onAbort = () => { try { stream.destroy(new Error("aborted")); } catch { } };
|
||||
if (options.signal.aborted) onAbort();
|
||||
else options.signal.addEventListener("abort", onAbort, { once: true });
|
||||
}
|
||||
@@ -87,7 +87,7 @@ async function tryGotScrapingFetch(url, options) {
|
||||
_gotScrapingLoggedHosts.add(host);
|
||||
dbg("TLS", `using got-scraping for ${host}`);
|
||||
}
|
||||
} catch { /* noop */ }
|
||||
} catch { }
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
@@ -95,6 +95,7 @@ async function tryGotScrapingFetch(url, options) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// DNS cache — use Map to avoid prototype pollution via malformed hostnames
|
||||
const DNS_CACHE = new Map();
|
||||
|
||||
Reference in New Issue
Block a user