* fix: add support for custom provider base URLs from config * feat: read custom provider apiKey from config and use it as primary credential when it exists * doc: update small-model documentation
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { readAuthFile, writeAuthFile } from '../opencode/auth.js';
|
||||
import { readConfig } from '../opencode/shared.js';
|
||||
import { getCatalogProvider } from './catalog.js';
|
||||
import { getAuthEntryForProvider } from './resolve.js';
|
||||
|
||||
@@ -279,13 +280,41 @@ const callCodexResponses = async ({ accessToken, accountId, modelID, prompt, sys
|
||||
return result;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Custom provider configuration support
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const readProviderConfig = (workingDirectory, providerID) => {
|
||||
try {
|
||||
const config = readConfig(workingDirectory);
|
||||
const providerCfg = config?.provider?.[providerID];
|
||||
if (!providerCfg || typeof providerCfg !== 'object') return null;
|
||||
const baseURL = typeof providerCfg?.options?.baseURL === 'string' ? providerCfg.options.baseURL.trim() : null;
|
||||
const apiKey = typeof providerCfg?.options?.apiKey === 'string' ? providerCfg.options.apiKey.trim() : null;
|
||||
return {
|
||||
baseURL,
|
||||
// Shape the config-supplied key as a regular api-key auth entry so it
|
||||
// can win the precedence check below and flow through the dispatch's
|
||||
// `entry.type === 'api' ? entry.key : ...` branch unchanged.
|
||||
auth: apiKey ? { type: 'api', key: apiKey } : null,
|
||||
};
|
||||
} catch {
|
||||
// Provider config is non-essential — continue with catalog-only resolution.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Dispatch
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export async function callSmallModel({ auth, catalog, providerID, modelID, prompt, system, maxOutputTokens }) {
|
||||
export async function callSmallModel({ auth, catalog, workingDirectory, providerID, modelID, prompt, system, maxOutputTokens }) {
|
||||
const tokens = Number(maxOutputTokens) > 0 ? Number(maxOutputTokens) : DEFAULT_MAX_OUTPUT_TOKENS;
|
||||
const entry = getAuthEntryForProvider(auth, providerID);
|
||||
const providerConfig = readProviderConfig(workingDirectory, providerID);
|
||||
// Match OpenCode's resolveSDK precedence:
|
||||
// config provider.<id>.options.apiKey (providerConfig.auth) wins; the
|
||||
// auth.json entry is only a fallback.
|
||||
const entry = providerConfig?.auth || getAuthEntryForProvider(auth, providerID);
|
||||
if (!entry) {
|
||||
throw new Error(`No OpenCode login found for provider "${providerID}"`);
|
||||
}
|
||||
@@ -343,13 +372,21 @@ export async function callSmallModel({ auth, catalog, providerID, modelID, promp
|
||||
}
|
||||
|
||||
// Everything else: OpenAI-compatible chat completions against the catalog's
|
||||
// base URL for that provider (openai itself included).
|
||||
// base URL for that provider (openai itself included). When a custom provider
|
||||
// is not in the catalog (e.g. a user-configured OpenAI-compatible proxy),
|
||||
// fall back to its baseURL from the OpenCode provider config. The openai
|
||||
// provider also respects provider.openai.options.baseURL — OpenCode itself
|
||||
// uses the same config for all providers including openai.
|
||||
const provider = getCatalogProvider(catalog, providerID);
|
||||
const baseURL = providerID === 'openai'
|
||||
? 'https://api.openai.com/v1'
|
||||
: typeof provider?.api === 'string' && provider.api
|
||||
? provider.api
|
||||
: null;
|
||||
const providerConfigUrl = providerConfig?.baseURL;
|
||||
const defaultOpenaiUrl = 'https://api.openai.com/v1';
|
||||
const baseURL = typeof providerConfigUrl === 'string' && providerConfigUrl
|
||||
? providerConfigUrl
|
||||
: providerID === 'openai'
|
||||
? defaultOpenaiUrl
|
||||
: typeof provider?.api === 'string' && provider.api
|
||||
? provider.api
|
||||
: null;
|
||||
if (!baseURL) {
|
||||
throw new Error(`Provider "${providerID}" has no known API base URL`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user