mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-13 18:32:12 +03:00
Migrates the Claude, Grok, LMArena, Notion and Perplexity web-cookie transports from the tls-client-node/Koffi sidecar to the exactly pinned wreq-js 3.2.0 runtime, keeping the per-provider browser/OS profiles, making request cookies ephemeral, bounding and generation-protecting the shared native transport pool, removing the legacy downloader and repair path, and carrying the native binding and license evidence through the npm, standalone, Electron, Docker and Bun packaging surfaces. This is the consolidation of the two competing migrations, and the consolidation was decided by evidence rather than by preference. #11753's six suites were installed over this implementation and run as an independent specification: 31 of 36 passed. All five failures are artefacts of #11753 being the older design, not coverage gaps — - two hardcode the 3.0.0 pin in their assertions (this branch pins 3.2.0, which is what the release tip already resolves; #11753's 3.0.0 would have conflicted); - one reads open-sse/services/chatgptTlsClient.ts, deleted when #11754 retired ChatGPT Web, so the test is stale against the current tip; - two import WREQ_JS_NATIVE_BINARY_NAMES / resolveWreqJsNativeBinaryName, which this branch redesigned into WREQ_JS_NATIVE_BINDINGS / resolveWreqJsNativeBinding plus WREQ_JS_VERSION — a rename from modelling natives as file names to modelling them as package bindings, verified as an API difference rather than a lost capability (the linux-x64-gnu .node is present and serviceable). This branch is also the strict superset by scope: 7 files exclusive to it, including the wreq-js Rust license inventory and notices, .trivyignore, open-sse/utils/tlsClient.ts and assembleStandalone.mjs. #11753 had one exclusive file, its changelog fragment. Nothing needed porting, so #11753 is superseded rather than merged, and the changelog entry credits both. Reconciled on merge: clean against the tip. The new migration suite (tests/unit/tls-client-wreq-migration.test.ts, 1374 lines, 31 cases) is frozen at its exact LOC with the rationale — it shares one native-transport harness, so splitting it mid-merge would duplicate that harness for no coverage gain. Verified that no existing cap moves. Verified: 182/182 across the eight TLS, native-manifest, postinstall, standalone-bundle, pack-artifact and provider-validation suites, typecheck:core clean, check:cycles OK, check-changelog-integrity OK, check-file-size OK, and every changed TypeScript file parses.
149 lines
5.0 KiB
JavaScript
149 lines
5.0 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Platform hydration for the shared Next standalone web build (issue #10321,
|
|
* Stage 8).
|
|
*
|
|
* The standalone bundle is built ONCE on ubuntu and restored on every desktop
|
|
* matrix leg. Everything except install-machine-forked optional packages is
|
|
* platform-independent:
|
|
*
|
|
* - Bundled-for-all (verify only): better-sqlite3 v13 ships Node-API prebuilds
|
|
* for 8 platforms, and onnxruntime-node ships `bin/napi-v6/<os>/<arch>`.
|
|
* - Install-machine-forked (hydrate): `@img/sharp-*`, `@img/sharp-libvips-*`,
|
|
* `@ngrok/ngrok-*`, `@wreq-js/binding-*`, and macOS-only `fsevents` resolve
|
|
* to whichever platform ran `npm ci`. The ubuntu-built tree carries the
|
|
* linux forks; each leg replaces them with the forks from its OWN install.
|
|
*/
|
|
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
import { resolveWreqJsNativeBinding } from "./wreqJsNative.mjs";
|
|
|
|
/** Scope prefixes whose members are install-machine-forked. */
|
|
export const HYDRATED_SCOPES = [
|
|
"@img/sharp-",
|
|
"@img/sharp-libvips-",
|
|
"@ngrok/ngrok-",
|
|
"@wreq-js/binding-",
|
|
];
|
|
|
|
/** Standalone packages that are not forked but must never be platform-forked. */
|
|
export const HYDRATED_ROOT_PACKAGES = ["fsevents"];
|
|
|
|
/**
|
|
* onnxruntime-node does not publish a darwin-x64 binary for napi-v6 (only
|
|
* linux/win32 x64 + darwin arm64), so existence cannot be asserted there.
|
|
*/
|
|
export const BUNDLED_EXEMPTIONS = new Set(["onnxruntime-node:darwin-x64"]);
|
|
|
|
function platformTriple(platform, arch) {
|
|
return { dash: `${platform}-${arch}` };
|
|
}
|
|
|
|
function rmrf(target) {
|
|
fs.rmSync(target, { recursive: true, force: true });
|
|
}
|
|
|
|
function copyDir(from, to) {
|
|
fs.cpSync(from, to, { recursive: true, verbatimSymlinks: false, force: true });
|
|
}
|
|
|
|
function directMemberNames(nodeModulesDir, scope) {
|
|
const scopeDir = path.join(nodeModulesDir, ...scope.split("/").slice(0, -1));
|
|
const prefix = scope.split("/").pop();
|
|
try {
|
|
return fs
|
|
.readdirSync(scopeDir)
|
|
.filter((name) => name.startsWith(prefix))
|
|
.map((name) => `${scope.slice(0, scope.lastIndexOf("/"))}/${name}`);
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Replace install-machine-forked packages inside the restored standalone tree
|
|
* with the forks resolved by THIS machine's node_modules.
|
|
*
|
|
* @param {{standaloneNodeModules: string, sourceNodeModules: string}} opts
|
|
* @returns {{replaced: string[], removed: string[], copied: string[]}}
|
|
*/
|
|
export function hydratePlatformNatives({ standaloneNodeModules, sourceNodeModules }) {
|
|
const replaced = [];
|
|
const removed = [];
|
|
const copied = [];
|
|
|
|
const forkedNames = new Set();
|
|
for (const scope of HYDRATED_SCOPES) {
|
|
for (const name of directMemberNames(sourceNodeModules, scope)) forkedNames.add(name);
|
|
for (const name of directMemberNames(standaloneNodeModules, scope)) forkedNames.add(name);
|
|
}
|
|
for (const pkg of HYDRATED_ROOT_PACKAGES) {
|
|
if (fs.existsSync(path.join(sourceNodeModules, pkg))) forkedNames.add(pkg);
|
|
if (fs.existsSync(path.join(standaloneNodeModules, pkg))) forkedNames.add(pkg);
|
|
}
|
|
|
|
for (const name of forkedNames) {
|
|
const standalonePath = path.join(standaloneNodeModules, ...name.split("/"));
|
|
const sourcePath = path.join(sourceNodeModules, ...name.split("/"));
|
|
const hadIt = fs.existsSync(standalonePath);
|
|
const hasIt = fs.existsSync(sourcePath);
|
|
if (hadIt) rmrf(standalonePath);
|
|
if (!hasIt) {
|
|
if (hadIt) removed.push(name);
|
|
continue; // e.g. fsevents on non-darwin legs: simply absent everywhere.
|
|
}
|
|
copyDir(sourcePath, standalonePath);
|
|
copied.push(name);
|
|
if (hadIt) replaced.push(name);
|
|
}
|
|
return { replaced, removed, copied };
|
|
}
|
|
|
|
/**
|
|
* Assert that every bundled native dependency can service `platform`/`arch`.
|
|
*
|
|
* @returns {{ok: true} | {ok: false, errors: string[]}}
|
|
*/
|
|
export function verifyBundledNatives({ nodeModulesDir, platform, arch }) {
|
|
const errors = [];
|
|
const triple = platformTriple(platform, arch);
|
|
|
|
const sqlitePrebuild = path.join(
|
|
nodeModulesDir,
|
|
"better-sqlite3",
|
|
"prebuilds",
|
|
`${triple.dash}.node`
|
|
);
|
|
if (!fs.existsSync(sqlitePrebuild))
|
|
errors.push(`better-sqlite3: missing prebuild ${triple.dash}.node`);
|
|
|
|
const wreqBinding = resolveWreqJsNativeBinding({
|
|
platform,
|
|
arch,
|
|
libc: platform === "linux" ? "gnu" : undefined,
|
|
});
|
|
if (!wreqBinding) {
|
|
errors.push(`wreq-js: unsupported target ${triple.dash}`);
|
|
} else {
|
|
const wreqBinary = path.join(
|
|
nodeModulesDir,
|
|
...wreqBinding.packageName.split("/"),
|
|
wreqBinding.fileName
|
|
);
|
|
if (!fs.existsSync(wreqBinary)) {
|
|
errors.push(`wreq-js: missing ${wreqBinding.packageName}/${wreqBinding.fileName}`);
|
|
}
|
|
}
|
|
|
|
const exempt = BUNDLED_EXEMPTIONS.has(`onnxruntime-node:${triple.dash}`);
|
|
if (!exempt) {
|
|
const onnxDir = path.join(nodeModulesDir, "onnxruntime-node", "bin", "napi-v6", platform, arch);
|
|
if (!fs.existsSync(onnxDir))
|
|
errors.push(`onnxruntime-node: missing ${platform}/${arch} binary`);
|
|
}
|
|
|
|
return errors.length === 0 ? { ok: true } : { ok: false, errors };
|
|
}
|