# 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:
decolua
2026-05-26 12:46:30 +07:00
parent f3176b4b23
commit 0065bbbdfd
9 changed files with 74 additions and 143 deletions
+8 -7
View File
@@ -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();