refactor: dynamically fetch available InferenceProviders for gui

This commit is contained in:
2026-07-10 15:38:08 +05:30
parent f88cc4efb4
commit d8d9015015
6 changed files with 79 additions and 9 deletions

View File

@@ -10,8 +10,9 @@ import {
getProviderMappings,
setProviderMapping,
updateProviderInstance,
getAvailableProviders,
} from "@/app/play/actions";
import type { LLMProviderInstance } from "@omnia/llm";
import type { LLMProviderInstance, LLMProviderMeta } from "@omnia/llm";
interface ConfigStatus {
apiKeySet: boolean;
@@ -24,6 +25,7 @@ export default function ConfigPage() {
const [config, setConfig] = useState<ConfigStatus | null>(null);
const [instances, setInstances] = useState<LLMProviderInstance[]>([]);
const [mappings, setMappings] = useState<Record<string, string>>({});
const [availableProviders, setAvailableProviders] = useState<LLMProviderMeta[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
@@ -37,9 +39,11 @@ export default function ConfigPage() {
useEffect(() => {
if (selectedInstanceId === "new") {
setEditName("");
setEditProvider("google-genai");
const defaultProvider = "google-genai";
setEditProvider(defaultProvider);
setEditKey("");
setEditModel("gemini-2.5-flash");
const pMeta = availableProviders.find((p) => p.id === defaultProvider);
setEditModel(pMeta?.defaultModel || "gemini-2.5-flash");
setEditIsActive(false);
} else {
const inst = instances.find((i) => i.id === selectedInstanceId);
@@ -47,11 +51,20 @@ export default function ConfigPage() {
setEditName(inst.name);
setEditProvider(inst.providerName);
setEditKey("");
setEditModel(inst.modelName || "gemini-2.5-flash");
const pMeta = availableProviders.find((p) => p.id === inst.providerName);
setEditModel(inst.modelName || pMeta?.defaultModel || "gemini-2.5-flash");
setEditIsActive(inst.isActive);
}
}
}, [selectedInstanceId, instances]);
}, [selectedInstanceId, instances, availableProviders]);
const handleProviderChange = (providerId: string) => {
setEditProvider(providerId);
const pMeta = availableProviders.find((p) => p.id === providerId);
if (pMeta) {
setEditModel(pMeta.defaultModel);
}
};
const loadInstances = useCallback(async () => {
try {
@@ -79,6 +92,8 @@ export default function ConfigPage() {
setConfig(result);
await loadInstances();
await loadMappings();
const provs = await getAvailableProviders();
setAvailableProviders(provs);
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
} finally {
@@ -231,11 +246,19 @@ export default function ConfigPage() {
<select
id="formProvider"
value={editProvider}
onChange={(e) => setEditProvider(e.target.value)}
onChange={(e) => handleProviderChange(e.target.value)}
>
<option value="google-genai">Google Gemini (Gemini-2.5-flash)</option>
<option value="mock">Mock LLM Provider</option>
{availableProviders.map((p) => (
<option key={p.id} value={p.id}>
{p.displayName}
</option>
))}
</select>
{editProvider && availableProviders.length > 0 && (
<span className="config-hint" style={{ marginTop: "0.25rem", background: "#f3f4f6", border: "1px solid #e5e7eb", color: "#4b5563" }}>
{availableProviders.find((p) => p.id === editProvider)?.description}
</span>
)}
</div>
<div className="form-group">

View File

@@ -4,7 +4,7 @@ import path from "path";
import fs from "fs";
import { simulationManager } from "@/lib/simulation";
import type { SimSnapshot } from "@/lib/simulation";
import { ProviderManager, LLMProviderInstance } from "@omnia/llm";
import { ProviderManager, LLMProviderInstance, AVAILABLE_PROVIDERS, LLMProviderMeta } from "@omnia/llm";
function resolveScenarioPath(relative: string): string {
const cwd = process.cwd();
@@ -274,3 +274,7 @@ export async function setProviderMapping(
): Promise<void> {
ProviderManager.setMapping(task, providerInstanceId);
}
export async function getAvailableProviders(): Promise<LLMProviderMeta[]> {
return AVAILABLE_PROVIDERS;
}

View File

@@ -45,3 +45,31 @@ export interface LLMProviderInstance {
isActive: boolean;
modelName?: string;
}
export interface LLMProviderMeta {
id: string;
displayName: string;
description: string;
defaultModel: string;
}
export const AVAILABLE_PROVIDERS: LLMProviderMeta[] = [
{
id: "google-genai",
displayName: "Google Gemini",
description: "Official Gemini integration using Google Gen AI SDK",
defaultModel: "gemini-2.5-flash",
},
{
id: "openrouter",
displayName: "OpenRouter",
description: "Multi-model router supporting Anthropic, OpenAI, DeepSeek, and local models",
defaultModel: "google/gemini-2.5-flash",
},
{
id: "mock",
displayName: "Mock LLM Provider",
description: "Stateless mock provider for testing and offline development",
defaultModel: "mock",
},
];

View File

@@ -5,6 +5,11 @@ import { llmConfig } from "../config.js";
import { ProviderManager } from "../provider-manager.js";
export class GeminiProvider implements ILLMProvider {
static readonly providerId = "google-genai";
static readonly displayName = "Google Gemini";
static readonly description = "Official Gemini integration using Google Gen AI SDK";
static readonly defaultModel = "gemini-2.5-flash";
providerName = "Gemini";
private model: ChatGoogleGenerativeAI;
lastCalls: LLMCallRecord[] = [];

View File

@@ -2,6 +2,11 @@ import { z } from "zod";
import { ILLMProvider, LLMRequest, LLMResponse, LLMCallRecord } from "../llm.js";
export class MockLLMProvider implements ILLMProvider {
static readonly providerId = "mock";
static readonly displayName = "Mock LLM Provider";
static readonly description = "Stateless mock provider for testing and offline development";
static readonly defaultModel = "mock";
providerName = "mock";
private callCount = 0;
lastCalls: LLMCallRecord[] = [];

View File

@@ -5,6 +5,11 @@ import { llmConfig } from "../config.js";
import { ProviderManager } from "../provider-manager.js";
export class OpenRouterProvider implements ILLMProvider {
static readonly providerId = "openrouter";
static readonly displayName = "OpenRouter";
static readonly description = "Multi-model router supporting Anthropic, OpenAI, DeepSeek, and local models";
static readonly defaultModel = "google/gemini-2.5-flash";
providerName = "OpenRouter";
private model: ChatOpenRouter;
lastCalls: LLMCallRecord[] = [];