mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-26 09:02:11 +03:00
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host. Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean. Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
73 lines
2.3 KiB
JavaScript
73 lines
2.3 KiB
JavaScript
import http from "node:http";
|
|
import net from "node:net";
|
|
|
|
const listenPort = 9223;
|
|
const upstreamHost = "127.0.0.1";
|
|
const upstreamPort = 9222;
|
|
|
|
function proxyHeaders(headers) {
|
|
const next = { ...headers, host: `${upstreamHost}:${upstreamPort}` };
|
|
delete next.connection;
|
|
delete next.upgrade;
|
|
return next;
|
|
}
|
|
|
|
const server = http.createServer((request, response) => {
|
|
const upstream = http.request(
|
|
{
|
|
host: upstreamHost,
|
|
port: upstreamPort,
|
|
method: request.method,
|
|
path: request.url,
|
|
headers: proxyHeaders(request.headers),
|
|
},
|
|
(upstreamResponse) => {
|
|
const chunks = [];
|
|
upstreamResponse.on("data", (chunk) => chunks.push(chunk));
|
|
upstreamResponse.on("end", () => {
|
|
let body = Buffer.concat(chunks);
|
|
const contentType = String(upstreamResponse.headers["content-type"] || "");
|
|
if (contentType.includes("application/json")) {
|
|
body = Buffer.from(
|
|
body
|
|
.toString("utf8")
|
|
.replaceAll(`ws://${upstreamHost}:${upstreamPort}`, `ws://${request.headers.host}`)
|
|
);
|
|
}
|
|
const headers = { ...upstreamResponse.headers, "content-length": String(body.length) };
|
|
response.writeHead(upstreamResponse.statusCode || 502, headers);
|
|
response.end(body);
|
|
});
|
|
}
|
|
);
|
|
upstream.on("error", () => {
|
|
response.writeHead(503, { "content-type": "application/json" });
|
|
response.end(JSON.stringify({ error: "CDP browser is starting" }));
|
|
});
|
|
request.pipe(upstream);
|
|
});
|
|
|
|
server.on("upgrade", (request, socket, head) => {
|
|
const upstream = net.connect(upstreamPort, upstreamHost, () => {
|
|
const upgradeHeaders = {
|
|
...request.headers,
|
|
host: `${upstreamHost}:${upstreamPort}`,
|
|
connection: "Upgrade",
|
|
upgrade: "websocket",
|
|
};
|
|
const headers = Object.entries(upgradeHeaders)
|
|
.flatMap(([name, value]) =>
|
|
Array.isArray(value) ? value.map((item) => `${name}: ${item}`) : [`${name}: ${value}`]
|
|
)
|
|
.join("\r\n");
|
|
upstream.write(
|
|
`${request.method} ${request.url} HTTP/${request.httpVersion}\r\n${headers}\r\n\r\n`
|
|
);
|
|
if (head.length > 0) upstream.write(head);
|
|
socket.pipe(upstream).pipe(socket);
|
|
});
|
|
upstream.on("error", () => socket.destroy());
|
|
});
|
|
|
|
server.listen(listenPort, "0.0.0.0");
|