fix(auth): return synthetic credentials for noAuth free providers

Requests to opencode (noAuth: true) were failing with "No credentials for
provider: opencode" because getProviderCredentials found no DB connections and
returned null — triggering the 400 error path in chatHelpers.

Inject a synthetic credential object (connectionId: "noauth", no apiKey/token)
before the regular connection lookup so the executor receives valid credentials
and skips the Authorization header. Also enable model import for noAuth providers
(canImportModels = true when isFreeNoAuth).
This commit is contained in:
diegosouzapw
2026-05-16 21:31:03 -03:00
parent 42011abc69
commit 7fdcba9e05
2 changed files with 25 additions and 2 deletions

View File

@@ -2542,7 +2542,7 @@ export default function ProviderDetailPage() {
}
};
const canImportModels = connections.some((conn) => conn.isActive !== false);
const canImportModels = isFreeNoAuth || connections.some((conn) => conn.isActive !== false);
// Auto-sync toggle state: read from first active connection's providerSpecificData
const autoSyncConnection = connections.find((conn: any) => conn.isActive !== false);

View File

@@ -37,7 +37,7 @@ import {
PROVIDER_ERROR_TYPES,
} from "@omniroute/open-sse/services/errorClassifier.ts";
import { getCodexModelScope } from "@omniroute/open-sse/executors/codex.ts";
import { getProviderAlias, resolveProviderId } from "@/shared/constants/providers";
import { getProviderAlias, resolveProviderId, FREE_PROVIDERS } from "@/shared/constants/providers";
import { isModelExcludedByConnection } from "@/domain/connectionModelRules";
import * as log from "../utils/logger";
import { fisherYatesShuffle, getNextFromDeckSync } from "@/shared/utils/shuffleDeck";
@@ -770,6 +770,29 @@ export async function getProviderCredentials(
try {
await currentMutex;
// noAuth free providers (e.g. opencode) need no DB connection — return synthetic credentials
// so the executor receives a valid credentials object without auth headers being added.
const resolvedId = resolveProviderId(provider);
if (FREE_PROVIDERS[resolvedId]?.noAuth) {
return {
apiKey: null,
accessToken: null,
refreshToken: null,
expiresAt: null,
projectId: null,
copilotToken: null,
providerSpecificData: {},
connectionId: "noauth",
testStatus: "active",
lastError: null,
lastErrorType: null,
lastErrorSource: null,
errorCode: null,
rateLimitedUntil: null,
maxConcurrent: null,
};
}
const allowSuppressedConnections = options.allowSuppressedConnections === true;
const bypassQuotaPolicy = options.bypassQuotaPolicy === true;
const forcedConnectionId =