Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/app/settings/settings.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ export class SettingsPage {
this.settings.cloud_ai_api_key = '';
this.settings.cloud_ai_model = '';
this.settings.cloud_ai_base_url = '';
this.settings.cloud_ai_model_supports_temperature = null;
this.saveSettings();
}

Expand Down Expand Up @@ -619,6 +620,11 @@ export class SettingsPage {
const { data } = await modal.onWillDismiss();
if (data?.modelId) {
this.settings.cloud_ai_model = data.modelId;
// Capability advertised by the provider (OpenRouter); null when unknown.
this.settings.cloud_ai_model_supports_temperature =
typeof data.supportsTemperature === 'boolean'
? data.supportsTemperature
: null;
this.saveSettings();
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/classes/settings/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ export class Settings implements ISettings {
public cloud_ai_api_key: string;
public cloud_ai_model: string;
public cloud_ai_base_url: string;
public cloud_ai_model_supports_temperature: boolean | null;

public show_backup_issues: boolean;

Expand Down Expand Up @@ -612,6 +613,7 @@ export class Settings implements ISettings {
this.cloud_ai_api_key = '';
this.cloud_ai_model = '';
this.cloud_ai_base_url = '';
this.cloud_ai_model_supports_temperature = null;

this.show_backup_issues = true;

Expand Down Expand Up @@ -714,6 +716,12 @@ export class Settings implements ISettings {
} else {
this.cloud_ai_base_url = settingsObj.cloud_ai_base_url;
}
if (typeof settingsObj.cloud_ai_model_supports_temperature === 'boolean') {
this.cloud_ai_model_supports_temperature =
settingsObj.cloud_ai_model_supports_temperature;
} else {
this.cloud_ai_model_supports_temperature = null;
}
}

public resetBeanFilter() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export class CloudModelPickerComponent implements OnInit {

selectModel(model: CloudModel): void {
void this.modalCtrl.dismiss(
{ modelId: model.id },
{ modelId: model.id, supportsTemperature: model.supportsTemperature },
'confirm',
CloudModelPickerComponent.COMPONENT_ID,
);
Expand Down
3 changes: 3 additions & 0 deletions src/interfaces/settings/iSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ export interface ISettings {
cloud_ai_api_key: string;
cloud_ai_model: string;
cloud_ai_base_url: string;
// Whether the selected model accepts an explicit temperature, when the
// provider advertises it (OpenRouter). null = unknown, decided at runtime.
cloud_ai_model_supports_temperature: boolean | null;

show_backup_issues: boolean;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,51 @@ describe('cloud-model-list.service', () => {
expect(gpt4o.contextLength).toBe(128000);
expect(claude.contextLength).toBe(200000);
});

it('should derive supportsTemperature from supported_parameters', async () => {
// Arrange
fetchSpy.and.returnValue(
Promise.resolve(
mockFetchResponse({
data: [
{
id: 'openai/gpt-4o',
name: 'GPT-4o',
supported_parameters: ['temperature', 'top_p', 'tools'],
},
{
id: 'openai/gpt-5.6-terra',
name: 'GPT-5.6 Terra',
supported_parameters: ['top_p', 'tools'],
},
{
id: 'some/model-without-metadata',
name: 'No Metadata',
},
],
}),
),
);

// Act
const models = await fetchAvailableModels(
AI_PROVIDER_ENUM.OPENROUTER,
'',
);

// Assert
expect(
models.find((m) => m.id === 'openai/gpt-4o').supportsTemperature,
).toBe(true);
expect(
models.find((m) => m.id === 'openai/gpt-5.6-terra').supportsTemperature,
).toBe(false);
// No supported_parameters advertised → unknown, left undefined.
expect(
models.find((m) => m.id === 'some/model-without-metadata')
.supportsTemperature,
).toBeUndefined();
});
});

describe('OpenAI', () => {
Expand Down
4 changes: 4 additions & 0 deletions src/services/aiBeanImport/cloud-field-extraction.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ export class CloudFieldExtractionService {
apiKey: settings.cloud_ai_api_key,
model: settings.cloud_ai_model,
baseUrl: settings.cloud_ai_base_url || undefined,
// Skip the first (doomed) attempt when the provider already told us the
// model rejects an explicit temperature.
supportsTemperature:
settings.cloud_ai_model_supports_temperature ?? undefined,
};
}

Expand Down
7 changes: 7 additions & 0 deletions src/services/aiBeanImport/cloud-model-list.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ export interface CloudModel {
id: string;
name: string;
contextLength?: number;
// Whether the model accepts an explicit `temperature`, when the provider
// advertises it (OpenRouter's supported_parameters). undefined = unknown.
supportsTemperature?: boolean;
}

const TIMEOUT_MS = 15000;
Expand Down Expand Up @@ -42,6 +45,7 @@ interface RawOpenRouterModel {
id: string;
name?: string;
context_length?: number;
supported_parameters?: string[];
}

interface RawCustomModel {
Expand Down Expand Up @@ -167,6 +171,9 @@ function buildProviderConfig(
id: m.id,
name: m.name ?? m.id,
contextLength: m.context_length,
supportsTemperature: Array.isArray(m.supported_parameters)
? m.supported_parameters.includes('temperature')
: undefined,
};
},
};
Expand Down
Loading