Viewing File: /usr/local/cpanel/whostmgr/docroot/cgi/softaculous/lib/ai/providers/class_providers.php
<?php
if(!defined('SOFTACULOUS')){
die('Hacking Attempt');
}
require_once(__DIR__ . '/interface_ai_provider.php');
require_once(__DIR__ . '/../core/class_ai_file_handler.php');
class OpenAIProvider extends BaseAIProvider {
protected $id = 'openai';
protected $name = 'OpenAI';
protected $logo = 'openai.svg';
protected $api_endpoint = 'https://api.openai.com/v1';
protected $auth_type = 'api_key';
protected $default_model = 'gpt-4o';
protected $models = array(
'gpt-4o' => array('name' => 'GPT-4o', 'context_window' => 128000),
'gpt-4o-mini' => array('name' => 'GPT-4o Mini', 'context_window' => 128000),
'gpt-4-turbo' => array('name' => 'GPT-4 Turbo', 'context_window' => 128000),
'gpt-3.5-turbo' => array('name' => 'GPT-3.5 Turbo', 'context_window' => 16385)
);
protected $context_window = 128000;
protected $supports_streaming = true;
}
class AnthropicProvider extends BaseAIProvider {
protected $id = 'anthropic';
protected $name = 'Anthropic';
protected $logo = 'anthropic.svg';
protected $api_endpoint = 'https://api.anthropic.com/v1';
protected $auth_type = 'api_key';
protected $default_model = 'claude-sonnet-4-5-20250929';
protected $models = array(
'claude-sonnet-5' => array('name' => 'Claude Sonnet 5', 'context_window' => 1000000),
'claude-fable-5' => array('name' => 'Claude Fable 5', 'context_window' => 1000000),
'claude-opus-4-8' => array('name' => 'Claude Opus 4.8', 'context_window' => 1000000),
'claude-opus-4-7' => array('name' => 'Claude Opus 4.7', 'context_window' => 1000000),
'claude-sonnet-4-6' => array('name' => 'Claude Sonnet 4.6', 'context_window' => 1000000),
'claude-opus-4-6' => array('name' => 'Claude Opus 4.6', 'context_window' => 1000000),
'claude-opus-4-5-20251101' => array('name' => 'Claude Opus 4.5', 'context_window' => 200000),
'claude-haiku-4-5-20251001' => array('name' => 'Claude Haiku 4.5', 'context_window' => 200000),
'claude-sonnet-4-5-20250929' => array('name' => 'Claude Sonnet 4.5', 'context_window' => 200000)
);
protected $context_window = 200000;
protected $supports_streaming = true;
private $runtime_api_key = '';
public function set_runtime_api_key($key) {
$this->runtime_api_key = is_string($key) ? $key : '';
}
private function get_cache_file() {
$dir = AIFileHandler::get_ai_base_dir('') . '/provider';
AIFileHandler::ensure_dir($dir, true);
return $dir . '/' . $this->id . '.json.php';
}
private function load_from_cache() {
$file = $this->get_cache_file();
$data = AIFileHandler::read($file);
if (empty($data) || empty($data['fetched_at']) || empty($data['models'])) {
return null;
}
if (time() - intval($data['fetched_at']) > 86400) {
return null;
}
return $data['models'];
}
private function save_to_cache(array $models) {
$file = $this->get_cache_file();
AIFileHandler::write($file, array(
'fetched_at' => time(),
'models' => $models
));
}
public function fetch_models_from_server(array $config = array()) {
$api_key = !empty($config['api_key']) ? $config['api_key'] : $this->runtime_api_key;
$url = rtrim($this->api_endpoint, '/') . '/models?limit=100';
$after_id = null;
$all_models = array();
do {
$req_url = $url;
if ($after_id !== null) {
$req_url .= '&after_id=' . urlencode($after_id);
}
$ch = curl_init($req_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$headers = array('anthropic-version: 2023-06-01');
if (!empty($api_key)) {
$headers[] = 'x-api-key: ' . $api_key;
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($response === false || $http_code !== 200) {
break;
}
$data = json_decode($response, true);
if (empty($data) || !is_array($data) || empty($data['data'])) {
break;
}
foreach ($data['data'] as $model) {
if (empty($model['id'])) {
continue;
}
$mid = $model['id'];
$display = !empty($model['display_name']) ? $model['display_name'] : $mid;
$cw = !empty($model['max_input_tokens']) ? intval($model['max_input_tokens']) : $this->context_window;
$all_models[$mid] = array(
'name' => $display,
'context_window' => $cw
);
}
$after_id = null;
if (!empty($data['has_more']) && !empty($data['last_id'])) {
$after_id = $data['last_id'];
}
} while ($after_id !== null && count($all_models) < 500);
if (empty($all_models)) {
return array();
}
ksort($all_models);
return $all_models;
}
public function get_supported_models() {
$cached = $this->load_from_cache();
if ($cached !== null) {
return $cached;
}
$api_models = $this->fetch_models_from_server();
if (!empty($api_models)) {
$this->save_to_cache($api_models);
return $api_models;
}
return $this->models;
}
public function get_default_model() {
$models = $this->get_supported_models();
if (!empty($models[$this->default_model])) {
return $this->default_model;
}
if (!empty($models)) {
return array_key_first($models);
}
return $this->default_model;
}
public function get_chat_url() {
return 'https://api.anthropic.com/v1/messages';
}
public function build_headers(array $config) {
$api_key = isset($config['api_key']) ? $config['api_key'] : $this->runtime_api_key;
$headers = array(
'Content-Type: application/json',
'x-api-key: ' . $api_key,
'anthropic-version: 2023-06-01',
'Accept: application/json'
);
return $headers;
}
public function build_payload(array $messages, $model, array $options = array()) {
$system_message = '';
$filtered_messages = array();
foreach ($messages as $msg) {
if ($msg['role'] === 'system') {
$system_message .= $msg['content'] . "\n";
} else {
$filtered_messages[] = $msg;
}
}
$payload = array(
'model' => $model,
'messages' => $filtered_messages,
'stream' => !empty($options['stream'])
);
if (!empty($system_message)) {
$payload['system'] = trim($system_message);
}
if (!empty($options['temperature'])) {
$payload['temperature'] = floatval($options['temperature']);
}
if (!empty($options['max_tokens'])) {
$payload['max_tokens'] = intval($options['max_tokens']);
} else {
$payload['max_tokens'] = 4096;
}
return $payload;
}
public function parse_stream_chunk($chunk) {
if (strpos($chunk, 'data: ') === 0) {
$json_str = substr($chunk, 6);
if (trim($json_str) === '[DONE]') {
return array('done' => true);
}
$data = json_decode($json_str, true);
if (!empty($data['type']) && $data['type'] === 'content_block_delta') {
if (!empty($data['delta']['text'])) {
return array(
'content' => $data['delta']['text'],
'done' => false
);
}
}
}
return array();
}
public function parse_response($response) {
$data = json_decode($response, true);
if (!empty($data['error'])) {
$error_msg = isset($data['error']['message']) ? $data['error']['message'] : __('Unknown error');
return array('error' => $error_msg);
}
if (!empty($data['content'][0]['text'])) {
return array(
'content' => $data['content'][0]['text'],
'usage' => !empty($data['usage']) ? $data['usage'] : null
);
}
return array('error' => __('Invalid response format'));
}
public function get_error_message(array $response) {
if (!empty($response['error']['message'])) {
return $response['error']['message'];
}
return __('Unknown error occurred');
}
}
class GoogleProvider extends BaseAIProvider {
protected $id = 'google';
protected $name = 'Google';
protected $logo = 'google.svg';
protected $api_endpoint = 'https://generativelanguage.googleapis.com/v1';
protected $auth_type = 'api_key';
protected $default_model = 'gemini-2.5-pro';
protected $models = array(
'gemini-2.5-pro' => array('name' => 'Gemini 2.5 Pro', 'context_window' => 1000000),
'gemini-2.5-flash' => array('name' => 'Gemini 2.5 Flash', 'context_window' => 1000000),
'gemini-1.5-pro' => array('name' => 'Gemini 1.5 Pro', 'context_window' => 1000000),
'gemini-1.5-flash' => array('name' => 'Gemini 1.5 Flash', 'context_window' => 1000000),
'gemini-1.5-flash-8b' => array('name' => 'Gemini 1.5 Flash 8B', 'context_window' => 1000000)
);
protected $context_window = 1000000;
protected $supports_streaming = true;
public function get_chat_url() {
return 'https://generativelanguage.googleapis.com/v1beta/models';
}
public function build_headers(array $config) {
$headers = array(
'Content-Type: application/json'
);
return $headers;
}
public function get_chat_url_with_model($model, array $config) {
$key = !empty($config['api_key']) ? '?key=' . $config['api_key'] : '';
return 'https://generativelanguage.googleapis.com/v1beta/models/' . $model . ':generateContent' . $key;
}
public function build_payload(array $messages, $model, array $options = array()) {
$contents = array();
foreach ($messages as $msg) {
$role = ($msg['role'] === 'assistant') ? 'model' : 'user';
$contents[] = array(
'role' => $role,
'parts' => array(array('text' => $msg['content']))
);
}
$payload = array(
'contents' => $contents,
'generationConfig' => array(
'temperature' => !empty($options['temperature']) ? floatval($options['temperature']) : 0.9,
'maxOutputTokens' => !empty($options['max_tokens']) ? intval($options['max_tokens']) : 8192
)
);
return $payload;
}
public function parse_stream_chunk($chunk) {
$data = json_decode($chunk, true);
if (!empty($data['candidates'][0]['content']['parts'][0]['text'])) {
return array(
'content' => $data['candidates'][0]['content']['parts'][0]['text'],
'done' => !empty($data['candidates'][0]['finishReason'])
);
}
return array();
}
public function parse_response($response) {
$data = json_decode($response, true);
if (!empty($data['error'])) {
$error_msg = isset($data['error']['message']) ? $data['error']['message'] : __('Unknown error');
return array('error' => $error_msg);
}
if (!empty($data['candidates'][0]['content']['parts'][0]['text'])) {
return array(
'content' => $data['candidates'][0]['content']['parts'][0]['text'],
'usage' => !empty($data['usageMetadata']) ? $data['usageMetadata'] : null
);
}
return array('error' => __('Invalid response format'));
}
}
class OpenRouterProvider extends BaseAIProvider {
protected $id = 'openrouter';
protected $name = 'OpenRouter';
protected $logo = 'openrouter.svg';
protected $api_endpoint = 'https://openrouter.ai/api/v1';
protected $auth_type = 'api_key';
protected $default_model = 'anthropic/claude-3.5-sonnet';
protected $models = array(); // Dynamic
protected $context_window = 128000;
protected $supports_streaming = true;
public function get_supported_models() {
if (!empty($this->models)) {
return $this->models;
}
return array(
'anthropic/claude-3.5-sonnet' => array('name' => 'Claude 3.5 Sonnet'),
'openai/gpt-4o' => array('name' => 'GPT-4o'),
'openai/gpt-4o-mini' => array('name' => 'GPT-4o Mini'),
'meta-llama/llama-3-70b' => array('name' => 'Llama 3 70B'),
'google/gemini-2.5-pro' => array('name' => 'Gemini 2.5 Pro')
);
}
}
class OllamaProvider extends BaseAIProvider {
protected $id = 'ollama';
protected $name = 'Ollama (Local)';
protected $logo = 'ollama.svg';
protected $api_endpoint = 'http://127.0.0.1:11434/v1';
protected $auth_type = 'none';
protected $default_model = 'llama3';
protected $models = array(); // Dynamic from server
protected $context_window = 4096;
protected $supports_streaming = true;
public function get_supported_models() {
return $this->models;
}
public function fetch_models_from_server(array $config) {
$url = 'http://127.0.0.1:11434/api/tags';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$response = curl_exec($ch);
curl_close($ch);
if ($response) {
$data = json_decode($response, true);
if (!empty($data['models'])) {
$models = array();
foreach ($data['models'] as $model) {
$name = $model['name'];
$models[$name] = array('name' => $name);
}
ksort($models);
$this->models = $models;
}
}
return $this->models;
}
}
class OllamaCloudProvider extends BaseAIProvider {
protected $id = 'ollama_cloud';
protected $name = 'Ollama Cloud';
protected $logo = 'ollama.svg';
protected $api_endpoint = 'https://ollama.com/v1';
protected $auth_type = 'api_key';
protected $default_model = 'llama3';
protected $models = array(
'llama3' => array('name' => 'Llama 3', 'context_window' => 128000),
'codellama' => array('name' => 'Code Llama', 'context_window' => 128000),
'mistral' => array('name' => 'Mistral', 'context_window' => 128000),
);
protected $context_window = 128000;
protected $supports_streaming = true;
private function get_cache_file() {
$dir = AIFileHandler::get_ai_base_dir('') . '/provider';
return $dir . '/' . $this->id . '.json.php';
}
private function load_from_cache() {
$file = $this->get_cache_file();
$data = AIFileHandler::read($file);
if (empty($data) || empty($data['fetched_at']) || empty($data['models'])) {
return null;
}
if (time() - intval($data['fetched_at']) > 86400) {
return null;
}
return $data['models'];
}
private function save_to_cache(array $models) {
$file = $this->get_cache_file();
AIFileHandler::write($file, array(
'fetched_at' => time(),
'models' => $models
));
}
public function fetch_models_from_server(array $config = array()) {
$base_url = !empty($config['base_url']) ? rtrim($config['base_url'], '/') : rtrim($this->api_endpoint, '/');
$url = $base_url . '/models';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
if (!empty($config['api_key'])) {
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $config['api_key']));
}
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($response === false || $http_code !== 200) {
return array();
}
$data = json_decode($response, true);
if (empty($data) || !is_array($data)) {
return array();
}
$raw_models = array();
if (!empty($data['data']) && is_array($data['data'])) {
$raw_models = $data['data'];
} elseif (!empty($data['models']) && is_array($data['models'])) {
$raw_models = $data['models'];
}
if (empty($raw_models)) {
return array();
}
$models = array();
foreach ($raw_models as $model) {
if (empty($model['id'])) {
continue;
}
$mid = $model['id'];
$models[$mid] = array(
'name' => !empty($model['name']) ? $model['name'] : $mid,
'context_window' => !empty($model['context_window']) ? intval($model['context_window']) : $this->context_window
);
}
ksort($models);
return $models;
}
public function get_supported_models() {
$cached = $this->load_from_cache();
if ($cached !== null) {
return $cached;
}
$api_models = $this->fetch_models_from_server();
if (!empty($api_models)) {
$this->save_to_cache($api_models);
return $api_models;
}
return $this->models;
}
public function get_default_model() {
$models = $this->get_supported_models();
if (!empty($models[$this->default_model])) {
return $this->default_model;
}
if (!empty($models)) {
return array_key_first($models);
}
return $this->default_model;
}
}
class GroqProvider extends BaseAIProvider {
protected $id = 'groq';
protected $name = 'Groq';
protected $logo = 'groq.svg';
protected $api_endpoint = 'https://api.groq.com/openai/v1';
protected $auth_type = 'api_key';
protected $default_model = 'llama-3.3-70b';
protected $models = array(
'llama-3.3-70b' => array('name' => 'Llama 3.3 70B', 'context_window' => 128000),
'mixtral-8x7b' => array('name' => 'Mixtral 8x7B', 'context_window' => 32000),
'llama-3.1-8b-instant' => array('name' => 'Llama 3.1 8B Instant', 'context_window' => 128000)
);
protected $context_window = 128000;
protected $supports_streaming = true;
}
class TogetherProvider extends BaseAIProvider {
protected $id = 'together';
protected $name = 'Together AI';
protected $logo = 'together.svg';
protected $api_endpoint = 'https://api.together.xyz/v1';
protected $auth_type = 'api_key';
protected $default_model = 'meta-llama/Llama-3-70b';
protected $models = array(
'meta-llama/Llama-3-70b' => array('name' => 'Llama 3 70B'),
'meta-llama/Llama-3.3-70b' => array('name' => 'Llama 3.3 70B'),
'deepseek-ai/DeepSeek-R1' => array('name' => 'DeepSeek R1')
);
protected $context_window = 128000;
protected $supports_streaming = true;
}
class DeepSeekProvider extends BaseAIProvider {
protected $id = 'deepseek';
protected $name = 'DeepSeek';
protected $logo = 'deepseek.svg';
protected $api_endpoint = 'https://api.deepseek.com/v1';
protected $auth_type = 'api_key';
protected $default_model = 'deepseek-chat';
protected $models = array(
'deepseek-chat' => array('name' => 'DeepSeek Chat', 'context_window' => 128000),
'deepseek-coder' => array('name' => 'DeepSeek Coder', 'context_window' => 128000)
);
protected $context_window = 128000;
protected $supports_streaming = true;
}
class AzureProvider extends BaseAIProvider {
protected $id = 'azure';
protected $name = 'Azure OpenAI';
protected $logo = 'azure.svg';
protected $api_endpoint = 'https://{resource}.openai.azure.com/openai/deployments/{deployment}/chat/completions';
protected $auth_type = 'api_key';
protected $default_model = 'gpt-4o';
protected $models = array();
protected $context_window = 128000;
protected $supports_streaming = true;
public function validate_config(array $config) {
$errors = array();
if (empty($config['resource'])) {
$errors[] = __('Azure resource name is required');
}
if (empty($config['deployment'])) {
$errors[] = __('Azure deployment name is required');
}
if (empty($config['api_key'])) {
$errors[] = __('API key is required');
}
return $errors;
}
public function get_chat_url() {
return 'https://{resource}.openai.azure.com/openai/deployments/{deployment}/chat/completions?api-version=2024-02-01';
}
public function build_headers(array $config) {
$api_key = isset($config['api_key']) ? $config['api_key'] : '';
return array(
'Content-Type: application/json',
'api-key: ' . $api_key
);
}
}
class BedrockProvider extends BaseAIProvider {
protected $id = 'bedrock';
protected $name = 'AWS Bedrock';
protected $logo = 'aws.svg';
protected $api_endpoint = 'bedrock';
protected $auth_type = 'aws';
protected $default_model = 'anthropic.claude-3-sonnet';
protected $models = array();
protected $context_window = 200000;
protected $supports_streaming = true;
public function validate_config(array $config) {
$errors = array();
if (empty($config['region'])) {
$errors[] = __('AWS region is required');
}
if (empty($config['access_key']) && empty($config['use_instance_role'])) {
$errors[] = __('AWS access key or instance role is required');
}
return $errors;
}
}
class FireworksProvider extends BaseAIProvider {
protected $id = 'fireworks';
protected $name = 'Fireworks AI';
protected $logo = 'fireworks.svg';
protected $api_endpoint = 'https://api.fireworks.ai/v1';
protected $auth_type = 'api_key';
protected $default_model = 'accounts/fireworks/models/llama-3-70b';
protected $models = array(
'accounts/fireworks/models/llama-3-70b' => array('name' => 'Llama 3 70B'),
'accounts/fireworks/models/qwen2-72b' => array('name' => 'Qwen2 72B')
);
protected $context_window = 128000;
protected $supports_streaming = true;
}
class CloudflareProvider extends BaseAIProvider {
protected $id = 'cloudflare';
protected $name = 'Cloudflare AI Gateway';
protected $logo = 'cloudflare.svg';
protected $api_endpoint = 'https://api.cloudflare.com/client/v4/ai';
protected $auth_type = 'api_key';
protected $default_model = '@cf/meta/llama-3.1-8b-instruct';
protected $models = array(
'@cf/meta/llama-3.1-8b-instruct' => array('name' => 'Llama 3.1 8B'),
'@cf/meta/llama-3.1-70b-instruct' => array('name' => 'Llama 3.1 70B')
);
protected $context_window = 128000;
protected $supports_streaming = true;
}
class HuggingFaceProvider extends BaseAIProvider {
protected $id = 'huggingface';
protected $name = 'Hugging Face';
protected $logo = 'huggingface.svg';
protected $api_endpoint = 'https://api-inference.huggingface.co/v1';
protected $auth_type = 'api_key';
protected $default_model = 'meta-llama/Llama-3-70b';
protected $models = array(); // Dynamic
protected $context_window = 128000;
protected $supports_streaming = true;
}
class OpenCodeZenProvider extends BaseAIProvider {
protected $id = 'opencode_zen';
protected $name = 'OpenCode Zen (Free)';
protected $logo = 'opencode.svg';
protected $api_endpoint = 'https://opencode.ai/zen/v1';
protected $auth_type = 'none';
protected $default_model = 'gpt-5-nano';
protected $models = array(
'gpt-5-nano' => array('name' => 'GPT-5 Nano', 'context_window' => 128000),
'grok-code' => array('name' => 'Grok Code Fast 1', 'context_window' => 128000),
'glm-5-free' => array('name' => 'GLM-5 Free', 'context_window' => 128000),
'kimi-k2.5-free' => array('name' => 'Kimi K2.5 Free', 'context_window' => 128000),
'qwen3.6-plus-free' => array('name' => 'Qwen3.6 Plus Free', 'context_window' => 128000),
'minimax-m2.5-free' => array('name' => 'MiniMax M2.5 Free', 'context_window' => 128000),
);
protected $context_window = 128000;
protected $supports_streaming = true;
public function __construct($provider_id = 'opencode_zen') {
$this->id = $provider_id;
if ($provider_id === 'opencode_zen_premium') {
$this->name = 'OpenCode Zen (Premium)';
$this->auth_type = 'api_key';
}
}
private function get_cache_dir() {
$dir = AIFileHandler::get_ai_base_dir('') . '/provider';
AIFileHandler::ensure_dir($dir, true);
return $dir;
}
private function get_cache_file($provider_id) {
return $this->get_cache_dir() . '/' . $provider_id . '.json.php';
}
private function load_from_cache() {
$file = $this->get_cache_file($this->id);
$data = AIFileHandler::read($file);
if (empty($data) || empty($data['fetched_at']) || empty($data['models'])) {
return null;
}
if (time() - intval($data['fetched_at']) > 86400) {
return null;
}
return $data['models'];
}
private function save_filtered_cache($provider_id, array $models, $timestamp) {
$file = $this->get_cache_file($provider_id);
AIFileHandler::write($file, array(
'fetched_at' => $timestamp,
'models' => $models
));
}
private function fetch_and_cache_all() {
$url = rtrim($this->api_endpoint, '/') . '/models';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($response === false || $http_code !== 200) {
return null;
}
$data = json_decode($response, true);
if (empty($data) || !is_array($data)) {
return null;
}
$raw_models = array();
if (!empty($data['data']) && is_array($data['data'])) {
$raw_models = $data['data'];
} elseif (!empty($data['models']) && is_array($data['models'])) {
$raw_models = $data['models'];
}
if (empty($raw_models)) {
return null;
}
$all_models = array();
foreach ($raw_models as $model) {
if (empty($model['id'])) {
continue;
}
$mid = $model['id'];
$all_models[$mid] = array(
'name' => !empty($model['name']) ? $model['name'] : $mid,
'context_window' => !empty($model['context_window']) ? intval($model['context_window']) : $this->context_window
);
}
ksort($all_models);
$free_models = array();
$premium_models = array();
foreach ($all_models as $id => $info) {
if (strpos($id, 'free') !== false) {
$free_models[$id] = $info;
} else {
$premium_models[$id] = $info;
}
}
$timestamp = time();
$this->save_filtered_cache('opencode_zen', $free_models, $timestamp);
$this->save_filtered_cache('opencode_zen_premium', $premium_models, $timestamp);
return $all_models;
}
private function get_fallback_models() {
$filtered = array();
foreach ($this->models as $id => $info) {
if ($this->id === 'opencode_zen' && strpos($id, 'free') !== false) {
$filtered[$id] = $info;
} elseif ($this->id === 'opencode_zen_premium' && strpos($id, 'free') === false) {
$filtered[$id] = $info;
}
}
return $filtered;
}
public function get_supported_models() {
$cached = $this->load_from_cache();
if ($cached !== null) {
return $cached;
}
$all_models = $this->fetch_and_cache_all();
if ($all_models !== null) {
$filtered = array();
foreach ($all_models as $id => $info) {
if ($this->id === 'opencode_zen' && strpos($id, 'free') !== false) {
$filtered[$id] = $info;
} elseif ($this->id === 'opencode_zen_premium' && strpos($id, 'free') === false) {
$filtered[$id] = $info;
}
}
return $filtered;
}
return $this->get_fallback_models();
}
public function get_default_model() {
$models = $this->get_supported_models();
if (!empty($models[$this->default_model])) {
return $this->default_model;
}
if (!empty($models)) {
return array_key_first($models);
}
return $this->default_model;
}
}
class MiniMaxProvider extends BaseAIProvider {
protected $id = 'minimax';
protected $name = 'MiniMax';
protected $logo = 'minimax.svg';
protected $api_endpoint = 'https://api.minimax.chat/v1';
protected $auth_type = 'api_key';
protected $default_model = 'MiniMax-Text-01';
protected $models = array(
'MiniMax-Text-01' => array('name' => 'MiniMax-Text-01', 'context_window' => 1048576),
'MiniMax-M1' => array('name' => 'MiniMax-M1', 'context_window' => 1048576)
);
protected $context_window = 1048576;
protected $supports_streaming = true;
}
class CustomProvider extends BaseAIProvider {
protected $id = 'custom';
protected $name = 'Custom Provider';
protected $logo = 'custom.svg';
protected $api_endpoint = '';
protected $auth_type = 'api_key';
protected $default_model = '';
protected $models = array();
protected $context_window = 128000;
protected $supports_streaming = true;
protected $custom_config = array();
public function __construct($base_url = '', $id = 'custom', $config = array()) {
$this->id = $id;
$this->api_endpoint = rtrim($base_url, '/');
$this->custom_config = $config;
if(!empty($config['models'])){
$this->models = $config['models'];
$this->default_model = array_key_first($config['models']);
}
}
public function validate_config(array $config) {
$errors = array();
if (empty($config['base_url'])) {
$errors[] = __('Base URL is required');
}
return $errors;
}
public function get_chat_url() {
return rtrim($this->api_endpoint, '/') . '/chat/completions';
}
}
Back to Directory