mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-17 20:32:25 +03:00
fix(opencode): hydrate Proxy Pool references for no-auth connections (#11584)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
This commit is contained in:
@@ -1128,13 +1128,40 @@ function planLastUsedCommit(
|
||||
};
|
||||
}
|
||||
|
||||
function materializeConnection(
|
||||
/**
|
||||
* Resolve Proxy Pool references on a real connection row at the same boundary
|
||||
* where credentials become request-ready. The synthetic no-auth fallback above
|
||||
* already performs this hydration, but a persisted connection (for example the
|
||||
* OpenCode card's `opencode` row selected through the `opencode-zen` alias)
|
||||
* bypasses that fallback. Keep inline/legacy entries untouched and only incur a
|
||||
* registry lookup when at least one by-id reference is present.
|
||||
*/
|
||||
async function hydrateAccountProxyReferences(
|
||||
providerSpecificData: JsonRecord
|
||||
): Promise<JsonRecord> {
|
||||
const entries = providerSpecificData.accountProxies;
|
||||
if (!Array.isArray(entries)) return providerSpecificData;
|
||||
|
||||
const containsProxyReference = entries.some((entry) => {
|
||||
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
|
||||
const proxyId = (entry as Record<string, unknown>).proxyId;
|
||||
return typeof proxyId === "string" && proxyId.trim().length > 0;
|
||||
});
|
||||
if (!containsProxyReference) return providerSpecificData;
|
||||
|
||||
return {
|
||||
...providerSpecificData,
|
||||
accountProxies: await resolveAccountProxiesFromRegistry(entries),
|
||||
};
|
||||
}
|
||||
|
||||
async function materializeConnection(
|
||||
connection: ProviderConnectionView,
|
||||
options: CredentialSelectionOptions,
|
||||
extra: DeferredLeaseSelection & { exclusiveLease?: ExclusiveConnectionLease } = {}
|
||||
) {
|
||||
const apiKeyHealth = connection.providerSpecificData?.apiKeyHealth as
|
||||
Record<string, KeyHealth> | undefined;
|
||||
const providerSpecificData = await hydrateAccountProxyReferences(connection.providerSpecificData);
|
||||
const apiKeyHealth = providerSpecificData.apiKeyHealth as Record<string, KeyHealth> | undefined;
|
||||
if (apiKeyHealth) syncHealthFromDB(connection.id, apiKeyHealth);
|
||||
const releaseOAuthSession =
|
||||
options.reserveOAuthSession === true && connection.authType === "oauth" && options.sessionKey
|
||||
@@ -1148,10 +1175,10 @@ function materializeConnection(
|
||||
projectId: connection.projectId,
|
||||
defaultModel: connection.defaultModel || null,
|
||||
copilotToken:
|
||||
typeof connection.providerSpecificData.copilotToken === "string"
|
||||
? connection.providerSpecificData.copilotToken
|
||||
typeof providerSpecificData.copilotToken === "string"
|
||||
? providerSpecificData.copilotToken
|
||||
: null,
|
||||
providerSpecificData: connection.providerSpecificData,
|
||||
providerSpecificData,
|
||||
id: connection.id,
|
||||
provider: connection.provider,
|
||||
authType: connection.authType,
|
||||
|
||||
@@ -27,6 +27,7 @@ process.env.DATA_DIR = TEST_DATA_DIR;
|
||||
const core = await import("../../src/lib/db/core.ts");
|
||||
const { getProviderCredentials } = await import("../../src/sse/services/auth.ts");
|
||||
const { createProviderConnection } = await import("../../src/lib/db/providers.ts");
|
||||
const { createProxy } = await import("../../src/lib/db/proxies.ts");
|
||||
const { OpencodeExecutor } = await import("../../open-sse/executors/opencode.ts");
|
||||
const { resolveProxyForRequest } = await import("../../open-sse/utils/proxyFetch.ts");
|
||||
|
||||
@@ -47,10 +48,17 @@ function listen(server: net.Server): Promise<number> {
|
||||
test.before(async () => {
|
||||
proxyServer = net.createServer((s) => s.destroy());
|
||||
proxyPort = await listen(proxyServer);
|
||||
const proxy = await createProxy({
|
||||
name: "opencode-noauth-test-proxy",
|
||||
type: "http",
|
||||
host: "127.0.0.1",
|
||||
port: proxyPort,
|
||||
});
|
||||
assert.ok(proxy?.id, "test proxy must be persisted in the registry");
|
||||
|
||||
// Mirror exactly what the NoAuthAccountCard UI writes: a `provider_connections`
|
||||
// row filed under the no-auth id "opencode" (NOT "opencode-zen"), carrying the
|
||||
// configured account proxy.
|
||||
// configured account proxy as a Proxy Pool reference.
|
||||
await createProviderConnection({
|
||||
provider: "opencode",
|
||||
authType: "no-auth",
|
||||
@@ -61,7 +69,7 @@ test.before(async () => {
|
||||
accountProxies: [
|
||||
{
|
||||
fingerprint: FINGERPRINT,
|
||||
proxy: { type: "http", host: "127.0.0.1", port: proxyPort },
|
||||
proxyId: proxy.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -95,6 +103,17 @@ test("#7993 getProviderCredentials('opencode-zen') hydrates the proxy saved unde
|
||||
Array.isArray(psd.accountProxies) && psd.accountProxies.length === 1,
|
||||
`expected the sibling opencode connection's accountProxies to be hydrated, got ${JSON.stringify(psd)}`
|
||||
);
|
||||
const accountProxy = (psd.accountProxies as Array<Record<string, unknown>>)[0];
|
||||
assert.equal(
|
||||
accountProxy.proxyId,
|
||||
undefined,
|
||||
"request credentials must not retain a raw proxyId"
|
||||
);
|
||||
assert.deepEqual(accountProxy.proxy, {
|
||||
type: "http",
|
||||
host: "127.0.0.1",
|
||||
port: proxyPort,
|
||||
});
|
||||
});
|
||||
|
||||
test("#7993 a canonical 'opencode/<model>' resolved combo/catalog target egresses through the assigned proxy, not direct", async () => {
|
||||
|
||||
Reference in New Issue
Block a user