dolibarr 25.0.0-alpha
list_models.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
29if (!defined('NOTOKENRENEWAL')) {
30 define('NOTOKENRENEWAL', '1');
31}
32if (!defined('NOREQUIREMENU')) {
33 define('NOREQUIREMENU', '1');
34}
35if (!defined('NOREQUIREHTML')) {
36 define('NOREQUIREHTML', '1');
37}
38if (!defined('NOREQUIREAJAX')) {
39 define('NOREQUIREAJAX', '1');
40}
41if (!defined('NOREQUIRESOC')) {
42 define('NOREQUIRESOC', '1');
43}
44
45require '../../main.inc.php';
46require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
47require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
48require_once DOL_DOCUMENT_ROOT.'/ai/lib/ai.lib.php';
55top_httphead('application/json');
56
57if (!isModEnabled('ai')) {
58 http_response_code(403);
59 print json_encode(array('error' => 'Module not enabled'));
60 exit;
61}
62// Same gate as the assistant itself: the dedicated right, or admin.
63if (empty($user->admin) && !$user->hasRight('ai', 'assistant', 'use')) {
64 http_response_code(403);
65 print json_encode(array('error' => 'Permission denied'));
66 exit;
67}
68
69$serviceKey = getDolGlobalString('AI_API_SERVICE');
70if (empty($serviceKey) || $serviceKey == '-1') {
71 print json_encode(array('service' => '', 'models' => array()));
72 exit;
73}
74
75// 1-hour cache in a JSON constant (avoid one provider round-trip per page)
76$cacheraw = getDolGlobalString('AI_MODELS_LIST_CACHE');
77if ($cacheraw) {
78 $cache = json_decode($cacheraw, true);
79 if (is_array($cache) && !empty($cache['service']) && $cache['service'] === $serviceKey
80 && !empty($cache['ts']) && (dol_now() - (int) $cache['ts']) < 3600
81 && !empty($cache['models']) && is_array($cache['models'])) {
82 print json_encode(array('service' => $serviceKey, 'models' => $cache['models'], 'cached' => true));
83 exit;
84 }
85}
86
87$servicesList = getListOfAIServices();
88$adapterType = $servicesList[$serviceKey]['adapter_type'] ?? 'openai';
89$defUrl = $servicesList[$serviceKey]['url'] ?? '';
90$baseUrl = rtrim(getDolGlobalString('AI_API_'.strtoupper($serviceKey).'_URL') ?: $defUrl, '/');
91
92$apiKey = getDolGlobalString('AI_API_'.strtoupper($serviceKey).'_KEY');
93if (preg_match('/^crypt:/', $apiKey)) {
94 $apiKey = dolDecrypt($apiKey, $conf->file->instance_unique_id);
95}
96if (empty($apiKey) || empty($baseUrl)) {
97 print json_encode(array('service' => $serviceKey, 'models' => array(), 'error' => 'Provider not configured'));
98 exit;
99}
100
101$models = array();
102if ($adapterType === 'anthropic') {
103 $headers = array('x-api-key: '.$apiKey, 'anthropic-version: 2023-06-01');
104 $res = getURLContent($baseUrl.'/models?limit=100', 'GET', '', 1, $headers, array('http', 'https'), 2);
105 $json = json_decode($res['content'] ?? '', true);
106 foreach ((array) ($json['data'] ?? array()) as $m) {
107 if (!empty($m['id'])) {
108 $models[] = (string) $m['id'];
109 }
110 }
111} elseif ($adapterType === 'google') {
112 $res = getURLContent($baseUrl.'/models?pageSize=200&key='.urlencode($apiKey), 'GET', '', 1, array(), array('http', 'https'), 2);
113 $json = json_decode($res['content'] ?? '', true);
114 foreach ((array) ($json['models'] ?? array()) as $m) {
115 if (!empty($m['name'])) {
116 $models[] = preg_replace('/^models\//', '', (string) $m['name']);
117 }
118 }
119} else {
120 // OpenAI-compatible providers (OpenAI, Mistral, Groq, DeepSeek, custom...)
121 $headers = array('Authorization: Bearer '.$apiKey);
122 $res = getURLContent($baseUrl.'/models', 'GET', '', 1, $headers, array('http', 'https'), 2);
123 $json = json_decode($res['content'] ?? '', true);
124 foreach ((array) ($json['data'] ?? array()) as $m) {
125 if (!empty($m['id'])) {
126 $models[] = (string) $m['id'];
127 }
128 }
129}
130
131$models = array_values(array_unique($models));
132sort($models);
133
134if (count($models)) {
135 dolibarr_set_const($db, 'AI_MODELS_LIST_CACHE', json_encode(array('service' => $serviceKey, 'ts' => dol_now(), 'models' => $models)), 'chaine', 0, '', $conf->entity);
136}
137
138print json_encode(array('service' => $serviceKey, 'models' => $models, 'cached' => false));
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
getListOfAIServices()
Get list of available ai services.
Definition ai.lib.php:69
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array(), $allowedschemes=array('http', 'https'), $localurl=0, $ssl_verifypeer=-1, $timeoutconnect=0, $timeoutresponse=0, $otherCurlOptions=array(), $morelogsuffix='')
Function to get a content from an URL (use proxy if proxy defined).
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
dolDecrypt($chain, $key='', $patterntotest='')
Decode a string with a symmetric encryption.