diff --git a/gitnexus-web/src/components/SettingsPanel.tsx b/gitnexus-web/src/components/SettingsPanel.tsx
index c93dd7df9..916eeffdd 100644
--- a/gitnexus-web/src/components/SettingsPanel.tsx
+++ b/gitnexus-web/src/components/SettingsPanel.tsx
@@ -4,6 +4,7 @@ import {
loadSettings,
saveSettings,
getProviderDisplayName,
+ getAvailableModels,
fetchOpenRouterModels,
} from '../core/llm/settings-service';
import type { LLMSettings, LLMProvider } from '../core/llm/types';
@@ -296,7 +297,7 @@ export const SettingsPanel = ({ isOpen, onClose, onSettingsSaved, backendUrl, is
if (!isOpen) return null;
- const providers: LLMProvider[] = ['openai', 'gemini', 'anthropic', 'azure-openai', 'ollama', 'openrouter', 'minimax'];
+ const providers: LLMProvider[] = ['openai', 'gemini', 'anthropic', 'azure-openai', 'ollama', 'openrouter', 'minimax', 'glm'];
return (
@@ -381,7 +382,7 @@ export const SettingsPanel = ({ isOpen, onClose, onSettingsSaved, backendUrl, is
w-8 h-8 rounded-lg flex items-center justify-center text-lg
${settings.activeProvider === provider ? 'bg-accent/20' : 'bg-surface'}
`}>
- {provider === 'openai' ? '🤖' : provider === 'gemini' ? '💎' : provider === 'anthropic' ? '🧠' : provider === 'ollama' ? '🦙' : provider === 'openrouter' ? '🌐' : provider === 'minimax' ? '⚡' : '☁️'}
+ {provider === 'openai' ? '🤖' : provider === 'gemini' ? '💎' : provider === 'anthropic' ? '🧠' : provider === 'ollama' ? '🦙' : provider === 'openrouter' ? '🌐' : provider === 'minimax' ? '⚡' : provider === 'glm' ? '🔮' : '☁️'}
{getProviderDisplayName(provider)}
@@ -756,6 +757,81 @@ export const SettingsPanel = ({ isOpen, onClose, onSettingsSaved, backendUrl, is
/>
)}
+ {/* GLM Settings */}
+ {settings.activeProvider === 'glm' && (
+
+
+
+
+ setSettings(prev => ({
+ ...prev,
+ glm: { ...prev.glm!, apiKey: e.target.value }
+ }))}
+ placeholder="Enter your Z.AI API key"
+ className="w-full px-4 py-3 pr-12 bg-elevated border border-border-subtle rounded-xl text-text-primary placeholder:text-text-muted focus:border-accent focus:ring-2 focus:ring-accent/20 outline-none transition-all"
+ />
+
+
+
+ Get your API key from{' '}
+
+ Z.AI Platform
+
+
+
+
+
+
+
+
+
+
+
+
setSettings(prev => ({
+ ...prev,
+ glm: { ...prev.glm!, baseUrl: e.target.value }
+ }))}
+ placeholder="https://api.z.ai/api/coding/paas/v4"
+ className="w-full px-4 py-3 bg-elevated border border-border-subtle rounded-xl text-text-primary placeholder:text-text-muted focus:border-accent focus:ring-2 focus:ring-accent/20 outline-none transition-all font-mono text-sm"
+ />
+
+ Coding API (default). Use https://api.z.ai/api/paas/v4 for the general API.
+
+
+
+ )}
+
{/* Privacy Note */}
diff --git a/gitnexus-web/src/core/llm/agent.ts b/gitnexus-web/src/core/llm/agent.ts
index 3fcd40bdf..e31c5e92d 100644
--- a/gitnexus-web/src/core/llm/agent.ts
+++ b/gitnexus-web/src/core/llm/agent.ts
@@ -22,6 +22,7 @@ import type {
OllamaConfig,
OpenRouterConfig,
MiniMaxConfig,
+ GLMConfig,
AgentStreamChunk,
} from './types';
import {
@@ -246,6 +247,26 @@ export const createChatModel = (config: ProviderConfig): BaseChatModel => {
});
}
+ case 'glm': {
+ const glmConfig = config as GLMConfig;
+
+ if (!glmConfig.apiKey || glmConfig.apiKey.trim() === '') {
+ throw new Error('GLM API key is required but was not provided');
+ }
+
+ return new ChatOpenAI({
+ apiKey: glmConfig.apiKey,
+ modelName: glmConfig.model,
+ temperature: glmConfig.temperature ?? 0.1,
+ maxTokens: glmConfig.maxTokens,
+ configuration: {
+ apiKey: glmConfig.apiKey,
+ baseURL: glmConfig.baseUrl ?? 'https://api.z.ai/api/coding/paas/v4',
+ },
+ streaming: true,
+ });
+ }
+
default:
throw new Error(`Unsupported provider: ${(config as any).provider}`);
}
diff --git a/gitnexus-web/src/core/llm/settings-service.ts b/gitnexus-web/src/core/llm/settings-service.ts
index 7fc9f5765..e07f957a7 100644
--- a/gitnexus-web/src/core/llm/settings-service.ts
+++ b/gitnexus-web/src/core/llm/settings-service.ts
@@ -16,6 +16,7 @@ import {
OllamaConfig,
OpenRouterConfig,
MiniMaxConfig,
+ GLMConfig,
ProviderConfig,
} from './types';
import { DEFAULT_OPENROUTER_BASE_URL, DEFAULT_OLLAMA_BASE_URL } from '../../config/ui-constants';
@@ -53,6 +54,10 @@ const mergeWithDefaults = (parsed?: Partial | null): LLMSettings =>
...DEFAULT_LLM_SETTINGS.minimax,
...parsed?.minimax,
},
+ glm: {
+ ...DEFAULT_LLM_SETTINGS.glm,
+ ...parsed?.glm,
+ },
});
const readSettings = (storage: Storage): Partial | null => {
@@ -127,7 +132,9 @@ export const updateProviderSettings = (
T extends 'gemini' ? Partial> :
T extends 'anthropic' ? Partial> :
T extends 'ollama' ? Partial> :
+ T extends 'openrouter' ? Partial> :
T extends 'minimax' ? Partial> :
+ T extends 'glm' ? Partial> :
never
>
): LLMSettings => {
@@ -212,6 +219,17 @@ export const updateProviderSettings = (
saveSettings(updated);
return updated;
}
+ case 'glm': {
+ const updated: LLMSettings = {
+ ...current,
+ glm: {
+ ...(current.glm ?? {}),
+ ...(updates as Partial>),
+ },
+ };
+ saveSettings(updated);
+ return updated;
+ }
default: {
// Should be unreachable due to T extends LLMProvider, but keep a safe fallback
const updated: LLMSettings = { ...current };
@@ -278,6 +296,17 @@ const providerBuilders: Record = {
if (!settings.minimax?.apiKey) return null;
return { provider: 'minimax', ...settings.minimax } as MiniMaxConfig;
},
+ glm: (settings) => {
+ if (!settings.glm?.apiKey) return null;
+ return {
+ provider: 'glm',
+ apiKey: settings.glm.apiKey,
+ model: settings.glm.model || 'GLM-5',
+ baseUrl: settings.glm.baseUrl || 'https://api.z.ai/api/coding/paas/v4',
+ temperature: settings.glm.temperature,
+ maxTokens: settings.glm.maxTokens,
+ } as GLMConfig;
+ },
};
export const getActiveProviderConfig = (): ProviderConfig | null => {
@@ -328,6 +357,8 @@ export const getProviderDisplayName = (provider: LLMProvider): string => {
return 'OpenRouter';
case 'minimax':
return 'MiniMax';
+ case 'glm':
+ return 'GLM (Z.AI)';
default:
return provider;
}
@@ -351,6 +382,8 @@ export const getAvailableModels = (provider: LLMProvider): string[] => {
return ['llama3.2', 'llama3.1', 'mistral', 'codellama', 'deepseek-coder'];
case 'minimax':
return ['MiniMax-M2.5', 'MiniMax-M2.5-highspeed'];
+ case 'glm':
+ return ['GLM-5', 'GLM-5-Turbo', 'GLM-4.7', 'GLM-4.5'];
default:
return [];
}
diff --git a/gitnexus-web/src/core/llm/types.ts b/gitnexus-web/src/core/llm/types.ts
index 4c611294f..d75f71f2a 100644
--- a/gitnexus-web/src/core/llm/types.ts
+++ b/gitnexus-web/src/core/llm/types.ts
@@ -2,15 +2,14 @@
* LLM Provider Types
*
* Type definitions for multi-provider LLM support.
- * Supports Azure OpenAI and Google Gemini (with extensibility for others).
+ * Supports OpenAI, Azure OpenAI, Gemini, Anthropic, Ollama, OpenRouter, MiniMax, and GLM5.
*/
/**
* Supported LLM providers
*/
import { DEFAULT_OLLAMA_BASE_URL, DEFAULT_OPENROUTER_BASE_URL } from '../../config/ui-constants';
-
-export type LLMProvider = 'openai' | 'azure-openai' | 'gemini' | 'anthropic' | 'ollama' | 'openrouter' | 'minimax';
+export type LLMProvider = 'openai' | 'azure-openai' | 'gemini' | 'anthropic' | 'ollama' | 'openrouter' | 'minimax' | 'glm';
/**
* Base configuration shared by all providers
@@ -89,10 +88,20 @@ export interface MiniMaxConfig extends BaseProviderConfig {
model: string; // e.g., 'MiniMax-M2.5', 'MiniMax-M2.5-highspeed'
}
+/**
+ * GLM (Z.AI) configuration — OpenAI-compatible API
+ */
+export interface GLMConfig extends BaseProviderConfig {
+ provider: 'glm';
+ apiKey: string;
+ model: string; // e.g., 'GLM-4.7', 'GLM-4.5', 'GLM-4.5-Air', 'GLM-5'
+ baseUrl?: string; // defaults to https://api.z.ai/api/coding/paas/v4
+}
+
/**
* Union type for all provider configurations
*/
-export type ProviderConfig = OpenAIConfig | AzureOpenAIConfig | GeminiConfig | AnthropicConfig | OllamaConfig | OpenRouterConfig | MiniMaxConfig;
+export type ProviderConfig = OpenAIConfig | AzureOpenAIConfig | GeminiConfig | AnthropicConfig | OllamaConfig | OpenRouterConfig | MiniMaxConfig | GLMConfig;
/**
* Stored settings (what goes to localStorage)
@@ -110,6 +119,7 @@ export interface LLMSettings {
ollama?: Partial>;
openrouter?: Partial>;
minimax?: Partial>;
+ glm?: Partial>;
// Intelligent Clustering Settings
intelligentClustering: boolean;
@@ -165,6 +175,12 @@ export const DEFAULT_LLM_SETTINGS: LLMSettings = {
model: 'MiniMax-M2.5',
temperature: 0.1,
},
+ glm: {
+ apiKey: '',
+ model: 'GLM-5',
+ baseUrl: 'https://api.z.ai/api/coding/paas/v4',
+ temperature: 0.1,
+ },
};
/**