From 2d6b24faae4648cd96dada4f30c43b901644b1a6 Mon Sep 17 00:00:00 2001 From: Robert Keus Date: Sun, 26 Jul 2026 21:49:11 +0200 Subject: [PATCH 1/2] feat(provider): add GreenPT --- .../components/icons/ProviderIcon.tsx | 5 ++ src/shared/models/index.ts | 6 ++ .../providers/definitions/greenpt.test.ts | 22 +++++++ src/shared/providers/definitions/greenpt.ts | 60 +++++++++++++++++++ .../providers/definitions/models/greenpt.ts | 5 ++ src/shared/providers/index.ts | 1 + src/shared/types/provider.ts | 1 + src/shared/utils/llm_utils.test.ts | 14 ++++- src/shared/utils/llm_utils.ts | 1 + 9 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/shared/providers/definitions/greenpt.test.ts create mode 100644 src/shared/providers/definitions/greenpt.ts create mode 100644 src/shared/providers/definitions/models/greenpt.ts diff --git a/src/renderer/components/icons/ProviderIcon.tsx b/src/renderer/components/icons/ProviderIcon.tsx index 0aceb77af4..ea6047a44d 100644 --- a/src/renderer/components/icons/ProviderIcon.tsx +++ b/src/renderer/components/icons/ProviderIcon.tsx @@ -69,6 +69,11 @@ export default function ProviderIcon(props: { className?: string; size?: number; )} + {provider === ModelProviderEnum.GreenPT && ( + + + + )} {provider === ModelProviderEnum.Gemini && ( <> diff --git a/src/shared/models/index.ts b/src/shared/models/index.ts index 304c6909a5..ab1a31b5a1 100644 --- a/src/shared/models/index.ts +++ b/src/shared/models/index.ts @@ -21,6 +21,7 @@ export const aiProviderNameHash: Record = { [ModelProviderEnum.Ollama]: 'Ollama API', [ModelProviderEnum.Groq]: 'Groq API', [ModelProviderEnum.DeepSeek]: 'DeepSeek API', + [ModelProviderEnum.GreenPT]: 'GreenPT API', [ModelProviderEnum.SiliconFlow]: 'SiliconFlow API', [ModelProviderEnum.VolcEngine]: 'VolcEngine API', [ModelProviderEnum.MistralAI]: 'MistralAI', @@ -75,6 +76,11 @@ export const AIModelProviderMenuOptionList = [ label: aiProviderNameHash[ModelProviderEnum.DeepSeek], disabled: false, }, + { + value: ModelProviderEnum.GreenPT, + label: aiProviderNameHash[ModelProviderEnum.GreenPT], + disabled: false, + }, { value: ModelProviderEnum.Qwen, label: aiProviderNameHash[ModelProviderEnum.Qwen], diff --git a/src/shared/providers/definitions/greenpt.test.ts b/src/shared/providers/definitions/greenpt.test.ts new file mode 100644 index 0000000000..e5b2350038 --- /dev/null +++ b/src/shared/providers/definitions/greenpt.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'vitest' +import { ModelProviderEnum, ModelProviderType } from '../../types' +import { greenPTProvider } from './greenpt' + +describe('GreenPT provider', () => { + it('registers the OpenAI-compatible endpoint and flagship models', () => { + expect(greenPTProvider).toMatchObject({ + id: ModelProviderEnum.GreenPT, + type: ModelProviderType.OpenAI, + defaultSettings: { + apiHost: 'https://api.greenpt.ai/v1', + }, + }) + expect(greenPTProvider.defaultSettings?.models).toEqual( + expect.arrayContaining([ + expect.objectContaining({ modelId: 'glm-5.2' }), + expect.objectContaining({ modelId: 'kimi-k2.7-code' }), + expect.objectContaining({ modelId: 'green-embedding', type: 'embedding' }), + ]) + ) + }) +}) diff --git a/src/shared/providers/definitions/greenpt.ts b/src/shared/providers/definitions/greenpt.ts new file mode 100644 index 0000000000..301617d2a1 --- /dev/null +++ b/src/shared/providers/definitions/greenpt.ts @@ -0,0 +1,60 @@ +import { ModelProviderEnum, ModelProviderType } from '../../types' +import { defineProvider } from '../registry' +import GreenPT from './models/greenpt' + +export const greenPTProvider = defineProvider({ + id: ModelProviderEnum.GreenPT, + name: 'GreenPT', + type: ModelProviderType.OpenAI, + description: 'OpenAI-compatible AI inference hosted in Europe on renewable-powered infrastructure.', + curatedModelIds: ['glm-5.2', 'kimi-k2.7-code', 'gemma4', 'green-embedding'], + urls: { + website: 'https://greenpt.com/', + apiKey: 'https://account.greenpt.ai/api/keys', + docs: 'https://docs.greenpt.ai/get-started', + models: 'https://docs.greenpt.ai/models', + }, + defaultSettings: { + apiHost: 'https://api.greenpt.ai/v1', + models: [ + { + modelId: 'glm-5.2', + contextWindow: 1_000_000, + capabilities: ['reasoning', 'tool_use'], + }, + { + modelId: 'kimi-k2.7-code', + contextWindow: 256_000, + maxOutput: 256_000, + capabilities: ['reasoning', 'tool_use'], + }, + { + modelId: 'gemma4', + contextWindow: 256_000, + maxOutput: 32_000, + capabilities: ['vision', 'reasoning', 'tool_use'], + }, + { + modelId: 'green-embedding', + type: 'embedding', + }, + ], + }, + createModel: (config) => { + return new GreenPT( + { + apiKey: config.effectiveApiKey, + apiHost: config.formattedApiHost, + model: config.model, + temperature: config.settings.temperature, + topP: config.settings.topP, + maxOutputTokens: config.settings.maxTokens, + stream: config.settings.stream, + }, + config.dependencies + ) + }, + getDisplayName: (modelId, providerSettings) => { + return `GreenPT API (${providerSettings?.models?.find((model) => model.modelId === modelId)?.nickname || modelId})` + }, +}) diff --git a/src/shared/providers/definitions/models/greenpt.ts b/src/shared/providers/definitions/models/greenpt.ts new file mode 100644 index 0000000000..dc293222e0 --- /dev/null +++ b/src/shared/providers/definitions/models/greenpt.ts @@ -0,0 +1,5 @@ +import OpenAICompatible from '../../../models/openai-compatible' + +export default class GreenPT extends OpenAICompatible { + public name = 'GreenPT' +} diff --git a/src/shared/providers/index.ts b/src/shared/providers/index.ts index 06742110e7..2dafe452fa 100644 --- a/src/shared/providers/index.ts +++ b/src/shared/providers/index.ts @@ -11,6 +11,7 @@ import './definitions/openai-responses' import './definitions/gemini' import './definitions/claude' import './definitions/deepseek' +import './definitions/greenpt' import './definitions/qwen' import './definitions/qwen-portal' import './definitions/minimax' diff --git a/src/shared/types/provider.ts b/src/shared/types/provider.ts index 8f12db4f03..370326f5c8 100644 --- a/src/shared/types/provider.ts +++ b/src/shared/types/provider.ts @@ -18,6 +18,7 @@ export enum ModelProviderEnum { Ollama = 'ollama', Groq = 'groq', DeepSeek = 'deepseek', + GreenPT = 'greenpt', SiliconFlow = 'siliconflow', VolcEngine = 'volcengine', MistralAI = 'mistral-ai', diff --git a/src/shared/utils/llm_utils.test.ts b/src/shared/utils/llm_utils.test.ts index 7aa06422c3..c57098e901 100644 --- a/src/shared/utils/llm_utils.test.ts +++ b/src/shared/utils/llm_utils.test.ts @@ -1,5 +1,17 @@ import { describe, expect, it } from 'vitest' -import { normalizeClaudeHost, normalizeGeminiHost, normalizeOpenAIApiHostAndPath } from './llm_utils' +import { ModelProviderEnum } from '../types' +import { + isOpenAICompatible, + normalizeClaudeHost, + normalizeGeminiHost, + normalizeOpenAIApiHostAndPath, +} from './llm_utils' + +describe('isOpenAICompatible', () => { + it('recognizes GreenPT', () => { + expect(isOpenAICompatible(ModelProviderEnum.GreenPT, 'glm-5.2')).toBe(true) + }) +}) describe('normalizeOpenAIApiHostAndPath', () => { it('returns defaults when apiHost is empty', () => { diff --git a/src/shared/utils/llm_utils.ts b/src/shared/utils/llm_utils.ts index 2df5666a1a..de89a599db 100644 --- a/src/shared/utils/llm_utils.ts +++ b/src/shared/utils/llm_utils.ts @@ -134,6 +134,7 @@ export function isOpenAICompatible(providerId: string, _modelId: string) { ModelProviderEnum.XAI, ModelProviderEnum.Groq, ModelProviderEnum.DeepSeek, + ModelProviderEnum.GreenPT, ModelProviderEnum.LMStudio, ModelProviderEnum.Qwen, ModelProviderEnum.QwenPortal, From cc5a3be26b1894430fe295d2d538534ebaf3fb25 Mon Sep 17 00:00:00 2001 From: Robert Keus Date: Sun, 26 Jul 2026 21:56:39 +0200 Subject: [PATCH 2/2] refactor(provider): prioritize GreenPT flagship models --- src/shared/providers/definitions/greenpt.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/shared/providers/definitions/greenpt.ts b/src/shared/providers/definitions/greenpt.ts index 301617d2a1..1935d1cf6a 100644 --- a/src/shared/providers/definitions/greenpt.ts +++ b/src/shared/providers/definitions/greenpt.ts @@ -6,8 +6,9 @@ export const greenPTProvider = defineProvider({ id: ModelProviderEnum.GreenPT, name: 'GreenPT', type: ModelProviderType.OpenAI, - description: 'OpenAI-compatible AI inference hosted in Europe on renewable-powered infrastructure.', - curatedModelIds: ['glm-5.2', 'kimi-k2.7-code', 'gemma4', 'green-embedding'], + description: + 'GreenPT is a European AI provider running optimized inference in data centers powered by 100% renewable energy.', + curatedModelIds: ['glm-5.2', 'kimi-k2.7-code', 'green-embedding'], urls: { website: 'https://greenpt.com/', apiKey: 'https://account.greenpt.ai/api/keys', @@ -28,12 +29,6 @@ export const greenPTProvider = defineProvider({ maxOutput: 256_000, capabilities: ['reasoning', 'tool_use'], }, - { - modelId: 'gemma4', - contextWindow: 256_000, - maxOutput: 32_000, - capabilities: ['vision', 'reasoning', 'tool_use'], - }, { modelId: 'green-embedding', type: 'embedding',