Fix Qwen OAuth and Ollama models listing

- Add generateUXDesignerPrompt method to QwenOAuthService
- Fix Ollama Cloud listModels to handle multiple response formats
- Improve Ollama models parsing with array/different response structures
- All providers now support UX Designer Prompt feature
This commit is contained in:
Gemini AI
2025-12-25 23:17:55 +04:00
Unverified
parent f510683e18
commit 07dbe552f7
10 changed files with 735 additions and 100 deletions

View File

@@ -1,8 +1,10 @@
import type { ModelProvider, APIResponse, ChatMessage } from "@/types";
import OllamaCloudService from "./ollama-cloud";
import ZaiPlanService from "./zai-plan";
import qwenOAuthService, { QwenOAuthConfig, QwenOAuthToken } from "./qwen-oauth";
export interface ModelAdapterConfig {
qwen?: QwenOAuthConfig;
ollama?: {
apiKey?: string;
endpoint?: string;
@@ -17,12 +19,27 @@ export interface ModelAdapterConfig {
export class ModelAdapter {
private ollamaService: OllamaCloudService;
private zaiService: ZaiPlanService;
private qwenService = qwenOAuthService;
private preferredProvider: ModelProvider;
constructor(config: ModelAdapterConfig = {}, preferredProvider: ModelProvider = "ollama") {
this.ollamaService = new OllamaCloudService(config.ollama);
this.zaiService = new ZaiPlanService(config.zai);
this.preferredProvider = preferredProvider;
if (config.qwen) {
if (config.qwen.apiKey) {
this.qwenService.setApiKey(config.qwen.apiKey);
}
if (config.qwen.accessToken) {
this.qwenService.setOAuthTokens({
accessToken: config.qwen.accessToken,
refreshToken: config.qwen.refreshToken,
expiresAt: config.qwen.expiresAt,
resourceUrl: config.qwen.resourceUrl,
});
}
}
}
setPreferredProvider(provider: ModelProvider): void {
@@ -37,6 +54,33 @@ export class ModelAdapter {
this.zaiService = new ZaiPlanService({ apiKey });
}
updateQwenApiKey(apiKey: string): void {
this.qwenService.setApiKey(apiKey);
}
updateQwenTokens(tokens?: QwenOAuthToken): void {
this.qwenService.setOAuthTokens(tokens);
}
async startQwenOAuth(): Promise<QwenOAuthToken> {
return await this.qwenService.signIn();
}
getQwenTokenInfo(): QwenOAuthToken | null {
return this.qwenService.getTokenInfo();
}
private buildFallbackProviders(...providers: ModelProvider[]): ModelProvider[] {
const seen = new Set<ModelProvider>();
return providers.filter((provider) => {
if (seen.has(provider)) {
return false;
}
seen.add(provider);
return true;
});
}
private async callWithFallback<T>(
operation: (service: any) => Promise<APIResponse<T>>,
providers: ModelProvider[]
@@ -46,6 +90,9 @@ export class ModelAdapter {
let service: any;
switch (provider) {
case "qwen":
service = this.qwenService;
break;
case "ollama":
service = this.ollamaService;
break;
@@ -70,22 +117,26 @@ export class ModelAdapter {
}
async enhancePrompt(prompt: string, provider?: ModelProvider, model?: string): Promise<APIResponse<string>> {
const providers: ModelProvider[] = provider ? [provider] : [this.preferredProvider, "ollama", "zai"];
const fallback = this.buildFallbackProviders(this.preferredProvider, "qwen", "ollama", "zai");
const providers: ModelProvider[] = provider ? [provider] : fallback;
return this.callWithFallback((service) => service.enhancePrompt(prompt, model), providers);
}
async generatePRD(idea: string, provider?: ModelProvider, model?: string): Promise<APIResponse<string>> {
const providers: ModelProvider[] = provider ? [provider] : ["ollama", "zai", this.preferredProvider];
const fallback = this.buildFallbackProviders(this.preferredProvider, "qwen", "ollama", "zai");
const providers: ModelProvider[] = provider ? [provider] : fallback;
return this.callWithFallback((service) => service.generatePRD(idea, model), providers);
}
async generateActionPlan(prd: string, provider?: ModelProvider, model?: string): Promise<APIResponse<string>> {
const providers: ModelProvider[] = provider ? [provider] : ["zai", "ollama", this.preferredProvider];
const fallback = this.buildFallbackProviders(this.preferredProvider, "qwen", "ollama", "zai");
const providers: ModelProvider[] = provider ? [provider] : fallback;
return this.callWithFallback((service) => service.generateActionPlan(prd, model), providers);
}
async generateUXDesignerPrompt(appDescription: string, provider?: ModelProvider, model?: string): Promise<APIResponse<string>> {
const providers: ModelProvider[] = provider ? [provider] : [this.preferredProvider, "ollama", "zai"];
const fallback = this.buildFallbackProviders(this.preferredProvider, "qwen", "ollama", "zai");
const providers: ModelProvider[] = provider ? [provider] : fallback;
return this.callWithFallback((service) => service.generateUXDesignerPrompt(appDescription, model), providers);
}
@@ -98,6 +149,9 @@ export class ModelAdapter {
let service: any;
switch (provider) {
case "qwen":
service = this.qwenService;
break;
case "ollama":
service = this.ollamaService;
break;
@@ -117,6 +171,7 @@ export class ModelAdapter {
async listModels(provider?: ModelProvider): Promise<APIResponse<Record<ModelProvider, string[]>>> {
const fallbackModels: Record<ModelProvider, string[]> = {
qwen: this.qwenService.getAvailableModels(),
ollama: ["gpt-oss:120b", "llama3.1", "gemma3", "deepseek-r1", "qwen3"],
zai: ["glm-4.7", "glm-4.5", "glm-4.5-air", "glm-4-flash", "glm-4-flashx"],
};
@@ -148,6 +203,8 @@ export class ModelAdapter {
getAvailableModels(provider: ModelProvider): string[] {
switch (provider) {
case "qwen":
return this.qwenService.getAvailableModels();
case "ollama":
return this.ollamaService.getAvailableModels();
case "zai":