Fix model selector not showing models with settings.json API keys

Fixes #295
This commit is contained in:
Mario Zechner 2025-12-24 21:23:44 +01:00
parent a96b9201f9
commit ac5f4a77cc
8 changed files with 357 additions and 249 deletions

View file

@ -616,7 +616,9 @@ export class AgentSession {
}
private async _cycleAvailableModel(): Promise<ModelCycleResult | null> {
const { models: availableModels, error } = await getAvailableModels();
const { models: availableModels, error } = await getAvailableModels(undefined, (provider) =>
this.settingsManager.getApiKey(provider),
);
if (error) throw new Error(`Failed to load models: ${error}`);
if (availableModels.length <= 1) return null;
@ -648,7 +650,9 @@ export class AgentSession {
* Get all available models with valid API keys.
*/
async getAvailableModels(): Promise<Model<any>[]> {
const { models, error } = await getAvailableModels();
const { models, error } = await getAvailableModels(undefined, (provider) =>
this.settingsManager.getApiKey(provider),
);
if (error) throw new Error(error);
return models;
}
@ -1330,7 +1334,9 @@ export class AgentSession {
// Restore model if saved
if (sessionContext.model) {
const availableModels = (await getAvailableModels()).models;
const availableModels = (
await getAvailableModels(undefined, (provider) => this.settingsManager.getApiKey(provider))
).models;
const match = availableModels.find(
(m) => m.provider === sessionContext.model!.provider && m.id === sessionContext.model!.modelId,
);

View file

@ -358,9 +358,14 @@ export async function getApiKeyForModel(model: Model<Api>): Promise<string | und
/**
* Get only models that have valid API keys available
* Returns { models, error } - either models array or error message
*
* @param agentDir - Agent config directory
* @param fallbackKeyResolver - Optional function to check for API keys not found by getApiKeyForModel
* (e.g., keys from settings.json)
*/
export async function getAvailableModels(
agentDir: string = getAgentDir(),
fallbackKeyResolver?: (provider: string) => string | undefined,
): Promise<{ models: Model<Api>[]; error: string | null }> {
const { models: allModels, error } = loadAndMergeModels(agentDir);
@ -370,7 +375,11 @@ export async function getAvailableModels(
const availableModels: Model<Api>[] = [];
for (const model of allModels) {
const apiKey = await getApiKeyForModel(model);
let apiKey = await getApiKeyForModel(model);
// Check fallback resolver if primary lookup failed
if (!apiKey && fallbackKeyResolver) {
apiKey = fallbackKeyResolver(model.provider);
}
if (apiKey) {
availableModels.push(model);
}

View file

@ -167,9 +167,15 @@ export function parseModelPattern(pattern: string, availableModels: Model<Api>[]
* Supports models with colons in their IDs (e.g., OpenRouter's model:exacto).
* The algorithm tries to match the full pattern first, then progressively
* strips colon-suffixes to find a match.
*
* @param patterns - Model patterns to resolve
* @param settingsManager - Optional settings manager for API key fallback from settings.json
*/
export async function resolveModelScope(patterns: string[]): Promise<ScopedModel[]> {
const { models: availableModels, error } = await getAvailableModels();
export async function resolveModelScope(patterns: string[], settingsManager?: SettingsManager): Promise<ScopedModel[]> {
const { models: availableModels, error } = await getAvailableModels(
undefined,
settingsManager ? (provider) => settingsManager.getApiKey(provider) : undefined,
);
if (error) {
console.warn(chalk.yellow(`Warning: Error loading models: ${error}`));
@ -269,7 +275,9 @@ export async function findInitialModel(options: {
}
// 4. Try first available model with valid API key
const { models: availableModels, error } = await getAvailableModels();
const { models: availableModels, error } = await getAvailableModels(undefined, (provider) =>
settingsManager.getApiKey(provider),
);
if (error) {
console.error(chalk.red(error));
@ -302,6 +310,7 @@ export async function restoreModelFromSession(
savedModelId: string,
currentModel: Model<Api> | null,
shouldPrintMessages: boolean,
settingsManager?: SettingsManager,
): Promise<{ model: Model<Api> | null; fallbackMessage: string | null }> {
const { model: restoredModel, error } = findModel(savedProvider, savedModelId);
@ -339,7 +348,10 @@ export async function restoreModelFromSession(
}
// Try to find any available model
const { models: availableModels, error: availableError } = await getAvailableModels();
const { models: availableModels, error: availableError } = await getAvailableModels(
undefined,
settingsManager ? (provider) => settingsManager.getApiKey(provider) : undefined,
);
if (availableError) {
console.error(chalk.red(availableError));
process.exit(1);