From f7409a9f287a0284d9a72bbfc0eb9b88773ae629 Mon Sep 17 00:00:00 2001
From: JMN09 <157629053+JMN09@users.noreply.github.com>
Date: Tue, 13 Aug 2024 17:07:58 +0300
Subject: [PATCH 1/2] feat(config.ts, llmservice.ts, engine.ts): Added a new
 implementation of AiEngine that supports a configurable backend, added the
 corresponding configuration variables, and integrated it in the factory
 method

---
 out/cli.cjs              | 804 +++++++++++++++++++++------------------
 out/github-action.cjs    | 781 +++++++++++++++++++------------------
 src/commands/config.ts   |  35 +-
 src/engine/llmservice.ts |  38 ++
 src/utils/engine.ts      |   3 +
 5 files changed, 913 insertions(+), 748 deletions(-)
 create mode 100644 src/engine/llmservice.ts

diff --git a/out/cli.cjs b/out/cli.cjs
index 3788260c..3bdfcb96 100755
--- a/out/cli.cjs
+++ b/out/cli.cjs
@@ -1239,8 +1239,8 @@ var require_normalizeHeaderName = __commonJS({
 var require_enhanceError = __commonJS({
   "node_modules/openai/node_modules/axios/lib/core/enhanceError.js"(exports, module2) {
     "use strict";
-    module2.exports = function enhanceError(error, config11, code, request3, response) {
-      error.config = config11;
+    module2.exports = function enhanceError(error, config12, code, request3, response) {
+      error.config = config12;
       if (code) {
         error.code = code;
       }
@@ -1284,9 +1284,9 @@ var require_createError = __commonJS({
   "node_modules/openai/node_modules/axios/lib/core/createError.js"(exports, module2) {
     "use strict";
     var enhanceError = require_enhanceError();
-    module2.exports = function createError(message, config11, code, request3, response) {
+    module2.exports = function createError(message, config12, code, request3, response) {
       var error = new Error(message);
-      return enhanceError(error, config11, code, request3, response);
+      return enhanceError(error, config12, code, request3, response);
     };
   }
 });
@@ -1515,32 +1515,32 @@ var require_xhr = __commonJS({
     var createError = require_createError();
     var transitionalDefaults = require_transitional();
     var Cancel2 = require_Cancel();
-    module2.exports = function xhrAdapter(config11) {
+    module2.exports = function xhrAdapter(config12) {
       return new Promise(function dispatchXhrRequest(resolve, reject) {
-        var requestData = config11.data;
-        var requestHeaders = config11.headers;
-        var responseType = config11.responseType;
+        var requestData = config12.data;
+        var requestHeaders = config12.headers;
+        var responseType = config12.responseType;
         var onCanceled;
         function done() {
-          if (config11.cancelToken) {
-            config11.cancelToken.unsubscribe(onCanceled);
+          if (config12.cancelToken) {
+            config12.cancelToken.unsubscribe(onCanceled);
           }
-          if (config11.signal) {
-            config11.signal.removeEventListener("abort", onCanceled);
+          if (config12.signal) {
+            config12.signal.removeEventListener("abort", onCanceled);
           }
         }
         if (utils.isFormData(requestData)) {
           delete requestHeaders["Content-Type"];
         }
         var request3 = new XMLHttpRequest();
-        if (config11.auth) {
-          var username = config11.auth.username || "";
-          var password = config11.auth.password ? unescape(encodeURIComponent(config11.auth.password)) : "";
+        if (config12.auth) {
+          var username = config12.auth.username || "";
+          var password = config12.auth.password ? unescape(encodeURIComponent(config12.auth.password)) : "";
           requestHeaders.Authorization = "Basic " + btoa(username + ":" + password);
         }
-        var fullPath = buildFullPath2(config11.baseURL, config11.url);
-        request3.open(config11.method.toUpperCase(), buildURL2(fullPath, config11.params, config11.paramsSerializer), true);
-        request3.timeout = config11.timeout;
+        var fullPath = buildFullPath2(config12.baseURL, config12.url);
+        request3.open(config12.method.toUpperCase(), buildURL2(fullPath, config12.params, config12.paramsSerializer), true);
+        request3.timeout = config12.timeout;
         function onloadend() {
           if (!request3) {
             return;
@@ -1552,7 +1552,7 @@ var require_xhr = __commonJS({
             status: request3.status,
             statusText: request3.statusText,
             headers: responseHeaders,
-            config: config11,
+            config: config12,
             request: request3
           };
           settle2(function _resolve(value) {
@@ -1581,31 +1581,31 @@ var require_xhr = __commonJS({
           if (!request3) {
             return;
           }
-          reject(createError("Request aborted", config11, "ECONNABORTED", request3));
+          reject(createError("Request aborted", config12, "ECONNABORTED", request3));
           request3 = null;
         };
         request3.onerror = function handleError() {
-          reject(createError("Network Error", config11, null, request3));
+          reject(createError("Network Error", config12, null, request3));
           request3 = null;
         };
         request3.ontimeout = function handleTimeout() {
-          var timeoutErrorMessage = config11.timeout ? "timeout of " + config11.timeout + "ms exceeded" : "timeout exceeded";
-          var transitional2 = config11.transitional || transitionalDefaults;
-          if (config11.timeoutErrorMessage) {
-            timeoutErrorMessage = config11.timeoutErrorMessage;
+          var timeoutErrorMessage = config12.timeout ? "timeout of " + config12.timeout + "ms exceeded" : "timeout exceeded";
+          var transitional2 = config12.transitional || transitionalDefaults;
+          if (config12.timeoutErrorMessage) {
+            timeoutErrorMessage = config12.timeoutErrorMessage;
           }
           reject(createError(
             timeoutErrorMessage,
-            config11,
+            config12,
             transitional2.clarifyTimeoutError ? "ETIMEDOUT" : "ECONNABORTED",
             request3
           ));
           request3 = null;
         };
         if (utils.isStandardBrowserEnv()) {
-          var xsrfValue = (config11.withCredentials || isURLSameOrigin(fullPath)) && config11.xsrfCookieName ? cookies.read(config11.xsrfCookieName) : void 0;
+          var xsrfValue = (config12.withCredentials || isURLSameOrigin(fullPath)) && config12.xsrfCookieName ? cookies.read(config12.xsrfCookieName) : void 0;
           if (xsrfValue) {
-            requestHeaders[config11.xsrfHeaderName] = xsrfValue;
+            requestHeaders[config12.xsrfHeaderName] = xsrfValue;
           }
         }
         if ("setRequestHeader" in request3) {
@@ -1617,19 +1617,19 @@ var require_xhr = __commonJS({
             }
           });
         }
-        if (!utils.isUndefined(config11.withCredentials)) {
-          request3.withCredentials = !!config11.withCredentials;
+        if (!utils.isUndefined(config12.withCredentials)) {
+          request3.withCredentials = !!config12.withCredentials;
         }
         if (responseType && responseType !== "json") {
-          request3.responseType = config11.responseType;
+          request3.responseType = config12.responseType;
         }
-        if (typeof config11.onDownloadProgress === "function") {
-          request3.addEventListener("progress", config11.onDownloadProgress);
+        if (typeof config12.onDownloadProgress === "function") {
+          request3.addEventListener("progress", config12.onDownloadProgress);
         }
-        if (typeof config11.onUploadProgress === "function" && request3.upload) {
-          request3.upload.addEventListener("progress", config11.onUploadProgress);
+        if (typeof config12.onUploadProgress === "function" && request3.upload) {
+          request3.upload.addEventListener("progress", config12.onUploadProgress);
         }
-        if (config11.cancelToken || config11.signal) {
+        if (config12.cancelToken || config12.signal) {
           onCanceled = function(cancel) {
             if (!request3) {
               return;
@@ -1638,9 +1638,9 @@ var require_xhr = __commonJS({
             request3.abort();
             request3 = null;
           };
-          config11.cancelToken && config11.cancelToken.subscribe(onCanceled);
-          if (config11.signal) {
-            config11.signal.aborted ? onCanceled() : config11.signal.addEventListener("abort", onCanceled);
+          config12.cancelToken && config12.cancelToken.subscribe(onCanceled);
+          if (config12.signal) {
+            config12.signal.aborted ? onCanceled() : config12.signal.addEventListener("abort", onCanceled);
           }
         }
         if (!requestData) {
@@ -2936,15 +2936,15 @@ var require_http = __commonJS({
         setProxy2(redirection, proxy, redirection.href);
       };
     }
-    module2.exports = function httpAdapter2(config11) {
+    module2.exports = function httpAdapter2(config12) {
       return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
         var onCanceled;
         function done() {
-          if (config11.cancelToken) {
-            config11.cancelToken.unsubscribe(onCanceled);
+          if (config12.cancelToken) {
+            config12.cancelToken.unsubscribe(onCanceled);
           }
-          if (config11.signal) {
-            config11.signal.removeEventListener("abort", onCanceled);
+          if (config12.signal) {
+            config12.signal.removeEventListener("abort", onCanceled);
           }
         }
         var resolve = function resolve2(value) {
@@ -2957,8 +2957,8 @@ var require_http = __commonJS({
           rejected = true;
           rejectPromise(value);
         };
-        var data = config11.data;
-        var headers = config11.headers;
+        var data = config12.data;
+        var headers = config12.headers;
         var headerNames = {};
         Object.keys(headers).forEach(function storeLowerName(name) {
           headerNames[name.toLowerCase()] = name;
@@ -2979,23 +2979,23 @@ var require_http = __commonJS({
           } else {
             return reject(createError(
               "Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream",
-              config11
+              config12
             ));
           }
-          if (config11.maxBodyLength > -1 && data.length > config11.maxBodyLength) {
-            return reject(createError("Request body larger than maxBodyLength limit", config11));
+          if (config12.maxBodyLength > -1 && data.length > config12.maxBodyLength) {
+            return reject(createError("Request body larger than maxBodyLength limit", config12));
           }
           if (!headerNames["content-length"]) {
             headers["Content-Length"] = data.length;
           }
         }
         var auth = void 0;
-        if (config11.auth) {
-          var username = config11.auth.username || "";
-          var password = config11.auth.password || "";
+        if (config12.auth) {
+          var username = config12.auth.username || "";
+          var password = config12.auth.password || "";
           auth = username + ":" + password;
         }
-        var fullPath = buildFullPath2(config11.baseURL, config11.url);
+        var fullPath = buildFullPath2(config12.baseURL, config12.url);
         var parsed = url2.parse(fullPath);
         var protocol = parsed.protocol || "http:";
         if (!auth && parsed.auth) {
@@ -3008,31 +3008,31 @@ var require_http = __commonJS({
           delete headers[headerNames.authorization];
         }
         var isHttpsRequest = isHttps2.test(protocol);
-        var agent = isHttpsRequest ? config11.httpsAgent : config11.httpAgent;
+        var agent = isHttpsRequest ? config12.httpsAgent : config12.httpAgent;
         try {
-          buildURL2(parsed.path, config11.params, config11.paramsSerializer).replace(/^\?/, "");
+          buildURL2(parsed.path, config12.params, config12.paramsSerializer).replace(/^\?/, "");
         } catch (err) {
           var customErr = new Error(err.message);
-          customErr.config = config11;
-          customErr.url = config11.url;
+          customErr.config = config12;
+          customErr.url = config12.url;
           customErr.exists = true;
           reject(customErr);
         }
         var options = {
-          path: buildURL2(parsed.path, config11.params, config11.paramsSerializer).replace(/^\?/, ""),
-          method: config11.method.toUpperCase(),
+          path: buildURL2(parsed.path, config12.params, config12.paramsSerializer).replace(/^\?/, ""),
+          method: config12.method.toUpperCase(),
           headers,
           agent,
-          agents: { http: config11.httpAgent, https: config11.httpsAgent },
+          agents: { http: config12.httpAgent, https: config12.httpsAgent },
           auth
         };
-        if (config11.socketPath) {
-          options.socketPath = config11.socketPath;
+        if (config12.socketPath) {
+          options.socketPath = config12.socketPath;
         } else {
           options.hostname = parsed.hostname;
           options.port = parsed.port;
         }
-        var proxy = config11.proxy;
+        var proxy = config12.proxy;
         if (!proxy && proxy !== false) {
           var proxyEnv = protocol.slice(0, -1) + "_proxy";
           var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()];
@@ -3079,28 +3079,28 @@ var require_http = __commonJS({
         }
         var transport;
         var isHttpsProxy = isHttpsRequest && (proxy ? isHttps2.test(proxy.protocol) : true);
-        if (config11.transport) {
-          transport = config11.transport;
-        } else if (config11.maxRedirects === 0) {
+        if (config12.transport) {
+          transport = config12.transport;
+        } else if (config12.maxRedirects === 0) {
           transport = isHttpsProxy ? https3 : http3;
         } else {
-          if (config11.maxRedirects) {
-            options.maxRedirects = config11.maxRedirects;
+          if (config12.maxRedirects) {
+            options.maxRedirects = config12.maxRedirects;
           }
           transport = isHttpsProxy ? httpsFollow2 : httpFollow2;
         }
-        if (config11.maxBodyLength > -1) {
-          options.maxBodyLength = config11.maxBodyLength;
+        if (config12.maxBodyLength > -1) {
+          options.maxBodyLength = config12.maxBodyLength;
         }
-        if (config11.insecureHTTPParser) {
-          options.insecureHTTPParser = config11.insecureHTTPParser;
+        if (config12.insecureHTTPParser) {
+          options.insecureHTTPParser = config12.insecureHTTPParser;
         }
         var req = transport.request(options, function handleResponse(res) {
           if (req.aborted)
             return;
           var stream4 = res;
           var lastRequest = res.req || req;
-          if (res.statusCode !== 204 && lastRequest.method !== "HEAD" && config11.decompress !== false) {
+          if (res.statusCode !== 204 && lastRequest.method !== "HEAD" && config12.decompress !== false) {
             switch (res.headers["content-encoding"]) {
               case "gzip":
               case "compress":
@@ -3114,10 +3114,10 @@ var require_http = __commonJS({
             status: res.statusCode,
             statusText: res.statusMessage,
             headers: res.headers,
-            config: config11,
+            config: config12,
             request: lastRequest
           };
-          if (config11.responseType === "stream") {
+          if (config12.responseType === "stream") {
             response.data = stream4;
             settle2(resolve, reject, response);
           } else {
@@ -3126,12 +3126,12 @@ var require_http = __commonJS({
             stream4.on("data", function handleStreamData(chunk) {
               responseBuffer.push(chunk);
               totalResponseBytes += chunk.length;
-              if (config11.maxContentLength > -1 && totalResponseBytes > config11.maxContentLength) {
+              if (config12.maxContentLength > -1 && totalResponseBytes > config12.maxContentLength) {
                 rejected = true;
                 stream4.destroy();
                 reject(createError(
-                  "maxContentLength size of " + config11.maxContentLength + " exceeded",
-                  config11,
+                  "maxContentLength size of " + config12.maxContentLength + " exceeded",
+                  config12,
                   null,
                   lastRequest
                 ));
@@ -3142,25 +3142,25 @@ var require_http = __commonJS({
                 return;
               }
               stream4.destroy();
-              reject(createError("error request aborted", config11, "ERR_REQUEST_ABORTED", lastRequest));
+              reject(createError("error request aborted", config12, "ERR_REQUEST_ABORTED", lastRequest));
             });
             stream4.on("error", function handleStreamError(err) {
               if (req.aborted)
                 return;
-              reject(enhanceError(err, config11, null, lastRequest));
+              reject(enhanceError(err, config12, null, lastRequest));
             });
             stream4.on("end", function handleStreamEnd() {
               try {
                 var responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
-                if (config11.responseType !== "arraybuffer") {
-                  responseData = responseData.toString(config11.responseEncoding);
-                  if (!config11.responseEncoding || config11.responseEncoding === "utf8") {
+                if (config12.responseType !== "arraybuffer") {
+                  responseData = responseData.toString(config12.responseEncoding);
+                  if (!config12.responseEncoding || config12.responseEncoding === "utf8") {
                     responseData = utils.stripBOM(responseData);
                   }
                 }
                 response.data = responseData;
               } catch (err) {
-                reject(enhanceError(err, config11, err.code, response.request, response));
+                reject(enhanceError(err, config12, err.code, response.request, response));
               }
               settle2(resolve, reject, response);
             });
@@ -3169,17 +3169,17 @@ var require_http = __commonJS({
         req.on("error", function handleRequestError(err) {
           if (req.aborted && err.code !== "ERR_FR_TOO_MANY_REDIRECTS")
             return;
-          reject(enhanceError(err, config11, null, req));
+          reject(enhanceError(err, config12, null, req));
         });
         req.on("socket", function handleRequestSocket(socket) {
           socket.setKeepAlive(true, 1e3 * 60);
         });
-        if (config11.timeout) {
-          var timeout = parseInt(config11.timeout, 10);
+        if (config12.timeout) {
+          var timeout = parseInt(config12.timeout, 10);
           if (isNaN(timeout)) {
             reject(createError(
               "error trying to parse `config.timeout` to int",
-              config11,
+              config12,
               "ERR_PARSE_TIMEOUT",
               req
             ));
@@ -3188,35 +3188,35 @@ var require_http = __commonJS({
           req.setTimeout(timeout, function handleRequestTimeout() {
             req.abort();
             var timeoutErrorMessage = "";
-            if (config11.timeoutErrorMessage) {
-              timeoutErrorMessage = config11.timeoutErrorMessage;
+            if (config12.timeoutErrorMessage) {
+              timeoutErrorMessage = config12.timeoutErrorMessage;
             } else {
-              timeoutErrorMessage = "timeout of " + config11.timeout + "ms exceeded";
+              timeoutErrorMessage = "timeout of " + config12.timeout + "ms exceeded";
             }
-            var transitional2 = config11.transitional || transitionalDefaults;
+            var transitional2 = config12.transitional || transitionalDefaults;
             reject(createError(
               timeoutErrorMessage,
-              config11,
+              config12,
               transitional2.clarifyTimeoutError ? "ETIMEDOUT" : "ECONNABORTED",
               req
             ));
           });
         }
-        if (config11.cancelToken || config11.signal) {
+        if (config12.cancelToken || config12.signal) {
           onCanceled = function(cancel) {
             if (req.aborted)
               return;
             req.abort();
             reject(!cancel || cancel && cancel.type ? new Cancel2("canceled") : cancel);
           };
-          config11.cancelToken && config11.cancelToken.subscribe(onCanceled);
-          if (config11.signal) {
-            config11.signal.aborted ? onCanceled() : config11.signal.addEventListener("abort", onCanceled);
+          config12.cancelToken && config12.cancelToken.subscribe(onCanceled);
+          if (config12.signal) {
+            config12.signal.aborted ? onCanceled() : config12.signal.addEventListener("abort", onCanceled);
           }
         }
         if (utils.isStream(data)) {
           data.on("error", function handleStreamError(err) {
-            reject(enhanceError(err, config11, null, req));
+            reject(enhanceError(err, config12, null, req));
           }).pipe(req);
         } else {
           req.end(data);
@@ -3364,53 +3364,53 @@ var require_dispatchRequest = __commonJS({
     var isCancel3 = require_isCancel();
     var defaults2 = require_defaults();
     var Cancel2 = require_Cancel();
-    function throwIfCancellationRequested2(config11) {
-      if (config11.cancelToken) {
-        config11.cancelToken.throwIfRequested();
+    function throwIfCancellationRequested2(config12) {
+      if (config12.cancelToken) {
+        config12.cancelToken.throwIfRequested();
       }
-      if (config11.signal && config11.signal.aborted) {
+      if (config12.signal && config12.signal.aborted) {
         throw new Cancel2("canceled");
       }
     }
-    module2.exports = function dispatchRequest2(config11) {
-      throwIfCancellationRequested2(config11);
-      config11.headers = config11.headers || {};
-      config11.data = transformData2.call(
-        config11,
-        config11.data,
-        config11.headers,
-        config11.transformRequest
+    module2.exports = function dispatchRequest2(config12) {
+      throwIfCancellationRequested2(config12);
+      config12.headers = config12.headers || {};
+      config12.data = transformData2.call(
+        config12,
+        config12.data,
+        config12.headers,
+        config12.transformRequest
       );
-      config11.headers = utils.merge(
-        config11.headers.common || {},
-        config11.headers[config11.method] || {},
-        config11.headers
+      config12.headers = utils.merge(
+        config12.headers.common || {},
+        config12.headers[config12.method] || {},
+        config12.headers
       );
       utils.forEach(
         ["delete", "get", "head", "post", "put", "patch", "common"],
         function cleanHeaderConfig(method) {
-          delete config11.headers[method];
+          delete config12.headers[method];
         }
       );
-      var adapter = config11.adapter || defaults2.adapter;
-      return adapter(config11).then(function onAdapterResolution(response) {
-        throwIfCancellationRequested2(config11);
+      var adapter = config12.adapter || defaults2.adapter;
+      return adapter(config12).then(function onAdapterResolution(response) {
+        throwIfCancellationRequested2(config12);
         response.data = transformData2.call(
-          config11,
+          config12,
           response.data,
           response.headers,
-          config11.transformResponse
+          config12.transformResponse
         );
         return response;
       }, function onAdapterRejection(reason) {
         if (!isCancel3(reason)) {
-          throwIfCancellationRequested2(config11);
+          throwIfCancellationRequested2(config12);
           if (reason && reason.response) {
             reason.response.data = transformData2.call(
-              config11,
+              config12,
               reason.response.data,
               reason.response.headers,
-              config11.transformResponse
+              config12.transformResponse
             );
           }
         }
@@ -3427,7 +3427,7 @@ var require_mergeConfig = __commonJS({
     var utils = require_utils();
     module2.exports = function mergeConfig3(config1, config22) {
       config22 = config22 || {};
-      var config11 = {};
+      var config12 = {};
       function getMergedValue(target, source) {
         if (utils.isPlainObject(target) && utils.isPlainObject(source)) {
           return utils.merge(target, source);
@@ -3495,9 +3495,9 @@ var require_mergeConfig = __commonJS({
       utils.forEach(Object.keys(config1).concat(Object.keys(config22)), function computeConfigValue(prop) {
         var merge2 = mergeMap[prop] || mergeDeepProperties;
         var configValue = merge2(prop);
-        utils.isUndefined(configValue) && merge2 !== mergeDirectKeys || (config11[prop] = configValue);
+        utils.isUndefined(configValue) && merge2 !== mergeDirectKeys || (config12[prop] = configValue);
       });
-      return config11;
+      return config12;
     };
   }
 });
@@ -3581,22 +3581,22 @@ var require_Axios = __commonJS({
         response: new InterceptorManager2()
       };
     }
-    Axios3.prototype.request = function request3(configOrUrl, config11) {
+    Axios3.prototype.request = function request3(configOrUrl, config12) {
       if (typeof configOrUrl === "string") {
-        config11 = config11 || {};
-        config11.url = configOrUrl;
+        config12 = config12 || {};
+        config12.url = configOrUrl;
       } else {
-        config11 = configOrUrl || {};
+        config12 = configOrUrl || {};
       }
-      config11 = mergeConfig3(this.defaults, config11);
-      if (config11.method) {
-        config11.method = config11.method.toLowerCase();
+      config12 = mergeConfig3(this.defaults, config12);
+      if (config12.method) {
+        config12.method = config12.method.toLowerCase();
       } else if (this.defaults.method) {
-        config11.method = this.defaults.method.toLowerCase();
+        config12.method = this.defaults.method.toLowerCase();
       } else {
-        config11.method = "get";
+        config12.method = "get";
       }
-      var transitional2 = config11.transitional;
+      var transitional2 = config12.transitional;
       if (transitional2 !== void 0) {
         validator.assertOptions(transitional2, {
           silentJSONParsing: validators3.transitional(validators3.boolean),
@@ -3607,7 +3607,7 @@ var require_Axios = __commonJS({
       var requestInterceptorChain = [];
       var synchronousRequestInterceptors = true;
       this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
-        if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config11) === false) {
+        if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config12) === false) {
           return;
         }
         synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
@@ -3622,13 +3622,13 @@ var require_Axios = __commonJS({
         var chain = [dispatchRequest2, void 0];
         Array.prototype.unshift.apply(chain, requestInterceptorChain);
         chain = chain.concat(responseInterceptorChain);
-        promise = Promise.resolve(config11);
+        promise = Promise.resolve(config12);
         while (chain.length) {
           promise = promise.then(chain.shift(), chain.shift());
         }
         return promise;
       }
-      var newConfig = config11;
+      var newConfig = config12;
       while (requestInterceptorChain.length) {
         var onFulfilled = requestInterceptorChain.shift();
         var onRejected = requestInterceptorChain.shift();
@@ -3649,22 +3649,22 @@ var require_Axios = __commonJS({
       }
       return promise;
     };
-    Axios3.prototype.getUri = function getUri(config11) {
-      config11 = mergeConfig3(this.defaults, config11);
-      return buildURL2(config11.url, config11.params, config11.paramsSerializer).replace(/^\?/, "");
+    Axios3.prototype.getUri = function getUri(config12) {
+      config12 = mergeConfig3(this.defaults, config12);
+      return buildURL2(config12.url, config12.params, config12.paramsSerializer).replace(/^\?/, "");
     };
     utils.forEach(["delete", "get", "head", "options"], function forEachMethodNoData2(method) {
-      Axios3.prototype[method] = function(url2, config11) {
-        return this.request(mergeConfig3(config11 || {}, {
+      Axios3.prototype[method] = function(url2, config12) {
+        return this.request(mergeConfig3(config12 || {}, {
           method,
           url: url2,
-          data: (config11 || {}).data
+          data: (config12 || {}).data
         }));
       };
     });
     utils.forEach(["post", "put", "patch"], function forEachMethodWithData2(method) {
-      Axios3.prototype[method] = function(url2, data, config11) {
-        return this.request(mergeConfig3(config11 || {}, {
+      Axios3.prototype[method] = function(url2, data, config12) {
+        return this.request(mergeConfig3(config12 || {}, {
           method,
           url: url2,
           data
@@ -14799,7 +14799,7 @@ var require_main = __commonJS({
         return { parsed: parsedAll };
       }
     }
-    function config11(options) {
+    function config12(options) {
       if (_dotenvKey(options).length === 0) {
         return DotenvModule.configDotenv(options);
       }
@@ -14866,7 +14866,7 @@ var require_main = __commonJS({
       configDotenv,
       _configVault,
       _parseVault,
-      config: config11,
+      config: config12,
       decrypt,
       parse,
       populate
@@ -30567,8 +30567,8 @@ var vi_VN_default = {
 // src/i18n/zh_CN.json
 var zh_CN_default = {
   localLanguage: "\u7B80\u4F53\u4E2D\u6587",
-  commitFix: "\u4FEE\u590D(server.ts)\uFF1A\u5C06\u7AEF\u53E3\u53D8\u91CF\u4ECE\u5C0F\u5199port\u6539\u4E3A\u5927\u5199PORT",
-  commitFeat: "\u529F\u80FD(server.ts)\uFF1A\u6DFB\u52A0\u5BF9process.env.PORT\u73AF\u5883\u53D8\u91CF\u7684\u652F\u6301",
+  commitFix: "fix(server.ts)\uFF1A\u5C06\u7AEF\u53E3\u53D8\u91CF\u4ECE\u5C0F\u5199port\u6539\u4E3A\u5927\u5199PORT",
+  commitFeat: "feat(server.ts)\uFF1A\u6DFB\u52A0\u5BF9process.env.PORT\u73AF\u5883\u53D8\u91CF\u7684\u652F\u6301",
   commitDescription: "\u73B0\u5728\u7AEF\u53E3\u53D8\u91CF\u88AB\u547D\u540D\u4E3APORT\uFF0C\u8FD9\u63D0\u9AD8\u4E86\u547D\u540D\u7EA6\u5B9A\u7684\u4E00\u81F4\u6027\uFF0C\u56E0\u4E3APORT\u662F\u4E00\u4E2A\u5E38\u91CF\u3002\u73AF\u5883\u53D8\u91CF\u7684\u652F\u6301\u4F7F\u5E94\u7528\u7A0B\u5E8F\u66F4\u52A0\u7075\u6D3B\uFF0C\u56E0\u4E3A\u5B83\u73B0\u5728\u53EF\u4EE5\u901A\u8FC7process.env.PORT\u73AF\u5883\u53D8\u91CF\u5728\u4EFB\u4F55\u53EF\u7528\u7AEF\u53E3\u4E0A\u8FD0\u884C\u3002"
 };
 
@@ -30640,8 +30640,8 @@ var TEST_MOCK_TYPES = [
 ];
 var TestAi = class {
   async generateCommitMessage(_messages) {
-    const config11 = getConfig();
-    switch (config11?.OCO_TEST_MOCK_TYPE) {
+    const config12 = getConfig();
+    switch (config12?.OCO_TEST_MOCK_TYPE) {
       case "commit-message":
         return "fix(testAi.ts): test commit message";
       case "prompt-module-commitlint-config":
@@ -30691,7 +30691,14 @@ var MODEL_LIST = {
     "claude-3-5-sonnet-20240620",
     "claude-3-opus-20240229",
     "claude-3-sonnet-20240229",
-    "claude-3-opus-20240229"
+    "claude-3-haiku-20240307"
+  ],
+  gemini: [
+    "gemini-1.5-flash",
+    "gemini-1.5-pro",
+    "gemini-1.0-pro",
+    "gemini-pro-vision",
+    "text-embedding-004"
   ]
 };
 var getDefaultModel = (provider4) => {
@@ -30715,43 +30722,43 @@ var validateConfig = (key, condition, validationMessage) => {
   }
 };
 var configValidators = {
-  ["OCO_OPENAI_API_KEY" /* OCO_OPENAI_API_KEY */](value, config11 = {}) {
-    if (config11.OCO_AI_PROVIDER == "gemini")
+  ["OCO_OPENAI_API_KEY" /* OCO_OPENAI_API_KEY */](value, config12 = {}) {
+    if (config12.OCO_AI_PROVIDER == "gemini")
       return value;
     validateConfig(
       "OpenAI API_KEY",
-      value || config11.OCO_ANTHROPIC_API_KEY || config11.OCO_AI_PROVIDER.startsWith("ollama") || config11.OCO_AZURE_API_KEY || config11.OCO_AI_PROVIDER == "test",
+      value || config12.OCO_ANTHROPIC_API_KEY || config12.OCO_AI_PROVIDER.startsWith("ollama") || config12.OCO_AZURE_API_KEY || config12.OCO_AI_PROVIDER == "llmservice" || config12.OCO_AI_PROVIDER == "test",
       "You need to provide an OpenAI/Anthropic/Azure API key"
     );
     validateConfig(
       "OCO_OPENAI_API_KEY" /* OCO_OPENAI_API_KEY */,
-      value.startsWith("sk-") || config11.OCO_AI_PROVIDER != "openai",
+      value.startsWith("sk-") || config12.OCO_AI_PROVIDER != "openai",
       'Must start with "sk-" for openai provider'
     );
     return value;
   },
-  ["OCO_AZURE_API_KEY" /* OCO_AZURE_API_KEY */](value, config11 = {}) {
+  ["OCO_AZURE_API_KEY" /* OCO_AZURE_API_KEY */](value, config12 = {}) {
     validateConfig(
       "ANTHROPIC_API_KEY",
-      value || config11.OCO_OPENAI_API_KEY || config11.OCO_AZURE_API_KEY || config11.OCO_AI_PROVIDER == "ollama" || config11.OCO_AI_PROVIDER == "test",
+      value || config12.OCO_OPENAI_API_KEY || config12.OCO_AZURE_API_KEY || config12.OCO_AI_PROVIDER == "ollama" || config12.OCO_AI_PROVIDER == "llmservice" || config12.OCO_AI_PROVIDER == "test",
       "You need to provide an OpenAI/Anthropic/Azure API key"
     );
     return value;
   },
-  ["OCO_GEMINI_API_KEY" /* OCO_GEMINI_API_KEY */](value, config11 = {}) {
-    if (config11.OCO_AI_PROVIDER != "gemini")
+  ["OCO_GEMINI_API_KEY" /* OCO_GEMINI_API_KEY */](value, config12 = {}) {
+    if (config12.OCO_AI_PROVIDER != "gemini")
       return value;
     validateConfig(
       "Gemini API Key",
-      value || config11.OCO_GEMINI_API_KEY || config11.OCO_AI_PROVIDER == "test",
+      value || config12.OCO_GEMINI_API_KEY || config12.OCO_AI_PROVIDER == "test",
       "You need to provide an Gemini API key"
     );
     return value;
   },
-  ["OCO_ANTHROPIC_API_KEY" /* OCO_ANTHROPIC_API_KEY */](value, config11 = {}) {
+  ["OCO_ANTHROPIC_API_KEY" /* OCO_ANTHROPIC_API_KEY */](value, config12 = {}) {
     validateConfig(
       "ANTHROPIC_API_KEY",
-      value || config11.OCO_OPENAI_API_KEY || config11.OCO_AI_PROVIDER == "ollama" || config11.OCO_AI_PROVIDER == "test",
+      value || config12.OCO_OPENAI_API_KEY || config12.OCO_AI_PROVIDER == "ollama" || config12.OCO_AI_PROVIDER == "llmservice" || config12.OCO_AI_PROVIDER == "test",
       "You need to provide an OpenAI/Anthropic API key"
     );
     return value;
@@ -30820,14 +30827,14 @@ var configValidators = {
     );
     return value;
   },
-  ["OCO_MODEL" /* OCO_MODEL */](value, config11 = {}) {
+  ["OCO_MODEL" /* OCO_MODEL */](value, config12 = {}) {
     validateConfig(
       "OCO_MODEL" /* OCO_MODEL */,
       [
         ...MODEL_LIST.openai,
         ...MODEL_LIST.anthropic,
         ...MODEL_LIST.gemini
-      ].includes(value) || config11.OCO_AI_PROVIDER == "ollama" || config11.OCO_AI_PROVIDER == "azure" || config11.OCO_AI_PROVIDER == "test",
+      ].includes(value) || config12.OCO_AI_PROVIDER == "ollama" || config12.OCO_AI_PROVIDER == "azure" || config12.OCO_AI_PROVIDER == "llmservice" || config12.OCO_AI_PROVIDER == "test",
       `${value} is not supported yet, use:
 
  ${[
@@ -30865,8 +30872,8 @@ var configValidators = {
   ["OCO_AI_PROVIDER" /* OCO_AI_PROVIDER */](value) {
     validateConfig(
       "OCO_AI_PROVIDER" /* OCO_AI_PROVIDER */,
-      ["", "openai", "anthropic", "gemini", "azure", "test"].includes(value) || value.startsWith("ollama"),
-      `${value} is not supported yet, use 'ollama', 'anthropic', 'azure', 'gemini' or 'openai' (default)`
+      ["", "openai", "anthropic", "gemini", "azure", "llmservice", "test"].includes(value) || value.startsWith("ollama"),
+      `${value} is not supported yet, use 'ollama', 'llmservice', 'anthropic', 'azure', 'gemini', or 'openai' (default)`
     );
     return value;
   },
@@ -30903,6 +30910,22 @@ var configValidators = {
       `${value} is not a valid URL`
     );
     return value;
+  },
+  ["OCO_BACKEND_ENDPOINT" /* OCO_BACKEND_ENDPOINT */](value) {
+    validateConfig(
+      "OCO_BACKEND_ENDPOINT" /* OCO_BACKEND_ENDPOINT */,
+      typeof value === "string",
+      "Must be string"
+    );
+    return value;
+  },
+  ["OCO_BACKEND_PATH" /* OCO_BACKEND_PATH */](value) {
+    validateConfig(
+      "OCO_BACKEND_PATH" /* OCO_BACKEND_PATH */,
+      typeof value === "string",
+      "Must be string"
+    );
+    return value;
   }
 };
 var defaultConfigPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit");
@@ -30930,26 +30953,28 @@ var getConfig = ({
     OCO_AI_PROVIDER: process.env.OCO_AI_PROVIDER || "openai",
     OCO_GITPUSH: process.env.OCO_GITPUSH === "false" ? false : true,
     OCO_ONE_LINE_COMMIT: process.env.OCO_ONE_LINE_COMMIT === "true" ? true : false,
-    OCO_AZURE_ENDPOINT: process.env.OCO_AZURE_ENDPOINT || "",
-    OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE || "commit-message"
+    OCO_AZURE_ENDPOINT: process.env.OCO_AZURE_ENDPOINT || void 0,
+    OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE || "commit-message",
+    OCO_BACKEND_ENDPOINT: process.env.OCO_BACKEND_ENDPOINT || "localhost:8000",
+    OCO_BACKEND_PATH: process.env.OCO_BACKEND_PATH || "api/generate"
   };
   const configExists = (0, import_fs.existsSync)(configPath);
   if (!configExists)
     return configFromEnv;
   const configFile = (0, import_fs.readFileSync)(configPath, "utf8");
-  const config11 = (0, import_ini.parse)(configFile);
-  for (const configKey of Object.keys(config11)) {
-    if (["null", "undefined"].includes(config11[configKey])) {
-      config11[configKey] = void 0;
+  const config12 = (0, import_ini.parse)(configFile);
+  for (const configKey of Object.keys(config12)) {
+    if (["null", "undefined"].includes(config12[configKey])) {
+      config12[configKey] = void 0;
       continue;
     }
     try {
       const validator = configValidators[configKey];
       const validValue = validator(
-        config11[configKey] ?? configFromEnv[configKey],
-        config11
+        config12[configKey] ?? configFromEnv[configKey],
+        config12
       );
-      config11[configKey] = validValue;
+      config12[configKey] = validValue;
     } catch (error) {
       ce(`Unknown '${configKey}' config option or missing validator.`);
       ce(
@@ -30958,10 +30983,10 @@ var getConfig = ({
       process.exit(1);
     }
   }
-  return config11;
+  return config12;
 };
 var setConfig = (keyValues, configPath = defaultConfigPath) => {
-  const config11 = getConfig() || {};
+  const config12 = getConfig() || {};
   for (const [configKey, configValue] of keyValues) {
     if (!configValidators.hasOwnProperty(configKey)) {
       throw new Error(`Unsupported config key: ${configKey}`);
@@ -30973,9 +30998,9 @@ var setConfig = (keyValues, configPath = defaultConfigPath) => {
       parsedConfigValue = configValue;
     }
     const validValue = configValidators[configKey](parsedConfigValue);
-    config11[configKey] = validValue;
+    config12[configKey] = validValue;
   }
-  (0, import_fs.writeFileSync)(configPath, (0, import_ini.stringify)(config11), "utf8");
+  (0, import_fs.writeFileSync)(configPath, (0, import_ini.stringify)(config12), "utf8");
   ce(`${source_default.green("\u2714")} Config successfully set`);
 };
 var configCommand = G3(
@@ -30988,9 +31013,9 @@ var configCommand = G3(
     try {
       const { mode: mode4, keyValues } = argv._;
       if (mode4 === "get" /* get */) {
-        const config11 = getConfig() || {};
+        const config12 = getConfig() || {};
         for (const key of keyValues) {
-          ce(`${key}=${config11[key]}`);
+          ce(`${key}=${config12[key]}`);
         }
       } else if (mode4 === "set" /* set */) {
         await setConfig(
@@ -31099,8 +31124,8 @@ var getPrompt = (ruleName, ruleConfig, prompt) => {
   ce(`${source_default.red("\u2716")} No prompt handler for rule "${ruleName}".`);
   return `Please manualy set the prompt for rule "${ruleName}".`;
 };
-var inferPromptsFromCommitlintConfig = (config11) => {
-  const { rules, prompt } = config11;
+var inferPromptsFromCommitlintConfig = (config12) => {
+  const { rules, prompt } = config12;
   if (!rules)
     return [];
   return Object.keys(rules).map(
@@ -31613,7 +31638,7 @@ var utils_default = {
 };
 
 // node_modules/axios/lib/core/AxiosError.js
-function AxiosError(message, code, config11, request3, response) {
+function AxiosError(message, code, config12, request3, response) {
   Error.call(this);
   if (Error.captureStackTrace) {
     Error.captureStackTrace(this, this.constructor);
@@ -31623,7 +31648,7 @@ function AxiosError(message, code, config11, request3, response) {
   this.message = message;
   this.name = "AxiosError";
   code && (this.code = code);
-  config11 && (this.config = config11);
+  config12 && (this.config = config12);
   request3 && (this.request = request3);
   response && (this.response = response);
 }
@@ -31664,14 +31689,14 @@ var descriptors2 = {};
 });
 Object.defineProperties(AxiosError, descriptors2);
 Object.defineProperty(prototype, "isAxiosError", { value: true });
-AxiosError.from = (error, code, config11, request3, response, customProps) => {
+AxiosError.from = (error, code, config12, request3, response, customProps) => {
   const axiosError = Object.create(prototype);
   utils_default.toFlatObject(error, axiosError, function filter2(obj) {
     return obj !== Error.prototype;
   }, (prop) => {
     return prop !== "isAxiosError";
   });
-  AxiosError.call(axiosError, error.message, code, config11, request3, response);
+  AxiosError.call(axiosError, error.message, code, config12, request3, response);
   axiosError.cause = error;
   axiosError.name = error.name;
   customProps && Object.assign(axiosError, customProps);
@@ -32367,12 +32392,12 @@ var AxiosHeaders_default = AxiosHeaders;
 
 // node_modules/axios/lib/core/transformData.js
 function transformData(fns, response) {
-  const config11 = this || defaults_default;
-  const context = response || config11;
+  const config12 = this || defaults_default;
+  const context = response || config12;
   const headers = AxiosHeaders_default.from(context.headers);
   let data = context.data;
   utils_default.forEach(fns, function transform(fn) {
-    data = fn.call(config11, data, headers.normalize(), response ? response.status : void 0);
+    data = fn.call(config12, data, headers.normalize(), response ? response.status : void 0);
   });
   headers.normalize();
   return data;
@@ -32384,8 +32409,8 @@ function isCancel(value) {
 }
 
 // node_modules/axios/lib/cancel/CanceledError.js
-function CanceledError(message, config11, request3) {
-  AxiosError_default.call(this, message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config11, request3);
+function CanceledError(message, config12, request3) {
+  AxiosError_default.call(this, message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config12, request3);
   this.name = "CanceledError";
 }
 utils_default.inherits(CanceledError, AxiosError_default, {
@@ -32917,11 +32942,11 @@ var resolveFamily = ({ address, family }) => {
   };
 };
 var buildAddressEntry = (address, family) => resolveFamily(utils_default.isObject(address) ? address : { address, family });
-var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
+var http_default = isHttpAdapterSupported && function httpAdapter(config12) {
   return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) {
-    let { data, lookup, family } = config11;
-    const { responseType, responseEncoding } = config11;
-    const method = config11.method.toUpperCase();
+    let { data, lookup, family } = config12;
+    const { responseType, responseEncoding } = config12;
+    const method = config12.method.toUpperCase();
     let isDone;
     let rejected = false;
     let req;
@@ -32939,11 +32964,11 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
     }
     const emitter = new import_events.EventEmitter();
     const onFinished = () => {
-      if (config11.cancelToken) {
-        config11.cancelToken.unsubscribe(abort);
+      if (config12.cancelToken) {
+        config12.cancelToken.unsubscribe(abort);
       }
-      if (config11.signal) {
-        config11.signal.removeEventListener("abort", abort);
+      if (config12.signal) {
+        config12.signal.removeEventListener("abort", abort);
       }
       emitter.removeAllListeners();
     };
@@ -32955,16 +32980,16 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
       }
     });
     function abort(reason) {
-      emitter.emit("abort", !reason || reason.type ? new CanceledError_default(null, config11, req) : reason);
+      emitter.emit("abort", !reason || reason.type ? new CanceledError_default(null, config12, req) : reason);
     }
     emitter.once("abort", reject);
-    if (config11.cancelToken || config11.signal) {
-      config11.cancelToken && config11.cancelToken.subscribe(abort);
-      if (config11.signal) {
-        config11.signal.aborted ? abort() : config11.signal.addEventListener("abort", abort);
+    if (config12.cancelToken || config12.signal) {
+      config12.cancelToken && config12.cancelToken.subscribe(abort);
+      if (config12.signal) {
+        config12.signal.aborted ? abort() : config12.signal.addEventListener("abort", abort);
       }
     }
-    const fullPath = buildFullPath(config11.baseURL, config11.url);
+    const fullPath = buildFullPath(config12.baseURL, config12.url);
     const parsed = new URL(fullPath, "http://localhost");
     const protocol = parsed.protocol || supportedProtocols[0];
     if (protocol === "data:") {
@@ -32974,15 +32999,15 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
           status: 405,
           statusText: "method not allowed",
           headers: {},
-          config: config11
+          config: config12
         });
       }
       try {
-        convertedData = fromDataURI(config11.url, responseType === "blob", {
-          Blob: config11.env && config11.env.Blob
+        convertedData = fromDataURI(config12.url, responseType === "blob", {
+          Blob: config12.env && config12.env.Blob
         });
       } catch (err) {
-        throw AxiosError_default.from(err, AxiosError_default.ERR_BAD_REQUEST, config11);
+        throw AxiosError_default.from(err, AxiosError_default.ERR_BAD_REQUEST, config12);
       }
       if (responseType === "text") {
         convertedData = convertedData.toString(responseEncoding);
@@ -32997,21 +33022,21 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
         status: 200,
         statusText: "OK",
         headers: new AxiosHeaders_default(),
-        config: config11
+        config: config12
       });
     }
     if (supportedProtocols.indexOf(protocol) === -1) {
       return reject(new AxiosError_default(
         "Unsupported protocol " + protocol,
         AxiosError_default.ERR_BAD_REQUEST,
-        config11
+        config12
       ));
     }
-    const headers = AxiosHeaders_default.from(config11.headers).normalize();
+    const headers = AxiosHeaders_default.from(config12.headers).normalize();
     headers.set("User-Agent", "axios/" + VERSION, false);
-    const onDownloadProgress = config11.onDownloadProgress;
-    const onUploadProgress = config11.onUploadProgress;
-    const maxRate = config11.maxRate;
+    const onDownloadProgress = config12.onDownloadProgress;
+    const onUploadProgress = config12.onUploadProgress;
+    const maxRate = config12.maxRate;
     let maxUploadRate = void 0;
     let maxDownloadRate = void 0;
     if (utils_default.isSpecCompliantForm(data)) {
@@ -33045,15 +33070,15 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
         return reject(new AxiosError_default(
           "Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream",
           AxiosError_default.ERR_BAD_REQUEST,
-          config11
+          config12
         ));
       }
       headers.setContentLength(data.length, false);
-      if (config11.maxBodyLength > -1 && data.length > config11.maxBodyLength) {
+      if (config12.maxBodyLength > -1 && data.length > config12.maxBodyLength) {
         return reject(new AxiosError_default(
           "Request body larger than maxBodyLength limit",
           AxiosError_default.ERR_BAD_REQUEST,
-          config11
+          config12
         ));
       }
     }
@@ -33079,9 +33104,9 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
       });
     }
     let auth = void 0;
-    if (config11.auth) {
-      const username = config11.auth.username || "";
-      const password = config11.auth.password || "";
+    if (config12.auth) {
+      const username = config12.auth.username || "";
+      const password = config12.auth.password || "";
       auth = username + ":" + password;
     }
     if (!auth && parsed.username) {
@@ -33094,13 +33119,13 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
     try {
       path5 = buildURL(
         parsed.pathname + parsed.search,
-        config11.params,
-        config11.paramsSerializer
+        config12.params,
+        config12.paramsSerializer
       ).replace(/^\?/, "");
     } catch (err) {
       const customErr = new Error(err.message);
-      customErr.config = config11;
-      customErr.url = config11.url;
+      customErr.config = config12;
+      customErr.url = config12.url;
       customErr.exists = true;
       return reject(customErr);
     }
@@ -33113,7 +33138,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
       path: path5,
       method,
       headers: headers.toJSON(),
-      agents: { http: config11.httpAgent, https: config11.httpsAgent },
+      agents: { http: config12.httpAgent, https: config12.httpsAgent },
       auth,
       protocol,
       family,
@@ -33121,36 +33146,36 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
       beforeRedirects: {}
     };
     !utils_default.isUndefined(lookup) && (options.lookup = lookup);
-    if (config11.socketPath) {
-      options.socketPath = config11.socketPath;
+    if (config12.socketPath) {
+      options.socketPath = config12.socketPath;
     } else {
       options.hostname = parsed.hostname;
       options.port = parsed.port;
-      setProxy(options, config11.proxy, protocol + "//" + parsed.hostname + (parsed.port ? ":" + parsed.port : "") + options.path);
+      setProxy(options, config12.proxy, protocol + "//" + parsed.hostname + (parsed.port ? ":" + parsed.port : "") + options.path);
     }
     let transport;
     const isHttpsRequest = isHttps.test(options.protocol);
-    options.agent = isHttpsRequest ? config11.httpsAgent : config11.httpAgent;
-    if (config11.transport) {
-      transport = config11.transport;
-    } else if (config11.maxRedirects === 0) {
+    options.agent = isHttpsRequest ? config12.httpsAgent : config12.httpAgent;
+    if (config12.transport) {
+      transport = config12.transport;
+    } else if (config12.maxRedirects === 0) {
       transport = isHttpsRequest ? import_https.default : import_http.default;
     } else {
-      if (config11.maxRedirects) {
-        options.maxRedirects = config11.maxRedirects;
+      if (config12.maxRedirects) {
+        options.maxRedirects = config12.maxRedirects;
       }
-      if (config11.beforeRedirect) {
-        options.beforeRedirects.config = config11.beforeRedirect;
+      if (config12.beforeRedirect) {
+        options.beforeRedirects.config = config12.beforeRedirect;
       }
       transport = isHttpsRequest ? httpsFollow : httpFollow;
     }
-    if (config11.maxBodyLength > -1) {
-      options.maxBodyLength = config11.maxBodyLength;
+    if (config12.maxBodyLength > -1) {
+      options.maxBodyLength = config12.maxBodyLength;
     } else {
       options.maxBodyLength = Infinity;
     }
-    if (config11.insecureHTTPParser) {
-      options.insecureHTTPParser = config11.insecureHTTPParser;
+    if (config12.insecureHTTPParser) {
+      options.insecureHTTPParser = config12.insecureHTTPParser;
     }
     req = transport.request(options, function handleResponse(res) {
       if (req.destroyed)
@@ -33171,7 +33196,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
       }
       let responseStream = res;
       const lastRequest = res.req || req;
-      if (config11.decompress !== false && res.headers["content-encoding"]) {
+      if (config12.decompress !== false && res.headers["content-encoding"]) {
         if (method === "HEAD" || res.statusCode === 204) {
           delete res.headers["content-encoding"];
         }
@@ -33204,7 +33229,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
         status: res.statusCode,
         statusText: res.statusMessage,
         headers: new AxiosHeaders_default(res.headers),
-        config: config11,
+        config: config12,
         request: lastRequest
       };
       if (responseType === "stream") {
@@ -33216,13 +33241,13 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
         responseStream.on("data", function handleStreamData(chunk) {
           responseBuffer.push(chunk);
           totalResponseBytes += chunk.length;
-          if (config11.maxContentLength > -1 && totalResponseBytes > config11.maxContentLength) {
+          if (config12.maxContentLength > -1 && totalResponseBytes > config12.maxContentLength) {
             rejected = true;
             responseStream.destroy();
             reject(new AxiosError_default(
-              "maxContentLength size of " + config11.maxContentLength + " exceeded",
+              "maxContentLength size of " + config12.maxContentLength + " exceeded",
               AxiosError_default.ERR_BAD_RESPONSE,
-              config11,
+              config12,
               lastRequest
             ));
           }
@@ -33232,9 +33257,9 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
             return;
           }
           const err = new AxiosError_default(
-            "maxContentLength size of " + config11.maxContentLength + " exceeded",
+            "maxContentLength size of " + config12.maxContentLength + " exceeded",
             AxiosError_default.ERR_BAD_RESPONSE,
-            config11,
+            config12,
             lastRequest
           );
           responseStream.destroy(err);
@@ -33243,7 +33268,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
         responseStream.on("error", function handleStreamError(err) {
           if (req.destroyed)
             return;
-          reject(AxiosError_default.from(err, null, config11, lastRequest));
+          reject(AxiosError_default.from(err, null, config12, lastRequest));
         });
         responseStream.on("end", function handleStreamEnd() {
           try {
@@ -33256,7 +33281,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
             }
             response.data = responseData;
           } catch (err) {
-            return reject(AxiosError_default.from(err, null, config11, response.request, response));
+            return reject(AxiosError_default.from(err, null, config12, response.request, response));
           }
           settle(resolve, reject, response);
         });
@@ -33273,18 +33298,18 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
       req.destroy(err);
     });
     req.on("error", function handleRequestError(err) {
-      reject(AxiosError_default.from(err, null, config11, req));
+      reject(AxiosError_default.from(err, null, config12, req));
     });
     req.on("socket", function handleRequestSocket(socket) {
       socket.setKeepAlive(true, 1e3 * 60);
     });
-    if (config11.timeout) {
-      const timeout = parseInt(config11.timeout, 10);
+    if (config12.timeout) {
+      const timeout = parseInt(config12.timeout, 10);
       if (Number.isNaN(timeout)) {
         reject(new AxiosError_default(
           "error trying to parse `config.timeout` to int",
           AxiosError_default.ERR_BAD_OPTION_VALUE,
-          config11,
+          config12,
           req
         ));
         return;
@@ -33292,15 +33317,15 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
       req.setTimeout(timeout, function handleRequestTimeout() {
         if (isDone)
           return;
-        let timeoutErrorMessage = config11.timeout ? "timeout of " + config11.timeout + "ms exceeded" : "timeout exceeded";
-        const transitional2 = config11.transitional || transitional_default;
-        if (config11.timeoutErrorMessage) {
-          timeoutErrorMessage = config11.timeoutErrorMessage;
+        let timeoutErrorMessage = config12.timeout ? "timeout of " + config12.timeout + "ms exceeded" : "timeout exceeded";
+        const transitional2 = config12.transitional || transitional_default;
+        if (config12.timeoutErrorMessage) {
+          timeoutErrorMessage = config12.timeoutErrorMessage;
         }
         reject(new AxiosError_default(
           timeoutErrorMessage,
           transitional2.clarifyTimeoutError ? AxiosError_default.ETIMEDOUT : AxiosError_default.ECONNABORTED,
-          config11,
+          config12,
           req
         ));
         abort();
@@ -33318,7 +33343,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
       });
       data.on("close", () => {
         if (!ended && !errored) {
-          abort(new CanceledError_default("Request stream has been aborted", config11, req));
+          abort(new CanceledError_default("Request stream has been aborted", config12, req));
         }
       });
       data.pipe(req);
@@ -33414,18 +33439,18 @@ function progressEventReducer(listener, isDownloadStream) {
   };
 }
 var isXHRAdapterSupported = typeof XMLHttpRequest !== "undefined";
-var xhr_default = isXHRAdapterSupported && function(config11) {
+var xhr_default = isXHRAdapterSupported && function(config12) {
   return new Promise(function dispatchXhrRequest(resolve, reject) {
-    let requestData = config11.data;
-    const requestHeaders = AxiosHeaders_default.from(config11.headers).normalize();
-    let { responseType, withXSRFToken } = config11;
+    let requestData = config12.data;
+    const requestHeaders = AxiosHeaders_default.from(config12.headers).normalize();
+    let { responseType, withXSRFToken } = config12;
     let onCanceled;
     function done() {
-      if (config11.cancelToken) {
-        config11.cancelToken.unsubscribe(onCanceled);
+      if (config12.cancelToken) {
+        config12.cancelToken.unsubscribe(onCanceled);
       }
-      if (config11.signal) {
-        config11.signal.removeEventListener("abort", onCanceled);
+      if (config12.signal) {
+        config12.signal.removeEventListener("abort", onCanceled);
       }
     }
     let contentType;
@@ -33438,14 +33463,14 @@ var xhr_default = isXHRAdapterSupported && function(config11) {
       }
     }
     let request3 = new XMLHttpRequest();
-    if (config11.auth) {
-      const username = config11.auth.username || "";
-      const password = config11.auth.password ? unescape(encodeURIComponent(config11.auth.password)) : "";
+    if (config12.auth) {
+      const username = config12.auth.username || "";
+      const password = config12.auth.password ? unescape(encodeURIComponent(config12.auth.password)) : "";
       requestHeaders.set("Authorization", "Basic " + btoa(username + ":" + password));
     }
-    const fullPath = buildFullPath(config11.baseURL, config11.url);
-    request3.open(config11.method.toUpperCase(), buildURL(fullPath, config11.params, config11.paramsSerializer), true);
-    request3.timeout = config11.timeout;
+    const fullPath = buildFullPath(config12.baseURL, config12.url);
+    request3.open(config12.method.toUpperCase(), buildURL(fullPath, config12.params, config12.paramsSerializer), true);
+    request3.timeout = config12.timeout;
     function onloadend() {
       if (!request3) {
         return;
@@ -33459,7 +33484,7 @@ var xhr_default = isXHRAdapterSupported && function(config11) {
         status: request3.status,
         statusText: request3.statusText,
         headers: responseHeaders,
-        config: config11,
+        config: config12,
         request: request3
       };
       settle(function _resolve(value) {
@@ -33488,33 +33513,33 @@ var xhr_default = isXHRAdapterSupported && function(config11) {
       if (!request3) {
         return;
       }
-      reject(new AxiosError_default("Request aborted", AxiosError_default.ECONNABORTED, config11, request3));
+      reject(new AxiosError_default("Request aborted", AxiosError_default.ECONNABORTED, config12, request3));
       request3 = null;
     };
     request3.onerror = function handleError() {
-      reject(new AxiosError_default("Network Error", AxiosError_default.ERR_NETWORK, config11, request3));
+      reject(new AxiosError_default("Network Error", AxiosError_default.ERR_NETWORK, config12, request3));
       request3 = null;
     };
     request3.ontimeout = function handleTimeout() {
-      let timeoutErrorMessage = config11.timeout ? "timeout of " + config11.timeout + "ms exceeded" : "timeout exceeded";
-      const transitional2 = config11.transitional || transitional_default;
-      if (config11.timeoutErrorMessage) {
-        timeoutErrorMessage = config11.timeoutErrorMessage;
+      let timeoutErrorMessage = config12.timeout ? "timeout of " + config12.timeout + "ms exceeded" : "timeout exceeded";
+      const transitional2 = config12.transitional || transitional_default;
+      if (config12.timeoutErrorMessage) {
+        timeoutErrorMessage = config12.timeoutErrorMessage;
       }
       reject(new AxiosError_default(
         timeoutErrorMessage,
         transitional2.clarifyTimeoutError ? AxiosError_default.ETIMEDOUT : AxiosError_default.ECONNABORTED,
-        config11,
+        config12,
         request3
       ));
       request3 = null;
     };
     if (platform_default.hasStandardBrowserEnv) {
-      withXSRFToken && utils_default.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config11));
+      withXSRFToken && utils_default.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config12));
       if (withXSRFToken || withXSRFToken !== false && isURLSameOrigin_default(fullPath)) {
-        const xsrfValue = config11.xsrfHeaderName && config11.xsrfCookieName && cookies_default.read(config11.xsrfCookieName);
+        const xsrfValue = config12.xsrfHeaderName && config12.xsrfCookieName && cookies_default.read(config12.xsrfCookieName);
         if (xsrfValue) {
-          requestHeaders.set(config11.xsrfHeaderName, xsrfValue);
+          requestHeaders.set(config12.xsrfHeaderName, xsrfValue);
         }
       }
     }
@@ -33524,35 +33549,35 @@ var xhr_default = isXHRAdapterSupported && function(config11) {
         request3.setRequestHeader(key, val);
       });
     }
-    if (!utils_default.isUndefined(config11.withCredentials)) {
-      request3.withCredentials = !!config11.withCredentials;
+    if (!utils_default.isUndefined(config12.withCredentials)) {
+      request3.withCredentials = !!config12.withCredentials;
     }
     if (responseType && responseType !== "json") {
-      request3.responseType = config11.responseType;
+      request3.responseType = config12.responseType;
     }
-    if (typeof config11.onDownloadProgress === "function") {
-      request3.addEventListener("progress", progressEventReducer(config11.onDownloadProgress, true));
+    if (typeof config12.onDownloadProgress === "function") {
+      request3.addEventListener("progress", progressEventReducer(config12.onDownloadProgress, true));
     }
-    if (typeof config11.onUploadProgress === "function" && request3.upload) {
-      request3.upload.addEventListener("progress", progressEventReducer(config11.onUploadProgress));
+    if (typeof config12.onUploadProgress === "function" && request3.upload) {
+      request3.upload.addEventListener("progress", progressEventReducer(config12.onUploadProgress));
     }
-    if (config11.cancelToken || config11.signal) {
+    if (config12.cancelToken || config12.signal) {
       onCanceled = (cancel) => {
         if (!request3) {
           return;
         }
-        reject(!cancel || cancel.type ? new CanceledError_default(null, config11, request3) : cancel);
+        reject(!cancel || cancel.type ? new CanceledError_default(null, config12, request3) : cancel);
         request3.abort();
         request3 = null;
       };
-      config11.cancelToken && config11.cancelToken.subscribe(onCanceled);
-      if (config11.signal) {
-        config11.signal.aborted ? onCanceled() : config11.signal.addEventListener("abort", onCanceled);
+      config12.cancelToken && config12.cancelToken.subscribe(onCanceled);
+      if (config12.signal) {
+        config12.signal.aborted ? onCanceled() : config12.signal.addEventListener("abort", onCanceled);
       }
     }
     const protocol = parseProtocol(fullPath);
     if (protocol && platform_default.protocols.indexOf(protocol) === -1) {
-      reject(new AxiosError_default("Unsupported protocol " + protocol + ":", AxiosError_default.ERR_BAD_REQUEST, config11));
+      reject(new AxiosError_default("Unsupported protocol " + protocol + ":", AxiosError_default.ERR_BAD_REQUEST, config12));
       return;
     }
     request3.send(requestData || null);
@@ -33613,41 +33638,41 @@ var adapters_default = {
 };
 
 // node_modules/axios/lib/core/dispatchRequest.js
-function throwIfCancellationRequested(config11) {
-  if (config11.cancelToken) {
-    config11.cancelToken.throwIfRequested();
+function throwIfCancellationRequested(config12) {
+  if (config12.cancelToken) {
+    config12.cancelToken.throwIfRequested();
   }
-  if (config11.signal && config11.signal.aborted) {
-    throw new CanceledError_default(null, config11);
+  if (config12.signal && config12.signal.aborted) {
+    throw new CanceledError_default(null, config12);
   }
 }
-function dispatchRequest(config11) {
-  throwIfCancellationRequested(config11);
-  config11.headers = AxiosHeaders_default.from(config11.headers);
-  config11.data = transformData.call(
-    config11,
-    config11.transformRequest
+function dispatchRequest(config12) {
+  throwIfCancellationRequested(config12);
+  config12.headers = AxiosHeaders_default.from(config12.headers);
+  config12.data = transformData.call(
+    config12,
+    config12.transformRequest
   );
-  if (["post", "put", "patch"].indexOf(config11.method) !== -1) {
-    config11.headers.setContentType("application/x-www-form-urlencoded", false);
+  if (["post", "put", "patch"].indexOf(config12.method) !== -1) {
+    config12.headers.setContentType("application/x-www-form-urlencoded", false);
   }
-  const adapter = adapters_default.getAdapter(config11.adapter || defaults_default.adapter);
-  return adapter(config11).then(function onAdapterResolution(response) {
-    throwIfCancellationRequested(config11);
+  const adapter = adapters_default.getAdapter(config12.adapter || defaults_default.adapter);
+  return adapter(config12).then(function onAdapterResolution(response) {
+    throwIfCancellationRequested(config12);
     response.data = transformData.call(
-      config11,
-      config11.transformResponse,
+      config12,
+      config12.transformResponse,
       response
     );
     response.headers = AxiosHeaders_default.from(response.headers);
     return response;
   }, function onAdapterRejection(reason) {
     if (!isCancel(reason)) {
-      throwIfCancellationRequested(config11);
+      throwIfCancellationRequested(config12);
       if (reason && reason.response) {
         reason.response.data = transformData.call(
-          config11,
-          config11.transformResponse,
+          config12,
+          config12.transformResponse,
           reason.response
         );
         reason.response.headers = AxiosHeaders_default.from(reason.response.headers);
@@ -33661,7 +33686,7 @@ function dispatchRequest(config11) {
 var headersToObject = (thing) => thing instanceof AxiosHeaders_default ? { ...thing } : thing;
 function mergeConfig(config1, config22) {
   config22 = config22 || {};
-  const config11 = {};
+  const config12 = {};
   function getMergedValue(target, source, caseless) {
     if (utils_default.isPlainObject(target) && utils_default.isPlainObject(source)) {
       return utils_default.merge.call({ caseless }, target, source);
@@ -33732,9 +33757,9 @@ function mergeConfig(config1, config22) {
   utils_default.forEach(Object.keys(Object.assign({}, config1, config22)), function computeConfigValue(prop) {
     const merge2 = mergeMap[prop] || mergeDeepProperties;
     const configValue = merge2(config1[prop], config22[prop], prop);
-    utils_default.isUndefined(configValue) && merge2 !== mergeDirectKeys || (config11[prop] = configValue);
+    utils_default.isUndefined(configValue) && merge2 !== mergeDirectKeys || (config12[prop] = configValue);
   });
-  return config11;
+  return config12;
 }
 
 // node_modules/axios/lib/helpers/validator.js
@@ -33805,9 +33830,9 @@ var Axios = class {
       response: new InterceptorManager_default()
     };
   }
-  async request(configOrUrl, config11) {
+  async request(configOrUrl, config12) {
     try {
-      return await this._request(configOrUrl, config11);
+      return await this._request(configOrUrl, config12);
     } catch (err) {
       if (err instanceof Error) {
         let dummy;
@@ -33822,15 +33847,15 @@ var Axios = class {
       throw err;
     }
   }
-  _request(configOrUrl, config11) {
+  _request(configOrUrl, config12) {
     if (typeof configOrUrl === "string") {
-      config11 = config11 || {};
-      config11.url = configOrUrl;
+      config12 = config12 || {};
+      config12.url = configOrUrl;
     } else {
-      config11 = configOrUrl || {};
+      config12 = configOrUrl || {};
     }
-    config11 = mergeConfig(this.defaults, config11);
-    const { transitional: transitional2, paramsSerializer, headers } = config11;
+    config12 = mergeConfig(this.defaults, config12);
+    const { transitional: transitional2, paramsSerializer, headers } = config12;
     if (transitional2 !== void 0) {
       validator_default.assertOptions(transitional2, {
         silentJSONParsing: validators2.transitional(validators2.boolean),
@@ -33840,7 +33865,7 @@ var Axios = class {
     }
     if (paramsSerializer != null) {
       if (utils_default.isFunction(paramsSerializer)) {
-        config11.paramsSerializer = {
+        config12.paramsSerializer = {
           serialize: paramsSerializer
         };
       } else {
@@ -33850,10 +33875,10 @@ var Axios = class {
         }, true);
       }
     }
-    config11.method = (config11.method || this.defaults.method || "get").toLowerCase();
+    config12.method = (config12.method || this.defaults.method || "get").toLowerCase();
     let contextHeaders = headers && utils_default.merge(
       headers.common,
-      headers[config11.method]
+      headers[config12.method]
     );
     headers && utils_default.forEach(
       ["delete", "get", "head", "post", "put", "patch", "common"],
@@ -33861,11 +33886,11 @@ var Axios = class {
         delete headers[method];
       }
     );
-    config11.headers = AxiosHeaders_default.concat(contextHeaders, headers);
+    config12.headers = AxiosHeaders_default.concat(contextHeaders, headers);
     const requestInterceptorChain = [];
     let synchronousRequestInterceptors = true;
     this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
-      if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config11) === false) {
+      if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config12) === false) {
         return;
       }
       synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
@@ -33883,14 +33908,14 @@ var Axios = class {
       chain.unshift.apply(chain, requestInterceptorChain);
       chain.push.apply(chain, responseInterceptorChain);
       len = chain.length;
-      promise = Promise.resolve(config11);
+      promise = Promise.resolve(config12);
       while (i3 < len) {
         promise = promise.then(chain[i3++], chain[i3++]);
       }
       return promise;
     }
     len = requestInterceptorChain.length;
-    let newConfig = config11;
+    let newConfig = config12;
     i3 = 0;
     while (i3 < len) {
       const onFulfilled = requestInterceptorChain[i3++];
@@ -33914,25 +33939,25 @@ var Axios = class {
     }
     return promise;
   }
-  getUri(config11) {
-    config11 = mergeConfig(this.defaults, config11);
-    const fullPath = buildFullPath(config11.baseURL, config11.url);
-    return buildURL(fullPath, config11.params, config11.paramsSerializer);
+  getUri(config12) {
+    config12 = mergeConfig(this.defaults, config12);
+    const fullPath = buildFullPath(config12.baseURL, config12.url);
+    return buildURL(fullPath, config12.params, config12.paramsSerializer);
   }
 };
 utils_default.forEach(["delete", "get", "head", "options"], function forEachMethodNoData(method) {
-  Axios.prototype[method] = function(url2, config11) {
-    return this.request(mergeConfig(config11 || {}, {
+  Axios.prototype[method] = function(url2, config12) {
+    return this.request(mergeConfig(config12 || {}, {
       method,
       url: url2,
-      data: (config11 || {}).data
+      data: (config12 || {}).data
     }));
   };
 });
 utils_default.forEach(["post", "put", "patch"], function forEachMethodWithData(method) {
   function generateHTTPMethod(isForm) {
-    return function httpMethod(url2, data, config11) {
-      return this.request(mergeConfig(config11 || {}, {
+    return function httpMethod(url2, data, config12) {
+      return this.request(mergeConfig(config12 || {}, {
         method,
         headers: isForm ? {
           "Content-Type": "multipart/form-data"
@@ -33978,11 +34003,11 @@ var CancelToken = class {
       };
       return promise;
     };
-    executor(function cancel(message, config11, request3) {
+    executor(function cancel(message, config12, request3) {
       if (token.reason) {
         return;
       }
-      token.reason = new CanceledError_default(message, config11, request3);
+      token.reason = new CanceledError_default(message, config12, request3);
       resolvePromise(token.reason);
     });
   }
@@ -41009,10 +41034,35 @@ var Azure = class {
 };
 var azure = new Azure();
 
+// src/engine/llmservice.ts
+var config7 = getConfig();
+var LlmService = class {
+  async generateCommitMessage(messages) {
+    const gitDiff = messages[messages.length - 1]?.content;
+    const url2 = `http://${config7?.OCO_BACKEND_ENDPOINT}/${config7?.OCO_BACKEND_PATH}`;
+    const payload = {
+      system_prompt: messages[0]?.content,
+      user_prompt: gitDiff
+    };
+    try {
+      const response = await axios_default.post(url2, payload, {
+        headers: {
+          "Content-Type": "application/json"
+        }
+      });
+      const message = response.data;
+      return message;
+    } catch (err) {
+      const message = err.response?.data?.error ?? err.message;
+      throw new Error("local model issues. details: " + message);
+    }
+  }
+};
+
 // src/utils/engine.ts
 function getEngine() {
-  const config11 = getConfig();
-  const provider4 = config11?.OCO_AI_PROVIDER;
+  const config12 = getConfig();
+  const provider4 = config12?.OCO_AI_PROVIDER;
   if (provider4?.startsWith("ollama")) {
     const ollamaAi = new OllamaAi();
     const model = provider4.split("/")[1];
@@ -41027,13 +41077,15 @@ function getEngine() {
     return new Gemini();
   } else if (provider4 == "azure") {
     return new Azure();
+  } else if (provider4 == "llmservice") {
+    return new LlmService();
   }
   return new OpenAi();
 }
 
 // src/modules/commitlint/config.ts
-var config7 = getConfig();
-var translation2 = i18n[config7?.OCO_LANGUAGE || "en"];
+var config8 = getConfig();
+var translation2 = i18n[config8?.OCO_LANGUAGE || "en"];
 var configureCommitlintIntegration = async (force = false) => {
   const spin = le();
   spin.start("Loading @commitlint configuration");
@@ -41086,15 +41138,15 @@ function removeConventionalCommitWord(message) {
 }
 
 // src/prompts.ts
-var config8 = getConfig();
-var translation3 = i18n[config8?.OCO_LANGUAGE || "en"];
+var config9 = getConfig();
+var translation3 = i18n[config9?.OCO_LANGUAGE || "en"];
 var IDENTITY = "You are to act as the author of a commit message in git.";
 var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({
   role: import_openai4.ChatCompletionRequestMessageRoleEnum.System,
   content: `${IDENTITY} Your mission is to create clean and comprehensive commit messages as per the ${fullGitMojiSpec ? "GitMoji specification" : "conventional commit convention"} and explain WHAT were the changes and mainly WHY the changes were done. I'll send you an output of 'git diff --staged' command, and you are to convert it into a commit message.
-  ${config8?.OCO_EMOJI ? `Use GitMoji convention to preface the commit. Here are some help to choose the right emoji (emoji, description): \u{1F41B}, Fix a bug; \u2728, Introduce new features; \u{1F4DD}, Add or update documentation; \u{1F680}, Deploy stuff; \u2705, Add, update, or pass tests; \u267B\uFE0F, Refactor code; \u2B06\uFE0F, Upgrade dependencies; \u{1F527}, Add or update configuration files; \u{1F310}, Internationalization and localization; \u{1F4A1}, Add or update comments in source code; ${fullGitMojiSpec ? "\u{1F3A8}, Improve structure / format of the code; \u26A1\uFE0F, Improve performance; \u{1F525}, Remove code or files; \u{1F691}\uFE0F, Critical hotfix; \u{1F484}, Add or update the UI and style files; \u{1F389}, Begin a project; \u{1F512}\uFE0F, Fix security issues; \u{1F510}, Add or update secrets; \u{1F516}, Release / Version tags; \u{1F6A8}, Fix compiler / linter warnings; \u{1F6A7}, Work in progress; \u{1F49A}, Fix CI Build; \u2B07\uFE0F, Downgrade dependencies; \u{1F4CC}, Pin dependencies to specific versions; \u{1F477}, Add or update CI build system; \u{1F4C8}, Add or update analytics or track code; \u2795, Add a dependency; \u2796, Remove a dependency; \u{1F528}, Add or update development scripts; \u270F\uFE0F, Fix typos; \u{1F4A9}, Write bad code that needs to be improved; \u23EA\uFE0F, Revert changes; \u{1F500}, Merge branches; \u{1F4E6}\uFE0F, Add or update compiled files or packages; \u{1F47D}\uFE0F, Update code due to external API changes; \u{1F69A}, Move or rename resources (e.g.: files, paths, routes); \u{1F4C4}, Add or update license; \u{1F4A5}, Introduce breaking changes; \u{1F371}, Add or update assets; \u267F\uFE0F, Improve accessibility; \u{1F37B}, Write code drunkenly; \u{1F4AC}, Add or update text and literals; \u{1F5C3}\uFE0F, Perform database related changes; \u{1F50A}, Add or update logs; \u{1F507}, Remove logs; \u{1F465}, Add or update contributor(s); \u{1F6B8}, Improve user experience / usability; \u{1F3D7}\uFE0F, Make architectural changes; \u{1F4F1}, Work on responsive design; \u{1F921}, Mock things; \u{1F95A}, Add or update an easter egg; \u{1F648}, Add or update a .gitignore file; \u{1F4F8}, Add or update snapshots; \u2697\uFE0F, Perform experiments; \u{1F50D}\uFE0F, Improve SEO; \u{1F3F7}\uFE0F, Add or update types; \u{1F331}, Add or update seed files; \u{1F6A9}, Add, update, or remove feature flags; \u{1F945}, Catch errors; \u{1F4AB}, Add or update animations and transitions; \u{1F5D1}\uFE0F, Deprecate code that needs to be cleaned up; \u{1F6C2}, Work on code related to authorization, roles and permissions; \u{1FA79}, Simple fix for a non-critical issue; \u{1F9D0}, Data exploration/inspection; \u26B0\uFE0F, Remove dead code; \u{1F9EA}, Add a failing test; \u{1F454}, Add or update business logic; \u{1FA7A}, Add or update healthcheck; \u{1F9F1}, Infrastructure related changes; \u{1F9D1}\u200D\u{1F4BB}, Improve developer experience; \u{1F4B8}, Add sponsorships or money related infrastructure; \u{1F9F5}, Add or update code related to multithreading or concurrency; \u{1F9BA}, Add or update code related to validation." : ""}` : "Do not preface the commit with anything. Conventional commit keywords:fix, feat, build, chore, ci, docs, style, refactor, perf, test."}  
-    ${config8?.OCO_DESCRIPTION ? `Add a short description of WHY the changes are done after the commit message. Don't start it with "This commit", just describe the changes.` : "Don't add any descriptions to the commit, only commit message."}
-    ${config8?.OCO_ONE_LINE_COMMIT ? "Craft a concise commit message that encapsulates all changes made, with an emphasis on the primary updates. If the modifications share a common theme or scope, mention it succinctly; otherwise, leave the scope out to maintain focus. The goal is to provide a clear and unified overview of the changes in a one single message, without diverging into a list of commit per file change." : ""}
+  ${config9?.OCO_EMOJI ? `Use GitMoji convention to preface the commit. Here are some help to choose the right emoji (emoji, description): \u{1F41B}, Fix a bug; \u2728, Introduce new features; \u{1F4DD}, Add or update documentation; \u{1F680}, Deploy stuff; \u2705, Add, update, or pass tests; \u267B\uFE0F, Refactor code; \u2B06\uFE0F, Upgrade dependencies; \u{1F527}, Add or update configuration files; \u{1F310}, Internationalization and localization; \u{1F4A1}, Add or update comments in source code; ${fullGitMojiSpec ? "\u{1F3A8}, Improve structure / format of the code; \u26A1\uFE0F, Improve performance; \u{1F525}, Remove code or files; \u{1F691}\uFE0F, Critical hotfix; \u{1F484}, Add or update the UI and style files; \u{1F389}, Begin a project; \u{1F512}\uFE0F, Fix security issues; \u{1F510}, Add or update secrets; \u{1F516}, Release / Version tags; \u{1F6A8}, Fix compiler / linter warnings; \u{1F6A7}, Work in progress; \u{1F49A}, Fix CI Build; \u2B07\uFE0F, Downgrade dependencies; \u{1F4CC}, Pin dependencies to specific versions; \u{1F477}, Add or update CI build system; \u{1F4C8}, Add or update analytics or track code; \u2795, Add a dependency; \u2796, Remove a dependency; \u{1F528}, Add or update development scripts; \u270F\uFE0F, Fix typos; \u{1F4A9}, Write bad code that needs to be improved; \u23EA\uFE0F, Revert changes; \u{1F500}, Merge branches; \u{1F4E6}\uFE0F, Add or update compiled files or packages; \u{1F47D}\uFE0F, Update code due to external API changes; \u{1F69A}, Move or rename resources (e.g.: files, paths, routes); \u{1F4C4}, Add or update license; \u{1F4A5}, Introduce breaking changes; \u{1F371}, Add or update assets; \u267F\uFE0F, Improve accessibility; \u{1F37B}, Write code drunkenly; \u{1F4AC}, Add or update text and literals; \u{1F5C3}\uFE0F, Perform database related changes; \u{1F50A}, Add or update logs; \u{1F507}, Remove logs; \u{1F465}, Add or update contributor(s); \u{1F6B8}, Improve user experience / usability; \u{1F3D7}\uFE0F, Make architectural changes; \u{1F4F1}, Work on responsive design; \u{1F921}, Mock things; \u{1F95A}, Add or update an easter egg; \u{1F648}, Add or update a .gitignore file; \u{1F4F8}, Add or update snapshots; \u2697\uFE0F, Perform experiments; \u{1F50D}\uFE0F, Improve SEO; \u{1F3F7}\uFE0F, Add or update types; \u{1F331}, Add or update seed files; \u{1F6A9}, Add, update, or remove feature flags; \u{1F945}, Catch errors; \u{1F4AB}, Add or update animations and transitions; \u{1F5D1}\uFE0F, Deprecate code that needs to be cleaned up; \u{1F6C2}, Work on code related to authorization, roles and permissions; \u{1FA79}, Simple fix for a non-critical issue; \u{1F9D0}, Data exploration/inspection; \u26B0\uFE0F, Remove dead code; \u{1F9EA}, Add a failing test; \u{1F454}, Add or update business logic; \u{1FA7A}, Add or update healthcheck; \u{1F9F1}, Infrastructure related changes; \u{1F9D1}\u200D\u{1F4BB}, Improve developer experience; \u{1F4B8}, Add sponsorships or money related infrastructure; \u{1F9F5}, Add or update code related to multithreading or concurrency; \u{1F9BA}, Add or update code related to validation." : ""}` : "Do not preface the commit with anything. Conventional commit keywords:fix, feat, build, chore, ci, docs, style, refactor, perf, test."}  
+    ${config9?.OCO_DESCRIPTION ? `Add a short description of WHY the changes are done after the commit message. Don't start it with "This commit", just describe the changes.` : "Don't add any descriptions to the commit, only commit message."}
+    ${config9?.OCO_ONE_LINE_COMMIT ? "Craft a concise commit message that encapsulates all changes made, with an emphasis on the primary updates. If the modifications share a common theme or scope, mention it succinctly; otherwise, leave the scope out to maintain focus. The goal is to provide a clear and unified overview of the changes in a one single message, without diverging into a list of commit per file change." : ""}
     Use the present tense. Lines must not be longer than 74 characters. Use ${language} for the commit message.`
 });
 var INIT_DIFF_PROMPT = {
@@ -41126,12 +41178,12 @@ var INIT_DIFF_PROMPT = {
 };
 var INIT_CONSISTENCY_PROMPT = (translation4) => ({
   role: import_openai4.ChatCompletionRequestMessageRoleEnum.Assistant,
-  content: `${config8?.OCO_EMOJI ? `\u{1F41B} ${removeConventionalCommitWord(translation4.commitFix)}` : translation4.commitFix}
-${config8?.OCO_EMOJI ? `\u2728 ${removeConventionalCommitWord(translation4.commitFeat)}` : translation4.commitFeat}
-${config8?.OCO_DESCRIPTION ? translation4.commitDescription : ""}`
+  content: `${config9?.OCO_EMOJI ? `\u{1F41B} ${removeConventionalCommitWord(translation4.commitFix)}` : translation4.commitFix}
+${config9?.OCO_EMOJI ? `\u2728 ${removeConventionalCommitWord(translation4.commitFeat)}` : translation4.commitFeat}
+${config9?.OCO_DESCRIPTION ? translation4.commitDescription : ""}`
 });
 var getMainCommitPrompt = async (fullGitMojiSpec) => {
-  switch (config8?.OCO_PROMPT_MODULE) {
+  switch (config9?.OCO_PROMPT_MODULE) {
     case "@commitlint":
       if (!await commitlintLLMConfigExists()) {
         ie(
@@ -41176,9 +41228,9 @@ function mergeDiffs(arr, maxStringLength) {
 }
 
 // src/generateCommitMessageFromGitDiff.ts
-var config9 = getConfig();
-var MAX_TOKENS_INPUT4 = config9?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */;
-var MAX_TOKENS_OUTPUT4 = config9?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */;
+var config10 = getConfig();
+var MAX_TOKENS_INPUT4 = config10?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */;
+var MAX_TOKENS_OUTPUT4 = config10?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */;
 var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec) => {
   const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
   const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT];
@@ -41410,14 +41462,14 @@ var trytm = async (promise) => {
 };
 
 // src/commands/commit.ts
-var config10 = getConfig();
+var config11 = getConfig();
 var getGitRemotes = async () => {
   const { stdout } = await execa("git", ["remote"]);
   return stdout.split("\n").filter((remote) => Boolean(remote.trim()));
 };
 var checkMessageTemplate = (extraArgs2) => {
   for (const key in extraArgs2) {
-    if (extraArgs2[key].includes(config10?.OCO_MESSAGE_TEMPLATE_PLACEHOLDER))
+    if (extraArgs2[key].includes(config11?.OCO_MESSAGE_TEMPLATE_PLACEHOLDER))
       return extraArgs2[key];
   }
   return false;
@@ -41432,11 +41484,11 @@ var generateCommitMessageFromGitDiff = async (diff, extraArgs2, fullGitMojiSpec,
       fullGitMojiSpec
     );
     const messageTemplate = checkMessageTemplate(extraArgs2);
-    if (config10?.OCO_MESSAGE_TEMPLATE_PLACEHOLDER && typeof messageTemplate === "string") {
+    if (config11?.OCO_MESSAGE_TEMPLATE_PLACEHOLDER && typeof messageTemplate === "string") {
       const messageTemplateIndex = extraArgs2.indexOf(messageTemplate);
       extraArgs2.splice(messageTemplateIndex, 1);
       commitMessage = messageTemplate.replace(
-        config10?.OCO_MESSAGE_TEMPLATE_PLACEHOLDER,
+        config11?.OCO_MESSAGE_TEMPLATE_PLACEHOLDER,
         commitMessage
       );
     }
@@ -41460,7 +41512,7 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
       ce(`${source_default.green("\u2714")} Successfully committed`);
       ce(stdout);
       const remotes = await getGitRemotes();
-      if (config10?.OCO_GITPUSH === false)
+      if (config11?.OCO_GITPUSH === false)
         return;
       if (!remotes.length) {
         const { stdout: stdout2 } = await execa("git", ["push"]);
@@ -41468,7 +41520,7 @@ ${source_default.grey("\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2
           ce(stdout2);
         process.exit(0);
       }
-      if (remotes.length === 1 && config10?.OCO_GITPUSH !== true) {
+      if (remotes.length === 1 && config11?.OCO_GITPUSH !== true) {
         const isPushConfirmedByUser = await Q3({
           message: "Do you want to run `git push`?"
         });
@@ -41730,8 +41782,8 @@ var prepareCommitMessageHook = async (isStageAllFlag = false) => {
     if (!staged)
       return;
     ae("opencommit");
-    const config11 = getConfig();
-    if (!config11?.OCO_OPENAI_API_KEY && !config11?.OCO_ANTHROPIC_API_KEY && !config11?.OCO_AZURE_API_KEY) {
+    const config12 = getConfig();
+    if (!config12?.OCO_OPENAI_API_KEY && !config12?.OCO_ANTHROPIC_API_KEY && !config12?.OCO_AZURE_API_KEY) {
       throw new Error(
         "No OPEN_AI_API or OCO_ANTHROPIC_API_KEY or OCO_AZURE_API_KEY exists. Set your key in ~/.opencommit"
       );
diff --git a/out/github-action.cjs b/out/github-action.cjs
index 87b2a099..0cd6ad2d 100644
--- a/out/github-action.cjs
+++ b/out/github-action.cjs
@@ -25504,8 +25504,8 @@ var require_normalizeHeaderName = __commonJS({
 var require_enhanceError = __commonJS({
   "node_modules/openai/node_modules/axios/lib/core/enhanceError.js"(exports, module2) {
     "use strict";
-    module2.exports = function enhanceError(error, config10, code, request3, response) {
-      error.config = config10;
+    module2.exports = function enhanceError(error, config11, code, request3, response) {
+      error.config = config11;
       if (code) {
         error.code = code;
       }
@@ -25549,9 +25549,9 @@ var require_createError = __commonJS({
   "node_modules/openai/node_modules/axios/lib/core/createError.js"(exports, module2) {
     "use strict";
     var enhanceError = require_enhanceError();
-    module2.exports = function createError(message, config10, code, request3, response) {
+    module2.exports = function createError(message, config11, code, request3, response) {
       var error = new Error(message);
-      return enhanceError(error, config10, code, request3, response);
+      return enhanceError(error, config11, code, request3, response);
     };
   }
 });
@@ -25780,32 +25780,32 @@ var require_xhr = __commonJS({
     var createError = require_createError();
     var transitionalDefaults = require_transitional();
     var Cancel2 = require_Cancel();
-    module2.exports = function xhrAdapter(config10) {
+    module2.exports = function xhrAdapter(config11) {
       return new Promise(function dispatchXhrRequest(resolve, reject) {
-        var requestData = config10.data;
-        var requestHeaders = config10.headers;
-        var responseType = config10.responseType;
+        var requestData = config11.data;
+        var requestHeaders = config11.headers;
+        var responseType = config11.responseType;
         var onCanceled;
         function done() {
-          if (config10.cancelToken) {
-            config10.cancelToken.unsubscribe(onCanceled);
+          if (config11.cancelToken) {
+            config11.cancelToken.unsubscribe(onCanceled);
           }
-          if (config10.signal) {
-            config10.signal.removeEventListener("abort", onCanceled);
+          if (config11.signal) {
+            config11.signal.removeEventListener("abort", onCanceled);
           }
         }
         if (utils.isFormData(requestData)) {
           delete requestHeaders["Content-Type"];
         }
         var request3 = new XMLHttpRequest();
-        if (config10.auth) {
-          var username = config10.auth.username || "";
-          var password = config10.auth.password ? unescape(encodeURIComponent(config10.auth.password)) : "";
+        if (config11.auth) {
+          var username = config11.auth.username || "";
+          var password = config11.auth.password ? unescape(encodeURIComponent(config11.auth.password)) : "";
           requestHeaders.Authorization = "Basic " + btoa(username + ":" + password);
         }
-        var fullPath = buildFullPath2(config10.baseURL, config10.url);
-        request3.open(config10.method.toUpperCase(), buildURL2(fullPath, config10.params, config10.paramsSerializer), true);
-        request3.timeout = config10.timeout;
+        var fullPath = buildFullPath2(config11.baseURL, config11.url);
+        request3.open(config11.method.toUpperCase(), buildURL2(fullPath, config11.params, config11.paramsSerializer), true);
+        request3.timeout = config11.timeout;
         function onloadend() {
           if (!request3) {
             return;
@@ -25817,7 +25817,7 @@ var require_xhr = __commonJS({
             status: request3.status,
             statusText: request3.statusText,
             headers: responseHeaders,
-            config: config10,
+            config: config11,
             request: request3
           };
           settle2(function _resolve(value) {
@@ -25846,31 +25846,31 @@ var require_xhr = __commonJS({
           if (!request3) {
             return;
           }
-          reject(createError("Request aborted", config10, "ECONNABORTED", request3));
+          reject(createError("Request aborted", config11, "ECONNABORTED", request3));
           request3 = null;
         };
         request3.onerror = function handleError() {
-          reject(createError("Network Error", config10, null, request3));
+          reject(createError("Network Error", config11, null, request3));
           request3 = null;
         };
         request3.ontimeout = function handleTimeout() {
-          var timeoutErrorMessage = config10.timeout ? "timeout of " + config10.timeout + "ms exceeded" : "timeout exceeded";
-          var transitional2 = config10.transitional || transitionalDefaults;
-          if (config10.timeoutErrorMessage) {
-            timeoutErrorMessage = config10.timeoutErrorMessage;
+          var timeoutErrorMessage = config11.timeout ? "timeout of " + config11.timeout + "ms exceeded" : "timeout exceeded";
+          var transitional2 = config11.transitional || transitionalDefaults;
+          if (config11.timeoutErrorMessage) {
+            timeoutErrorMessage = config11.timeoutErrorMessage;
           }
           reject(createError(
             timeoutErrorMessage,
-            config10,
+            config11,
             transitional2.clarifyTimeoutError ? "ETIMEDOUT" : "ECONNABORTED",
             request3
           ));
           request3 = null;
         };
         if (utils.isStandardBrowserEnv()) {
-          var xsrfValue = (config10.withCredentials || isURLSameOrigin(fullPath)) && config10.xsrfCookieName ? cookies.read(config10.xsrfCookieName) : void 0;
+          var xsrfValue = (config11.withCredentials || isURLSameOrigin(fullPath)) && config11.xsrfCookieName ? cookies.read(config11.xsrfCookieName) : void 0;
           if (xsrfValue) {
-            requestHeaders[config10.xsrfHeaderName] = xsrfValue;
+            requestHeaders[config11.xsrfHeaderName] = xsrfValue;
           }
         }
         if ("setRequestHeader" in request3) {
@@ -25882,19 +25882,19 @@ var require_xhr = __commonJS({
             }
           });
         }
-        if (!utils.isUndefined(config10.withCredentials)) {
-          request3.withCredentials = !!config10.withCredentials;
+        if (!utils.isUndefined(config11.withCredentials)) {
+          request3.withCredentials = !!config11.withCredentials;
         }
         if (responseType && responseType !== "json") {
-          request3.responseType = config10.responseType;
+          request3.responseType = config11.responseType;
         }
-        if (typeof config10.onDownloadProgress === "function") {
-          request3.addEventListener("progress", config10.onDownloadProgress);
+        if (typeof config11.onDownloadProgress === "function") {
+          request3.addEventListener("progress", config11.onDownloadProgress);
         }
-        if (typeof config10.onUploadProgress === "function" && request3.upload) {
-          request3.upload.addEventListener("progress", config10.onUploadProgress);
+        if (typeof config11.onUploadProgress === "function" && request3.upload) {
+          request3.upload.addEventListener("progress", config11.onUploadProgress);
         }
-        if (config10.cancelToken || config10.signal) {
+        if (config11.cancelToken || config11.signal) {
           onCanceled = function(cancel) {
             if (!request3) {
               return;
@@ -25903,9 +25903,9 @@ var require_xhr = __commonJS({
             request3.abort();
             request3 = null;
           };
-          config10.cancelToken && config10.cancelToken.subscribe(onCanceled);
-          if (config10.signal) {
-            config10.signal.aborted ? onCanceled() : config10.signal.addEventListener("abort", onCanceled);
+          config11.cancelToken && config11.cancelToken.subscribe(onCanceled);
+          if (config11.signal) {
+            config11.signal.aborted ? onCanceled() : config11.signal.addEventListener("abort", onCanceled);
           }
         }
         if (!requestData) {
@@ -27201,15 +27201,15 @@ var require_http = __commonJS({
         setProxy2(redirection, proxy, redirection.href);
       };
     }
-    module2.exports = function httpAdapter2(config10) {
+    module2.exports = function httpAdapter2(config11) {
       return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
         var onCanceled;
         function done() {
-          if (config10.cancelToken) {
-            config10.cancelToken.unsubscribe(onCanceled);
+          if (config11.cancelToken) {
+            config11.cancelToken.unsubscribe(onCanceled);
           }
-          if (config10.signal) {
-            config10.signal.removeEventListener("abort", onCanceled);
+          if (config11.signal) {
+            config11.signal.removeEventListener("abort", onCanceled);
           }
         }
         var resolve = function resolve2(value) {
@@ -27222,8 +27222,8 @@ var require_http = __commonJS({
           rejected = true;
           rejectPromise(value);
         };
-        var data = config10.data;
-        var headers = config10.headers;
+        var data = config11.data;
+        var headers = config11.headers;
         var headerNames = {};
         Object.keys(headers).forEach(function storeLowerName(name) {
           headerNames[name.toLowerCase()] = name;
@@ -27244,23 +27244,23 @@ var require_http = __commonJS({
           } else {
             return reject(createError(
               "Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream",
-              config10
+              config11
             ));
           }
-          if (config10.maxBodyLength > -1 && data.length > config10.maxBodyLength) {
-            return reject(createError("Request body larger than maxBodyLength limit", config10));
+          if (config11.maxBodyLength > -1 && data.length > config11.maxBodyLength) {
+            return reject(createError("Request body larger than maxBodyLength limit", config11));
           }
           if (!headerNames["content-length"]) {
             headers["Content-Length"] = data.length;
           }
         }
         var auth = void 0;
-        if (config10.auth) {
-          var username = config10.auth.username || "";
-          var password = config10.auth.password || "";
+        if (config11.auth) {
+          var username = config11.auth.username || "";
+          var password = config11.auth.password || "";
           auth = username + ":" + password;
         }
-        var fullPath = buildFullPath2(config10.baseURL, config10.url);
+        var fullPath = buildFullPath2(config11.baseURL, config11.url);
         var parsed = url2.parse(fullPath);
         var protocol = parsed.protocol || "http:";
         if (!auth && parsed.auth) {
@@ -27273,31 +27273,31 @@ var require_http = __commonJS({
           delete headers[headerNames.authorization];
         }
         var isHttpsRequest = isHttps2.test(protocol);
-        var agent = isHttpsRequest ? config10.httpsAgent : config10.httpAgent;
+        var agent = isHttpsRequest ? config11.httpsAgent : config11.httpAgent;
         try {
-          buildURL2(parsed.path, config10.params, config10.paramsSerializer).replace(/^\?/, "");
+          buildURL2(parsed.path, config11.params, config11.paramsSerializer).replace(/^\?/, "");
         } catch (err) {
           var customErr = new Error(err.message);
-          customErr.config = config10;
-          customErr.url = config10.url;
+          customErr.config = config11;
+          customErr.url = config11.url;
           customErr.exists = true;
           reject(customErr);
         }
         var options = {
-          path: buildURL2(parsed.path, config10.params, config10.paramsSerializer).replace(/^\?/, ""),
-          method: config10.method.toUpperCase(),
+          path: buildURL2(parsed.path, config11.params, config11.paramsSerializer).replace(/^\?/, ""),
+          method: config11.method.toUpperCase(),
           headers,
           agent,
-          agents: { http: config10.httpAgent, https: config10.httpsAgent },
+          agents: { http: config11.httpAgent, https: config11.httpsAgent },
           auth
         };
-        if (config10.socketPath) {
-          options.socketPath = config10.socketPath;
+        if (config11.socketPath) {
+          options.socketPath = config11.socketPath;
         } else {
           options.hostname = parsed.hostname;
           options.port = parsed.port;
         }
-        var proxy = config10.proxy;
+        var proxy = config11.proxy;
         if (!proxy && proxy !== false) {
           var proxyEnv = protocol.slice(0, -1) + "_proxy";
           var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()];
@@ -27344,28 +27344,28 @@ var require_http = __commonJS({
         }
         var transport;
         var isHttpsProxy = isHttpsRequest && (proxy ? isHttps2.test(proxy.protocol) : true);
-        if (config10.transport) {
-          transport = config10.transport;
-        } else if (config10.maxRedirects === 0) {
+        if (config11.transport) {
+          transport = config11.transport;
+        } else if (config11.maxRedirects === 0) {
           transport = isHttpsProxy ? https3 : http3;
         } else {
-          if (config10.maxRedirects) {
-            options.maxRedirects = config10.maxRedirects;
+          if (config11.maxRedirects) {
+            options.maxRedirects = config11.maxRedirects;
           }
           transport = isHttpsProxy ? httpsFollow2 : httpFollow2;
         }
-        if (config10.maxBodyLength > -1) {
-          options.maxBodyLength = config10.maxBodyLength;
+        if (config11.maxBodyLength > -1) {
+          options.maxBodyLength = config11.maxBodyLength;
         }
-        if (config10.insecureHTTPParser) {
-          options.insecureHTTPParser = config10.insecureHTTPParser;
+        if (config11.insecureHTTPParser) {
+          options.insecureHTTPParser = config11.insecureHTTPParser;
         }
         var req = transport.request(options, function handleResponse(res) {
           if (req.aborted)
             return;
           var stream4 = res;
           var lastRequest = res.req || req;
-          if (res.statusCode !== 204 && lastRequest.method !== "HEAD" && config10.decompress !== false) {
+          if (res.statusCode !== 204 && lastRequest.method !== "HEAD" && config11.decompress !== false) {
             switch (res.headers["content-encoding"]) {
               case "gzip":
               case "compress":
@@ -27379,10 +27379,10 @@ var require_http = __commonJS({
             status: res.statusCode,
             statusText: res.statusMessage,
             headers: res.headers,
-            config: config10,
+            config: config11,
             request: lastRequest
           };
-          if (config10.responseType === "stream") {
+          if (config11.responseType === "stream") {
             response.data = stream4;
             settle2(resolve, reject, response);
           } else {
@@ -27391,12 +27391,12 @@ var require_http = __commonJS({
             stream4.on("data", function handleStreamData(chunk) {
               responseBuffer.push(chunk);
               totalResponseBytes += chunk.length;
-              if (config10.maxContentLength > -1 && totalResponseBytes > config10.maxContentLength) {
+              if (config11.maxContentLength > -1 && totalResponseBytes > config11.maxContentLength) {
                 rejected = true;
                 stream4.destroy();
                 reject(createError(
-                  "maxContentLength size of " + config10.maxContentLength + " exceeded",
-                  config10,
+                  "maxContentLength size of " + config11.maxContentLength + " exceeded",
+                  config11,
                   null,
                   lastRequest
                 ));
@@ -27407,25 +27407,25 @@ var require_http = __commonJS({
                 return;
               }
               stream4.destroy();
-              reject(createError("error request aborted", config10, "ERR_REQUEST_ABORTED", lastRequest));
+              reject(createError("error request aborted", config11, "ERR_REQUEST_ABORTED", lastRequest));
             });
             stream4.on("error", function handleStreamError(err) {
               if (req.aborted)
                 return;
-              reject(enhanceError(err, config10, null, lastRequest));
+              reject(enhanceError(err, config11, null, lastRequest));
             });
             stream4.on("end", function handleStreamEnd() {
               try {
                 var responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
-                if (config10.responseType !== "arraybuffer") {
-                  responseData = responseData.toString(config10.responseEncoding);
-                  if (!config10.responseEncoding || config10.responseEncoding === "utf8") {
+                if (config11.responseType !== "arraybuffer") {
+                  responseData = responseData.toString(config11.responseEncoding);
+                  if (!config11.responseEncoding || config11.responseEncoding === "utf8") {
                     responseData = utils.stripBOM(responseData);
                   }
                 }
                 response.data = responseData;
               } catch (err) {
-                reject(enhanceError(err, config10, err.code, response.request, response));
+                reject(enhanceError(err, config11, err.code, response.request, response));
               }
               settle2(resolve, reject, response);
             });
@@ -27434,17 +27434,17 @@ var require_http = __commonJS({
         req.on("error", function handleRequestError(err) {
           if (req.aborted && err.code !== "ERR_FR_TOO_MANY_REDIRECTS")
             return;
-          reject(enhanceError(err, config10, null, req));
+          reject(enhanceError(err, config11, null, req));
         });
         req.on("socket", function handleRequestSocket(socket) {
           socket.setKeepAlive(true, 1e3 * 60);
         });
-        if (config10.timeout) {
-          var timeout = parseInt(config10.timeout, 10);
+        if (config11.timeout) {
+          var timeout = parseInt(config11.timeout, 10);
           if (isNaN(timeout)) {
             reject(createError(
               "error trying to parse `config.timeout` to int",
-              config10,
+              config11,
               "ERR_PARSE_TIMEOUT",
               req
             ));
@@ -27453,35 +27453,35 @@ var require_http = __commonJS({
           req.setTimeout(timeout, function handleRequestTimeout() {
             req.abort();
             var timeoutErrorMessage = "";
-            if (config10.timeoutErrorMessage) {
-              timeoutErrorMessage = config10.timeoutErrorMessage;
+            if (config11.timeoutErrorMessage) {
+              timeoutErrorMessage = config11.timeoutErrorMessage;
             } else {
-              timeoutErrorMessage = "timeout of " + config10.timeout + "ms exceeded";
+              timeoutErrorMessage = "timeout of " + config11.timeout + "ms exceeded";
             }
-            var transitional2 = config10.transitional || transitionalDefaults;
+            var transitional2 = config11.transitional || transitionalDefaults;
             reject(createError(
               timeoutErrorMessage,
-              config10,
+              config11,
               transitional2.clarifyTimeoutError ? "ETIMEDOUT" : "ECONNABORTED",
               req
             ));
           });
         }
-        if (config10.cancelToken || config10.signal) {
+        if (config11.cancelToken || config11.signal) {
           onCanceled = function(cancel) {
             if (req.aborted)
               return;
             req.abort();
             reject(!cancel || cancel && cancel.type ? new Cancel2("canceled") : cancel);
           };
-          config10.cancelToken && config10.cancelToken.subscribe(onCanceled);
-          if (config10.signal) {
-            config10.signal.aborted ? onCanceled() : config10.signal.addEventListener("abort", onCanceled);
+          config11.cancelToken && config11.cancelToken.subscribe(onCanceled);
+          if (config11.signal) {
+            config11.signal.aborted ? onCanceled() : config11.signal.addEventListener("abort", onCanceled);
           }
         }
         if (utils.isStream(data)) {
           data.on("error", function handleStreamError(err) {
-            reject(enhanceError(err, config10, null, req));
+            reject(enhanceError(err, config11, null, req));
           }).pipe(req);
         } else {
           req.end(data);
@@ -27629,53 +27629,53 @@ var require_dispatchRequest = __commonJS({
     var isCancel3 = require_isCancel();
     var defaults2 = require_defaults();
     var Cancel2 = require_Cancel();
-    function throwIfCancellationRequested2(config10) {
-      if (config10.cancelToken) {
-        config10.cancelToken.throwIfRequested();
+    function throwIfCancellationRequested2(config11) {
+      if (config11.cancelToken) {
+        config11.cancelToken.throwIfRequested();
       }
-      if (config10.signal && config10.signal.aborted) {
+      if (config11.signal && config11.signal.aborted) {
         throw new Cancel2("canceled");
       }
     }
-    module2.exports = function dispatchRequest2(config10) {
-      throwIfCancellationRequested2(config10);
-      config10.headers = config10.headers || {};
-      config10.data = transformData2.call(
-        config10,
-        config10.data,
-        config10.headers,
-        config10.transformRequest
+    module2.exports = function dispatchRequest2(config11) {
+      throwIfCancellationRequested2(config11);
+      config11.headers = config11.headers || {};
+      config11.data = transformData2.call(
+        config11,
+        config11.data,
+        config11.headers,
+        config11.transformRequest
       );
-      config10.headers = utils.merge(
-        config10.headers.common || {},
-        config10.headers[config10.method] || {},
-        config10.headers
+      config11.headers = utils.merge(
+        config11.headers.common || {},
+        config11.headers[config11.method] || {},
+        config11.headers
       );
       utils.forEach(
         ["delete", "get", "head", "post", "put", "patch", "common"],
         function cleanHeaderConfig(method) {
-          delete config10.headers[method];
+          delete config11.headers[method];
         }
       );
-      var adapter = config10.adapter || defaults2.adapter;
-      return adapter(config10).then(function onAdapterResolution(response) {
-        throwIfCancellationRequested2(config10);
+      var adapter = config11.adapter || defaults2.adapter;
+      return adapter(config11).then(function onAdapterResolution(response) {
+        throwIfCancellationRequested2(config11);
         response.data = transformData2.call(
-          config10,
+          config11,
           response.data,
           response.headers,
-          config10.transformResponse
+          config11.transformResponse
         );
         return response;
       }, function onAdapterRejection(reason) {
         if (!isCancel3(reason)) {
-          throwIfCancellationRequested2(config10);
+          throwIfCancellationRequested2(config11);
           if (reason && reason.response) {
             reason.response.data = transformData2.call(
-              config10,
+              config11,
               reason.response.data,
               reason.response.headers,
-              config10.transformResponse
+              config11.transformResponse
             );
           }
         }
@@ -27692,7 +27692,7 @@ var require_mergeConfig = __commonJS({
     var utils = require_utils6();
     module2.exports = function mergeConfig3(config1, config22) {
       config22 = config22 || {};
-      var config10 = {};
+      var config11 = {};
       function getMergedValue(target, source) {
         if (utils.isPlainObject(target) && utils.isPlainObject(source)) {
           return utils.merge(target, source);
@@ -27760,9 +27760,9 @@ var require_mergeConfig = __commonJS({
       utils.forEach(Object.keys(config1).concat(Object.keys(config22)), function computeConfigValue(prop) {
         var merge2 = mergeMap[prop] || mergeDeepProperties;
         var configValue = merge2(prop);
-        utils.isUndefined(configValue) && merge2 !== mergeDirectKeys || (config10[prop] = configValue);
+        utils.isUndefined(configValue) && merge2 !== mergeDirectKeys || (config11[prop] = configValue);
       });
-      return config10;
+      return config11;
     };
   }
 });
@@ -27846,22 +27846,22 @@ var require_Axios = __commonJS({
         response: new InterceptorManager2()
       };
     }
-    Axios3.prototype.request = function request3(configOrUrl, config10) {
+    Axios3.prototype.request = function request3(configOrUrl, config11) {
       if (typeof configOrUrl === "string") {
-        config10 = config10 || {};
-        config10.url = configOrUrl;
+        config11 = config11 || {};
+        config11.url = configOrUrl;
       } else {
-        config10 = configOrUrl || {};
+        config11 = configOrUrl || {};
       }
-      config10 = mergeConfig3(this.defaults, config10);
-      if (config10.method) {
-        config10.method = config10.method.toLowerCase();
+      config11 = mergeConfig3(this.defaults, config11);
+      if (config11.method) {
+        config11.method = config11.method.toLowerCase();
       } else if (this.defaults.method) {
-        config10.method = this.defaults.method.toLowerCase();
+        config11.method = this.defaults.method.toLowerCase();
       } else {
-        config10.method = "get";
+        config11.method = "get";
       }
-      var transitional2 = config10.transitional;
+      var transitional2 = config11.transitional;
       if (transitional2 !== void 0) {
         validator.assertOptions(transitional2, {
           silentJSONParsing: validators3.transitional(validators3.boolean),
@@ -27872,7 +27872,7 @@ var require_Axios = __commonJS({
       var requestInterceptorChain = [];
       var synchronousRequestInterceptors = true;
       this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
-        if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config10) === false) {
+        if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config11) === false) {
           return;
         }
         synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
@@ -27887,13 +27887,13 @@ var require_Axios = __commonJS({
         var chain = [dispatchRequest2, void 0];
         Array.prototype.unshift.apply(chain, requestInterceptorChain);
         chain = chain.concat(responseInterceptorChain);
-        promise = Promise.resolve(config10);
+        promise = Promise.resolve(config11);
         while (chain.length) {
           promise = promise.then(chain.shift(), chain.shift());
         }
         return promise;
       }
-      var newConfig = config10;
+      var newConfig = config11;
       while (requestInterceptorChain.length) {
         var onFulfilled = requestInterceptorChain.shift();
         var onRejected = requestInterceptorChain.shift();
@@ -27914,22 +27914,22 @@ var require_Axios = __commonJS({
       }
       return promise;
     };
-    Axios3.prototype.getUri = function getUri(config10) {
-      config10 = mergeConfig3(this.defaults, config10);
-      return buildURL2(config10.url, config10.params, config10.paramsSerializer).replace(/^\?/, "");
+    Axios3.prototype.getUri = function getUri(config11) {
+      config11 = mergeConfig3(this.defaults, config11);
+      return buildURL2(config11.url, config11.params, config11.paramsSerializer).replace(/^\?/, "");
     };
     utils.forEach(["delete", "get", "head", "options"], function forEachMethodNoData2(method) {
-      Axios3.prototype[method] = function(url2, config10) {
-        return this.request(mergeConfig3(config10 || {}, {
+      Axios3.prototype[method] = function(url2, config11) {
+        return this.request(mergeConfig3(config11 || {}, {
           method,
           url: url2,
-          data: (config10 || {}).data
+          data: (config11 || {}).data
         }));
       };
     });
     utils.forEach(["post", "put", "patch"], function forEachMethodWithData2(method) {
-      Axios3.prototype[method] = function(url2, data, config10) {
-        return this.request(mergeConfig3(config10 || {}, {
+      Axios3.prototype[method] = function(url2, data, config11) {
+        return this.request(mergeConfig3(config11 || {}, {
           method,
           url: url2,
           data
@@ -39064,7 +39064,7 @@ var require_main2 = __commonJS({
         return { parsed: parsedAll };
       }
     }
-    function config10(options) {
+    function config11(options) {
       if (_dotenvKey(options).length === 0) {
         return DotenvModule.configDotenv(options);
       }
@@ -39131,7 +39131,7 @@ var require_main2 = __commonJS({
       configDotenv,
       _configVault,
       _parseVault,
-      config: config10,
+      config: config11,
       decrypt,
       parse,
       populate
@@ -49377,8 +49377,8 @@ var vi_VN_default = {
 // src/i18n/zh_CN.json
 var zh_CN_default = {
   localLanguage: "\u7B80\u4F53\u4E2D\u6587",
-  commitFix: "\u4FEE\u590D(server.ts)\uFF1A\u5C06\u7AEF\u53E3\u53D8\u91CF\u4ECE\u5C0F\u5199port\u6539\u4E3A\u5927\u5199PORT",
-  commitFeat: "\u529F\u80FD(server.ts)\uFF1A\u6DFB\u52A0\u5BF9process.env.PORT\u73AF\u5883\u53D8\u91CF\u7684\u652F\u6301",
+  commitFix: "fix(server.ts)\uFF1A\u5C06\u7AEF\u53E3\u53D8\u91CF\u4ECE\u5C0F\u5199port\u6539\u4E3A\u5927\u5199PORT",
+  commitFeat: "feat(server.ts)\uFF1A\u6DFB\u52A0\u5BF9process.env.PORT\u73AF\u5883\u53D8\u91CF\u7684\u652F\u6301",
   commitDescription: "\u73B0\u5728\u7AEF\u53E3\u53D8\u91CF\u88AB\u547D\u540D\u4E3APORT\uFF0C\u8FD9\u63D0\u9AD8\u4E86\u547D\u540D\u7EA6\u5B9A\u7684\u4E00\u81F4\u6027\uFF0C\u56E0\u4E3APORT\u662F\u4E00\u4E2A\u5E38\u91CF\u3002\u73AF\u5883\u53D8\u91CF\u7684\u652F\u6301\u4F7F\u5E94\u7528\u7A0B\u5E8F\u66F4\u52A0\u7075\u6D3B\uFF0C\u56E0\u4E3A\u5B83\u73B0\u5728\u53EF\u4EE5\u901A\u8FC7process.env.PORT\u73AF\u5883\u53D8\u91CF\u5728\u4EFB\u4F55\u53EF\u7528\u7AEF\u53E3\u4E0A\u8FD0\u884C\u3002"
 };
 
@@ -49450,8 +49450,8 @@ var TEST_MOCK_TYPES = [
 ];
 var TestAi = class {
   async generateCommitMessage(_messages) {
-    const config10 = getConfig();
-    switch (config10?.OCO_TEST_MOCK_TYPE) {
+    const config11 = getConfig();
+    switch (config11?.OCO_TEST_MOCK_TYPE) {
       case "commit-message":
         return "fix(testAi.ts): test commit message";
       case "prompt-module-commitlint-config":
@@ -49501,7 +49501,7 @@ var MODEL_LIST = {
     "claude-3-5-sonnet-20240620",
     "claude-3-opus-20240229",
     "claude-3-sonnet-20240229",
-    "claude-3-opus-20240229"
+    "claude-3-haiku-20240307"
   ],
   gemini: [
     "gemini-1.5-flash",
@@ -49532,43 +49532,43 @@ var validateConfig = (key, condition, validationMessage) => {
   }
 };
 var configValidators = {
-  ["OCO_OPENAI_API_KEY" /* OCO_OPENAI_API_KEY */](value, config10 = {}) {
-    if (config10.OCO_AI_PROVIDER == "gemini")
+  ["OCO_OPENAI_API_KEY" /* OCO_OPENAI_API_KEY */](value, config11 = {}) {
+    if (config11.OCO_AI_PROVIDER == "gemini")
       return value;
     validateConfig(
       "OpenAI API_KEY",
-      value || config10.OCO_ANTHROPIC_API_KEY || config10.OCO_AI_PROVIDER.startsWith("ollama") || config10.OCO_AZURE_API_KEY || config10.OCO_AI_PROVIDER == "test",
+      value || config11.OCO_ANTHROPIC_API_KEY || config11.OCO_AI_PROVIDER.startsWith("ollama") || config11.OCO_AZURE_API_KEY || config11.OCO_AI_PROVIDER == "llmservice" || config11.OCO_AI_PROVIDER == "test",
       "You need to provide an OpenAI/Anthropic/Azure API key"
     );
     validateConfig(
       "OCO_OPENAI_API_KEY" /* OCO_OPENAI_API_KEY */,
-      value.startsWith("sk-") || config10.OCO_AI_PROVIDER != "openai",
+      value.startsWith("sk-") || config11.OCO_AI_PROVIDER != "openai",
       'Must start with "sk-" for openai provider'
     );
     return value;
   },
-  ["OCO_AZURE_API_KEY" /* OCO_AZURE_API_KEY */](value, config10 = {}) {
+  ["OCO_AZURE_API_KEY" /* OCO_AZURE_API_KEY */](value, config11 = {}) {
     validateConfig(
       "ANTHROPIC_API_KEY",
-      value || config10.OCO_OPENAI_API_KEY || config10.OCO_AZURE_API_KEY || config10.OCO_AI_PROVIDER == "ollama" || config10.OCO_AI_PROVIDER == "test",
+      value || config11.OCO_OPENAI_API_KEY || config11.OCO_AZURE_API_KEY || config11.OCO_AI_PROVIDER == "ollama" || config11.OCO_AI_PROVIDER == "llmservice" || config11.OCO_AI_PROVIDER == "test",
       "You need to provide an OpenAI/Anthropic/Azure API key"
     );
     return value;
   },
-  ["OCO_GEMINI_API_KEY" /* OCO_GEMINI_API_KEY */](value, config10 = {}) {
-    if (config10.OCO_AI_PROVIDER != "gemini")
+  ["OCO_GEMINI_API_KEY" /* OCO_GEMINI_API_KEY */](value, config11 = {}) {
+    if (config11.OCO_AI_PROVIDER != "gemini")
       return value;
     validateConfig(
       "Gemini API Key",
-      value || config10.OCO_GEMINI_API_KEY || config10.OCO_AI_PROVIDER == "test",
+      value || config11.OCO_GEMINI_API_KEY || config11.OCO_AI_PROVIDER == "test",
       "You need to provide an Gemini API key"
     );
     return value;
   },
-  ["OCO_ANTHROPIC_API_KEY" /* OCO_ANTHROPIC_API_KEY */](value, config10 = {}) {
+  ["OCO_ANTHROPIC_API_KEY" /* OCO_ANTHROPIC_API_KEY */](value, config11 = {}) {
     validateConfig(
       "ANTHROPIC_API_KEY",
-      value || config10.OCO_OPENAI_API_KEY || config10.OCO_AI_PROVIDER == "ollama" || config10.OCO_AI_PROVIDER == "test",
+      value || config11.OCO_OPENAI_API_KEY || config11.OCO_AI_PROVIDER == "ollama" || config11.OCO_AI_PROVIDER == "llmservice" || config11.OCO_AI_PROVIDER == "test",
       "You need to provide an OpenAI/Anthropic API key"
     );
     return value;
@@ -49637,14 +49637,14 @@ var configValidators = {
     );
     return value;
   },
-  ["OCO_MODEL" /* OCO_MODEL */](value, config10 = {}) {
+  ["OCO_MODEL" /* OCO_MODEL */](value, config11 = {}) {
     validateConfig(
       "OCO_MODEL" /* OCO_MODEL */,
       [
         ...MODEL_LIST.openai,
         ...MODEL_LIST.anthropic,
         ...MODEL_LIST.gemini
-      ].includes(value) || config10.OCO_AI_PROVIDER == "ollama" || config10.OCO_AI_PROVIDER == "azure" || config10.OCO_AI_PROVIDER == "test",
+      ].includes(value) || config11.OCO_AI_PROVIDER == "ollama" || config11.OCO_AI_PROVIDER == "azure" || config11.OCO_AI_PROVIDER == "llmservice" || config11.OCO_AI_PROVIDER == "test",
       `${value} is not supported yet, use:
 
  ${[
@@ -49682,8 +49682,8 @@ var configValidators = {
   ["OCO_AI_PROVIDER" /* OCO_AI_PROVIDER */](value) {
     validateConfig(
       "OCO_AI_PROVIDER" /* OCO_AI_PROVIDER */,
-      ["", "openai", "anthropic", "gemini", "azure", "test"].includes(value) || value.startsWith("ollama"),
-      `${value} is not supported yet, use 'ollama', 'anthropic', 'azure', 'gemini' or 'openai' (default)`
+      ["", "openai", "anthropic", "gemini", "azure", "llmservice", "test"].includes(value) || value.startsWith("ollama"),
+      `${value} is not supported yet, use 'ollama', 'llmservice', 'anthropic', 'azure', 'gemini', or 'openai' (default)`
     );
     return value;
   },
@@ -49720,6 +49720,22 @@ var configValidators = {
       `${value} is not a valid URL`
     );
     return value;
+  },
+  ["OCO_BACKEND_ENDPOINT" /* OCO_BACKEND_ENDPOINT */](value) {
+    validateConfig(
+      "OCO_BACKEND_ENDPOINT" /* OCO_BACKEND_ENDPOINT */,
+      typeof value === "string",
+      "Must be string"
+    );
+    return value;
+  },
+  ["OCO_BACKEND_PATH" /* OCO_BACKEND_PATH */](value) {
+    validateConfig(
+      "OCO_BACKEND_PATH" /* OCO_BACKEND_PATH */,
+      typeof value === "string",
+      "Must be string"
+    );
+    return value;
   }
 };
 var defaultConfigPath = (0, import_path.join)((0, import_os.homedir)(), ".opencommit");
@@ -49747,26 +49763,28 @@ var getConfig = ({
     OCO_AI_PROVIDER: process.env.OCO_AI_PROVIDER || "openai",
     OCO_GITPUSH: process.env.OCO_GITPUSH === "false" ? false : true,
     OCO_ONE_LINE_COMMIT: process.env.OCO_ONE_LINE_COMMIT === "true" ? true : false,
-    OCO_AZURE_ENDPOINT: process.env.OCO_AZURE_ENDPOINT || "",
-    OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE || "commit-message"
+    OCO_AZURE_ENDPOINT: process.env.OCO_AZURE_ENDPOINT || void 0,
+    OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE || "commit-message",
+    OCO_BACKEND_ENDPOINT: process.env.OCO_BACKEND_ENDPOINT || "localhost:8000",
+    OCO_BACKEND_PATH: process.env.OCO_BACKEND_PATH || "api/generate"
   };
   const configExists = (0, import_fs.existsSync)(configPath);
   if (!configExists)
     return configFromEnv;
   const configFile = (0, import_fs.readFileSync)(configPath, "utf8");
-  const config10 = (0, import_ini.parse)(configFile);
-  for (const configKey of Object.keys(config10)) {
-    if (["null", "undefined"].includes(config10[configKey])) {
-      config10[configKey] = void 0;
+  const config11 = (0, import_ini.parse)(configFile);
+  for (const configKey of Object.keys(config11)) {
+    if (["null", "undefined"].includes(config11[configKey])) {
+      config11[configKey] = void 0;
       continue;
     }
     try {
       const validator = configValidators[configKey];
       const validValue = validator(
-        config10[configKey] ?? configFromEnv[configKey],
-        config10
+        config11[configKey] ?? configFromEnv[configKey],
+        config11
       );
-      config10[configKey] = validValue;
+      config11[configKey] = validValue;
     } catch (error) {
       ce(`Unknown '${configKey}' config option or missing validator.`);
       ce(
@@ -49775,10 +49793,10 @@ var getConfig = ({
       process.exit(1);
     }
   }
-  return config10;
+  return config11;
 };
 var setConfig = (keyValues, configPath = defaultConfigPath) => {
-  const config10 = getConfig() || {};
+  const config11 = getConfig() || {};
   for (const [configKey, configValue] of keyValues) {
     if (!configValidators.hasOwnProperty(configKey)) {
       throw new Error(`Unsupported config key: ${configKey}`);
@@ -49790,9 +49808,9 @@ var setConfig = (keyValues, configPath = defaultConfigPath) => {
       parsedConfigValue = configValue;
     }
     const validValue = configValidators[configKey](parsedConfigValue);
-    config10[configKey] = validValue;
+    config11[configKey] = validValue;
   }
-  (0, import_fs.writeFileSync)(configPath, (0, import_ini.stringify)(config10), "utf8");
+  (0, import_fs.writeFileSync)(configPath, (0, import_ini.stringify)(config11), "utf8");
   ce(`${source_default.green("\u2714")} Config successfully set`);
 };
 var configCommand = G2(
@@ -49805,9 +49823,9 @@ var configCommand = G2(
     try {
       const { mode: mode4, keyValues } = argv._;
       if (mode4 === "get" /* get */) {
-        const config10 = getConfig() || {};
+        const config11 = getConfig() || {};
         for (const key of keyValues) {
-          ce(`${key}=${config10[key]}`);
+          ce(`${key}=${config11[key]}`);
         }
       } else if (mode4 === "set" /* set */) {
         await setConfig(
@@ -49916,8 +49934,8 @@ var getPrompt = (ruleName, ruleConfig, prompt) => {
   ce(`${source_default.red("\u2716")} No prompt handler for rule "${ruleName}".`);
   return `Please manualy set the prompt for rule "${ruleName}".`;
 };
-var inferPromptsFromCommitlintConfig = (config10) => {
-  const { rules, prompt } = config10;
+var inferPromptsFromCommitlintConfig = (config11) => {
+  const { rules, prompt } = config11;
   if (!rules)
     return [];
   return Object.keys(rules).map(
@@ -50430,7 +50448,7 @@ var utils_default = {
 };
 
 // node_modules/axios/lib/core/AxiosError.js
-function AxiosError(message, code, config10, request3, response) {
+function AxiosError(message, code, config11, request3, response) {
   Error.call(this);
   if (Error.captureStackTrace) {
     Error.captureStackTrace(this, this.constructor);
@@ -50440,7 +50458,7 @@ function AxiosError(message, code, config10, request3, response) {
   this.message = message;
   this.name = "AxiosError";
   code && (this.code = code);
-  config10 && (this.config = config10);
+  config11 && (this.config = config11);
   request3 && (this.request = request3);
   response && (this.response = response);
 }
@@ -50481,14 +50499,14 @@ var descriptors = {};
 });
 Object.defineProperties(AxiosError, descriptors);
 Object.defineProperty(prototype, "isAxiosError", { value: true });
-AxiosError.from = (error, code, config10, request3, response, customProps) => {
+AxiosError.from = (error, code, config11, request3, response, customProps) => {
   const axiosError = Object.create(prototype);
   utils_default.toFlatObject(error, axiosError, function filter2(obj) {
     return obj !== Error.prototype;
   }, (prop) => {
     return prop !== "isAxiosError";
   });
-  AxiosError.call(axiosError, error.message, code, config10, request3, response);
+  AxiosError.call(axiosError, error.message, code, config11, request3, response);
   axiosError.cause = error;
   axiosError.name = error.name;
   customProps && Object.assign(axiosError, customProps);
@@ -51184,12 +51202,12 @@ var AxiosHeaders_default = AxiosHeaders;
 
 // node_modules/axios/lib/core/transformData.js
 function transformData(fns, response) {
-  const config10 = this || defaults_default;
-  const context2 = response || config10;
+  const config11 = this || defaults_default;
+  const context2 = response || config11;
   const headers = AxiosHeaders_default.from(context2.headers);
   let data = context2.data;
   utils_default.forEach(fns, function transform(fn) {
-    data = fn.call(config10, data, headers.normalize(), response ? response.status : void 0);
+    data = fn.call(config11, data, headers.normalize(), response ? response.status : void 0);
   });
   headers.normalize();
   return data;
@@ -51201,8 +51219,8 @@ function isCancel(value) {
 }
 
 // node_modules/axios/lib/cancel/CanceledError.js
-function CanceledError(message, config10, request3) {
-  AxiosError_default.call(this, message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config10, request3);
+function CanceledError(message, config11, request3) {
+  AxiosError_default.call(this, message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config11, request3);
   this.name = "CanceledError";
 }
 utils_default.inherits(CanceledError, AxiosError_default, {
@@ -51734,11 +51752,11 @@ var resolveFamily = ({ address, family }) => {
   };
 };
 var buildAddressEntry = (address, family) => resolveFamily(utils_default.isObject(address) ? address : { address, family });
-var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
+var http_default = isHttpAdapterSupported && function httpAdapter(config11) {
   return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) {
-    let { data, lookup, family } = config10;
-    const { responseType, responseEncoding } = config10;
-    const method = config10.method.toUpperCase();
+    let { data, lookup, family } = config11;
+    const { responseType, responseEncoding } = config11;
+    const method = config11.method.toUpperCase();
     let isDone;
     let rejected = false;
     let req;
@@ -51756,11 +51774,11 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
     }
     const emitter = new import_events.EventEmitter();
     const onFinished = () => {
-      if (config10.cancelToken) {
-        config10.cancelToken.unsubscribe(abort);
+      if (config11.cancelToken) {
+        config11.cancelToken.unsubscribe(abort);
       }
-      if (config10.signal) {
-        config10.signal.removeEventListener("abort", abort);
+      if (config11.signal) {
+        config11.signal.removeEventListener("abort", abort);
       }
       emitter.removeAllListeners();
     };
@@ -51772,16 +51790,16 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
       }
     });
     function abort(reason) {
-      emitter.emit("abort", !reason || reason.type ? new CanceledError_default(null, config10, req) : reason);
+      emitter.emit("abort", !reason || reason.type ? new CanceledError_default(null, config11, req) : reason);
     }
     emitter.once("abort", reject);
-    if (config10.cancelToken || config10.signal) {
-      config10.cancelToken && config10.cancelToken.subscribe(abort);
-      if (config10.signal) {
-        config10.signal.aborted ? abort() : config10.signal.addEventListener("abort", abort);
+    if (config11.cancelToken || config11.signal) {
+      config11.cancelToken && config11.cancelToken.subscribe(abort);
+      if (config11.signal) {
+        config11.signal.aborted ? abort() : config11.signal.addEventListener("abort", abort);
       }
     }
-    const fullPath = buildFullPath(config10.baseURL, config10.url);
+    const fullPath = buildFullPath(config11.baseURL, config11.url);
     const parsed = new URL(fullPath, "http://localhost");
     const protocol = parsed.protocol || supportedProtocols[0];
     if (protocol === "data:") {
@@ -51791,15 +51809,15 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
           status: 405,
           statusText: "method not allowed",
           headers: {},
-          config: config10
+          config: config11
         });
       }
       try {
-        convertedData = fromDataURI(config10.url, responseType === "blob", {
-          Blob: config10.env && config10.env.Blob
+        convertedData = fromDataURI(config11.url, responseType === "blob", {
+          Blob: config11.env && config11.env.Blob
         });
       } catch (err) {
-        throw AxiosError_default.from(err, AxiosError_default.ERR_BAD_REQUEST, config10);
+        throw AxiosError_default.from(err, AxiosError_default.ERR_BAD_REQUEST, config11);
       }
       if (responseType === "text") {
         convertedData = convertedData.toString(responseEncoding);
@@ -51814,21 +51832,21 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
         status: 200,
         statusText: "OK",
         headers: new AxiosHeaders_default(),
-        config: config10
+        config: config11
       });
     }
     if (supportedProtocols.indexOf(protocol) === -1) {
       return reject(new AxiosError_default(
         "Unsupported protocol " + protocol,
         AxiosError_default.ERR_BAD_REQUEST,
-        config10
+        config11
       ));
     }
-    const headers = AxiosHeaders_default.from(config10.headers).normalize();
+    const headers = AxiosHeaders_default.from(config11.headers).normalize();
     headers.set("User-Agent", "axios/" + VERSION, false);
-    const onDownloadProgress = config10.onDownloadProgress;
-    const onUploadProgress = config10.onUploadProgress;
-    const maxRate = config10.maxRate;
+    const onDownloadProgress = config11.onDownloadProgress;
+    const onUploadProgress = config11.onUploadProgress;
+    const maxRate = config11.maxRate;
     let maxUploadRate = void 0;
     let maxDownloadRate = void 0;
     if (utils_default.isSpecCompliantForm(data)) {
@@ -51862,15 +51880,15 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
         return reject(new AxiosError_default(
           "Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream",
           AxiosError_default.ERR_BAD_REQUEST,
-          config10
+          config11
         ));
       }
       headers.setContentLength(data.length, false);
-      if (config10.maxBodyLength > -1 && data.length > config10.maxBodyLength) {
+      if (config11.maxBodyLength > -1 && data.length > config11.maxBodyLength) {
         return reject(new AxiosError_default(
           "Request body larger than maxBodyLength limit",
           AxiosError_default.ERR_BAD_REQUEST,
-          config10
+          config11
         ));
       }
     }
@@ -51896,9 +51914,9 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
       });
     }
     let auth = void 0;
-    if (config10.auth) {
-      const username = config10.auth.username || "";
-      const password = config10.auth.password || "";
+    if (config11.auth) {
+      const username = config11.auth.username || "";
+      const password = config11.auth.password || "";
       auth = username + ":" + password;
     }
     if (!auth && parsed.username) {
@@ -51911,13 +51929,13 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
     try {
       path2 = buildURL(
         parsed.pathname + parsed.search,
-        config10.params,
-        config10.paramsSerializer
+        config11.params,
+        config11.paramsSerializer
       ).replace(/^\?/, "");
     } catch (err) {
       const customErr = new Error(err.message);
-      customErr.config = config10;
-      customErr.url = config10.url;
+      customErr.config = config11;
+      customErr.url = config11.url;
       customErr.exists = true;
       return reject(customErr);
     }
@@ -51930,7 +51948,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
       path: path2,
       method,
       headers: headers.toJSON(),
-      agents: { http: config10.httpAgent, https: config10.httpsAgent },
+      agents: { http: config11.httpAgent, https: config11.httpsAgent },
       auth,
       protocol,
       family,
@@ -51938,36 +51956,36 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
       beforeRedirects: {}
     };
     !utils_default.isUndefined(lookup) && (options.lookup = lookup);
-    if (config10.socketPath) {
-      options.socketPath = config10.socketPath;
+    if (config11.socketPath) {
+      options.socketPath = config11.socketPath;
     } else {
       options.hostname = parsed.hostname;
       options.port = parsed.port;
-      setProxy(options, config10.proxy, protocol + "//" + parsed.hostname + (parsed.port ? ":" + parsed.port : "") + options.path);
+      setProxy(options, config11.proxy, protocol + "//" + parsed.hostname + (parsed.port ? ":" + parsed.port : "") + options.path);
     }
     let transport;
     const isHttpsRequest = isHttps.test(options.protocol);
-    options.agent = isHttpsRequest ? config10.httpsAgent : config10.httpAgent;
-    if (config10.transport) {
-      transport = config10.transport;
-    } else if (config10.maxRedirects === 0) {
+    options.agent = isHttpsRequest ? config11.httpsAgent : config11.httpAgent;
+    if (config11.transport) {
+      transport = config11.transport;
+    } else if (config11.maxRedirects === 0) {
       transport = isHttpsRequest ? import_https.default : import_http.default;
     } else {
-      if (config10.maxRedirects) {
-        options.maxRedirects = config10.maxRedirects;
+      if (config11.maxRedirects) {
+        options.maxRedirects = config11.maxRedirects;
       }
-      if (config10.beforeRedirect) {
-        options.beforeRedirects.config = config10.beforeRedirect;
+      if (config11.beforeRedirect) {
+        options.beforeRedirects.config = config11.beforeRedirect;
       }
       transport = isHttpsRequest ? httpsFollow : httpFollow;
     }
-    if (config10.maxBodyLength > -1) {
-      options.maxBodyLength = config10.maxBodyLength;
+    if (config11.maxBodyLength > -1) {
+      options.maxBodyLength = config11.maxBodyLength;
     } else {
       options.maxBodyLength = Infinity;
     }
-    if (config10.insecureHTTPParser) {
-      options.insecureHTTPParser = config10.insecureHTTPParser;
+    if (config11.insecureHTTPParser) {
+      options.insecureHTTPParser = config11.insecureHTTPParser;
     }
     req = transport.request(options, function handleResponse(res) {
       if (req.destroyed)
@@ -51988,7 +52006,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
       }
       let responseStream = res;
       const lastRequest = res.req || req;
-      if (config10.decompress !== false && res.headers["content-encoding"]) {
+      if (config11.decompress !== false && res.headers["content-encoding"]) {
         if (method === "HEAD" || res.statusCode === 204) {
           delete res.headers["content-encoding"];
         }
@@ -52021,7 +52039,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
         status: res.statusCode,
         statusText: res.statusMessage,
         headers: new AxiosHeaders_default(res.headers),
-        config: config10,
+        config: config11,
         request: lastRequest
       };
       if (responseType === "stream") {
@@ -52033,13 +52051,13 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
         responseStream.on("data", function handleStreamData(chunk) {
           responseBuffer.push(chunk);
           totalResponseBytes += chunk.length;
-          if (config10.maxContentLength > -1 && totalResponseBytes > config10.maxContentLength) {
+          if (config11.maxContentLength > -1 && totalResponseBytes > config11.maxContentLength) {
             rejected = true;
             responseStream.destroy();
             reject(new AxiosError_default(
-              "maxContentLength size of " + config10.maxContentLength + " exceeded",
+              "maxContentLength size of " + config11.maxContentLength + " exceeded",
               AxiosError_default.ERR_BAD_RESPONSE,
-              config10,
+              config11,
               lastRequest
             ));
           }
@@ -52049,9 +52067,9 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
             return;
           }
           const err = new AxiosError_default(
-            "maxContentLength size of " + config10.maxContentLength + " exceeded",
+            "maxContentLength size of " + config11.maxContentLength + " exceeded",
             AxiosError_default.ERR_BAD_RESPONSE,
-            config10,
+            config11,
             lastRequest
           );
           responseStream.destroy(err);
@@ -52060,7 +52078,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
         responseStream.on("error", function handleStreamError(err) {
           if (req.destroyed)
             return;
-          reject(AxiosError_default.from(err, null, config10, lastRequest));
+          reject(AxiosError_default.from(err, null, config11, lastRequest));
         });
         responseStream.on("end", function handleStreamEnd() {
           try {
@@ -52073,7 +52091,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
             }
             response.data = responseData;
           } catch (err) {
-            return reject(AxiosError_default.from(err, null, config10, response.request, response));
+            return reject(AxiosError_default.from(err, null, config11, response.request, response));
           }
           settle(resolve, reject, response);
         });
@@ -52090,18 +52108,18 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
       req.destroy(err);
     });
     req.on("error", function handleRequestError(err) {
-      reject(AxiosError_default.from(err, null, config10, req));
+      reject(AxiosError_default.from(err, null, config11, req));
     });
     req.on("socket", function handleRequestSocket(socket) {
       socket.setKeepAlive(true, 1e3 * 60);
     });
-    if (config10.timeout) {
-      const timeout = parseInt(config10.timeout, 10);
+    if (config11.timeout) {
+      const timeout = parseInt(config11.timeout, 10);
       if (Number.isNaN(timeout)) {
         reject(new AxiosError_default(
           "error trying to parse `config.timeout` to int",
           AxiosError_default.ERR_BAD_OPTION_VALUE,
-          config10,
+          config11,
           req
         ));
         return;
@@ -52109,15 +52127,15 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
       req.setTimeout(timeout, function handleRequestTimeout() {
         if (isDone)
           return;
-        let timeoutErrorMessage = config10.timeout ? "timeout of " + config10.timeout + "ms exceeded" : "timeout exceeded";
-        const transitional2 = config10.transitional || transitional_default;
-        if (config10.timeoutErrorMessage) {
-          timeoutErrorMessage = config10.timeoutErrorMessage;
+        let timeoutErrorMessage = config11.timeout ? "timeout of " + config11.timeout + "ms exceeded" : "timeout exceeded";
+        const transitional2 = config11.transitional || transitional_default;
+        if (config11.timeoutErrorMessage) {
+          timeoutErrorMessage = config11.timeoutErrorMessage;
         }
         reject(new AxiosError_default(
           timeoutErrorMessage,
           transitional2.clarifyTimeoutError ? AxiosError_default.ETIMEDOUT : AxiosError_default.ECONNABORTED,
-          config10,
+          config11,
           req
         ));
         abort();
@@ -52135,7 +52153,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config10) {
       });
       data.on("close", () => {
         if (!ended && !errored) {
-          abort(new CanceledError_default("Request stream has been aborted", config10, req));
+          abort(new CanceledError_default("Request stream has been aborted", config11, req));
         }
       });
       data.pipe(req);
@@ -52231,18 +52249,18 @@ function progressEventReducer(listener, isDownloadStream) {
   };
 }
 var isXHRAdapterSupported = typeof XMLHttpRequest !== "undefined";
-var xhr_default = isXHRAdapterSupported && function(config10) {
+var xhr_default = isXHRAdapterSupported && function(config11) {
   return new Promise(function dispatchXhrRequest(resolve, reject) {
-    let requestData = config10.data;
-    const requestHeaders = AxiosHeaders_default.from(config10.headers).normalize();
-    let { responseType, withXSRFToken } = config10;
+    let requestData = config11.data;
+    const requestHeaders = AxiosHeaders_default.from(config11.headers).normalize();
+    let { responseType, withXSRFToken } = config11;
     let onCanceled;
     function done() {
-      if (config10.cancelToken) {
-        config10.cancelToken.unsubscribe(onCanceled);
+      if (config11.cancelToken) {
+        config11.cancelToken.unsubscribe(onCanceled);
       }
-      if (config10.signal) {
-        config10.signal.removeEventListener("abort", onCanceled);
+      if (config11.signal) {
+        config11.signal.removeEventListener("abort", onCanceled);
       }
     }
     let contentType;
@@ -52255,14 +52273,14 @@ var xhr_default = isXHRAdapterSupported && function(config10) {
       }
     }
     let request3 = new XMLHttpRequest();
-    if (config10.auth) {
-      const username = config10.auth.username || "";
-      const password = config10.auth.password ? unescape(encodeURIComponent(config10.auth.password)) : "";
+    if (config11.auth) {
+      const username = config11.auth.username || "";
+      const password = config11.auth.password ? unescape(encodeURIComponent(config11.auth.password)) : "";
       requestHeaders.set("Authorization", "Basic " + btoa(username + ":" + password));
     }
-    const fullPath = buildFullPath(config10.baseURL, config10.url);
-    request3.open(config10.method.toUpperCase(), buildURL(fullPath, config10.params, config10.paramsSerializer), true);
-    request3.timeout = config10.timeout;
+    const fullPath = buildFullPath(config11.baseURL, config11.url);
+    request3.open(config11.method.toUpperCase(), buildURL(fullPath, config11.params, config11.paramsSerializer), true);
+    request3.timeout = config11.timeout;
     function onloadend() {
       if (!request3) {
         return;
@@ -52276,7 +52294,7 @@ var xhr_default = isXHRAdapterSupported && function(config10) {
         status: request3.status,
         statusText: request3.statusText,
         headers: responseHeaders,
-        config: config10,
+        config: config11,
         request: request3
       };
       settle(function _resolve(value) {
@@ -52305,33 +52323,33 @@ var xhr_default = isXHRAdapterSupported && function(config10) {
       if (!request3) {
         return;
       }
-      reject(new AxiosError_default("Request aborted", AxiosError_default.ECONNABORTED, config10, request3));
+      reject(new AxiosError_default("Request aborted", AxiosError_default.ECONNABORTED, config11, request3));
       request3 = null;
     };
     request3.onerror = function handleError() {
-      reject(new AxiosError_default("Network Error", AxiosError_default.ERR_NETWORK, config10, request3));
+      reject(new AxiosError_default("Network Error", AxiosError_default.ERR_NETWORK, config11, request3));
       request3 = null;
     };
     request3.ontimeout = function handleTimeout() {
-      let timeoutErrorMessage = config10.timeout ? "timeout of " + config10.timeout + "ms exceeded" : "timeout exceeded";
-      const transitional2 = config10.transitional || transitional_default;
-      if (config10.timeoutErrorMessage) {
-        timeoutErrorMessage = config10.timeoutErrorMessage;
+      let timeoutErrorMessage = config11.timeout ? "timeout of " + config11.timeout + "ms exceeded" : "timeout exceeded";
+      const transitional2 = config11.transitional || transitional_default;
+      if (config11.timeoutErrorMessage) {
+        timeoutErrorMessage = config11.timeoutErrorMessage;
       }
       reject(new AxiosError_default(
         timeoutErrorMessage,
         transitional2.clarifyTimeoutError ? AxiosError_default.ETIMEDOUT : AxiosError_default.ECONNABORTED,
-        config10,
+        config11,
         request3
       ));
       request3 = null;
     };
     if (platform_default.hasStandardBrowserEnv) {
-      withXSRFToken && utils_default.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config10));
+      withXSRFToken && utils_default.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config11));
       if (withXSRFToken || withXSRFToken !== false && isURLSameOrigin_default(fullPath)) {
-        const xsrfValue = config10.xsrfHeaderName && config10.xsrfCookieName && cookies_default.read(config10.xsrfCookieName);
+        const xsrfValue = config11.xsrfHeaderName && config11.xsrfCookieName && cookies_default.read(config11.xsrfCookieName);
         if (xsrfValue) {
-          requestHeaders.set(config10.xsrfHeaderName, xsrfValue);
+          requestHeaders.set(config11.xsrfHeaderName, xsrfValue);
         }
       }
     }
@@ -52341,35 +52359,35 @@ var xhr_default = isXHRAdapterSupported && function(config10) {
         request3.setRequestHeader(key, val);
       });
     }
-    if (!utils_default.isUndefined(config10.withCredentials)) {
-      request3.withCredentials = !!config10.withCredentials;
+    if (!utils_default.isUndefined(config11.withCredentials)) {
+      request3.withCredentials = !!config11.withCredentials;
     }
     if (responseType && responseType !== "json") {
-      request3.responseType = config10.responseType;
+      request3.responseType = config11.responseType;
     }
-    if (typeof config10.onDownloadProgress === "function") {
-      request3.addEventListener("progress", progressEventReducer(config10.onDownloadProgress, true));
+    if (typeof config11.onDownloadProgress === "function") {
+      request3.addEventListener("progress", progressEventReducer(config11.onDownloadProgress, true));
     }
-    if (typeof config10.onUploadProgress === "function" && request3.upload) {
-      request3.upload.addEventListener("progress", progressEventReducer(config10.onUploadProgress));
+    if (typeof config11.onUploadProgress === "function" && request3.upload) {
+      request3.upload.addEventListener("progress", progressEventReducer(config11.onUploadProgress));
     }
-    if (config10.cancelToken || config10.signal) {
+    if (config11.cancelToken || config11.signal) {
       onCanceled = (cancel) => {
         if (!request3) {
           return;
         }
-        reject(!cancel || cancel.type ? new CanceledError_default(null, config10, request3) : cancel);
+        reject(!cancel || cancel.type ? new CanceledError_default(null, config11, request3) : cancel);
         request3.abort();
         request3 = null;
       };
-      config10.cancelToken && config10.cancelToken.subscribe(onCanceled);
-      if (config10.signal) {
-        config10.signal.aborted ? onCanceled() : config10.signal.addEventListener("abort", onCanceled);
+      config11.cancelToken && config11.cancelToken.subscribe(onCanceled);
+      if (config11.signal) {
+        config11.signal.aborted ? onCanceled() : config11.signal.addEventListener("abort", onCanceled);
       }
     }
     const protocol = parseProtocol(fullPath);
     if (protocol && platform_default.protocols.indexOf(protocol) === -1) {
-      reject(new AxiosError_default("Unsupported protocol " + protocol + ":", AxiosError_default.ERR_BAD_REQUEST, config10));
+      reject(new AxiosError_default("Unsupported protocol " + protocol + ":", AxiosError_default.ERR_BAD_REQUEST, config11));
       return;
     }
     request3.send(requestData || null);
@@ -52430,41 +52448,41 @@ var adapters_default = {
 };
 
 // node_modules/axios/lib/core/dispatchRequest.js
-function throwIfCancellationRequested(config10) {
-  if (config10.cancelToken) {
-    config10.cancelToken.throwIfRequested();
+function throwIfCancellationRequested(config11) {
+  if (config11.cancelToken) {
+    config11.cancelToken.throwIfRequested();
   }
-  if (config10.signal && config10.signal.aborted) {
-    throw new CanceledError_default(null, config10);
+  if (config11.signal && config11.signal.aborted) {
+    throw new CanceledError_default(null, config11);
   }
 }
-function dispatchRequest(config10) {
-  throwIfCancellationRequested(config10);
-  config10.headers = AxiosHeaders_default.from(config10.headers);
-  config10.data = transformData.call(
-    config10,
-    config10.transformRequest
+function dispatchRequest(config11) {
+  throwIfCancellationRequested(config11);
+  config11.headers = AxiosHeaders_default.from(config11.headers);
+  config11.data = transformData.call(
+    config11,
+    config11.transformRequest
   );
-  if (["post", "put", "patch"].indexOf(config10.method) !== -1) {
-    config10.headers.setContentType("application/x-www-form-urlencoded", false);
+  if (["post", "put", "patch"].indexOf(config11.method) !== -1) {
+    config11.headers.setContentType("application/x-www-form-urlencoded", false);
   }
-  const adapter = adapters_default.getAdapter(config10.adapter || defaults_default.adapter);
-  return adapter(config10).then(function onAdapterResolution(response) {
-    throwIfCancellationRequested(config10);
+  const adapter = adapters_default.getAdapter(config11.adapter || defaults_default.adapter);
+  return adapter(config11).then(function onAdapterResolution(response) {
+    throwIfCancellationRequested(config11);
     response.data = transformData.call(
-      config10,
-      config10.transformResponse,
+      config11,
+      config11.transformResponse,
       response
     );
     response.headers = AxiosHeaders_default.from(response.headers);
     return response;
   }, function onAdapterRejection(reason) {
     if (!isCancel(reason)) {
-      throwIfCancellationRequested(config10);
+      throwIfCancellationRequested(config11);
       if (reason && reason.response) {
         reason.response.data = transformData.call(
-          config10,
-          config10.transformResponse,
+          config11,
+          config11.transformResponse,
           reason.response
         );
         reason.response.headers = AxiosHeaders_default.from(reason.response.headers);
@@ -52478,7 +52496,7 @@ function dispatchRequest(config10) {
 var headersToObject = (thing) => thing instanceof AxiosHeaders_default ? { ...thing } : thing;
 function mergeConfig(config1, config22) {
   config22 = config22 || {};
-  const config10 = {};
+  const config11 = {};
   function getMergedValue(target, source, caseless) {
     if (utils_default.isPlainObject(target) && utils_default.isPlainObject(source)) {
       return utils_default.merge.call({ caseless }, target, source);
@@ -52549,9 +52567,9 @@ function mergeConfig(config1, config22) {
   utils_default.forEach(Object.keys(Object.assign({}, config1, config22)), function computeConfigValue(prop) {
     const merge2 = mergeMap[prop] || mergeDeepProperties;
     const configValue = merge2(config1[prop], config22[prop], prop);
-    utils_default.isUndefined(configValue) && merge2 !== mergeDirectKeys || (config10[prop] = configValue);
+    utils_default.isUndefined(configValue) && merge2 !== mergeDirectKeys || (config11[prop] = configValue);
   });
-  return config10;
+  return config11;
 }
 
 // node_modules/axios/lib/helpers/validator.js
@@ -52622,9 +52640,9 @@ var Axios = class {
       response: new InterceptorManager_default()
     };
   }
-  async request(configOrUrl, config10) {
+  async request(configOrUrl, config11) {
     try {
-      return await this._request(configOrUrl, config10);
+      return await this._request(configOrUrl, config11);
     } catch (err) {
       if (err instanceof Error) {
         let dummy;
@@ -52639,15 +52657,15 @@ var Axios = class {
       throw err;
     }
   }
-  _request(configOrUrl, config10) {
+  _request(configOrUrl, config11) {
     if (typeof configOrUrl === "string") {
-      config10 = config10 || {};
-      config10.url = configOrUrl;
+      config11 = config11 || {};
+      config11.url = configOrUrl;
     } else {
-      config10 = configOrUrl || {};
+      config11 = configOrUrl || {};
     }
-    config10 = mergeConfig(this.defaults, config10);
-    const { transitional: transitional2, paramsSerializer, headers } = config10;
+    config11 = mergeConfig(this.defaults, config11);
+    const { transitional: transitional2, paramsSerializer, headers } = config11;
     if (transitional2 !== void 0) {
       validator_default.assertOptions(transitional2, {
         silentJSONParsing: validators2.transitional(validators2.boolean),
@@ -52657,7 +52675,7 @@ var Axios = class {
     }
     if (paramsSerializer != null) {
       if (utils_default.isFunction(paramsSerializer)) {
-        config10.paramsSerializer = {
+        config11.paramsSerializer = {
           serialize: paramsSerializer
         };
       } else {
@@ -52667,10 +52685,10 @@ var Axios = class {
         }, true);
       }
     }
-    config10.method = (config10.method || this.defaults.method || "get").toLowerCase();
+    config11.method = (config11.method || this.defaults.method || "get").toLowerCase();
     let contextHeaders = headers && utils_default.merge(
       headers.common,
-      headers[config10.method]
+      headers[config11.method]
     );
     headers && utils_default.forEach(
       ["delete", "get", "head", "post", "put", "patch", "common"],
@@ -52678,11 +52696,11 @@ var Axios = class {
         delete headers[method];
       }
     );
-    config10.headers = AxiosHeaders_default.concat(contextHeaders, headers);
+    config11.headers = AxiosHeaders_default.concat(contextHeaders, headers);
     const requestInterceptorChain = [];
     let synchronousRequestInterceptors = true;
     this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
-      if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config10) === false) {
+      if (typeof interceptor.runWhen === "function" && interceptor.runWhen(config11) === false) {
         return;
       }
       synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
@@ -52700,14 +52718,14 @@ var Axios = class {
       chain.unshift.apply(chain, requestInterceptorChain);
       chain.push.apply(chain, responseInterceptorChain);
       len = chain.length;
-      promise = Promise.resolve(config10);
+      promise = Promise.resolve(config11);
       while (i3 < len) {
         promise = promise.then(chain[i3++], chain[i3++]);
       }
       return promise;
     }
     len = requestInterceptorChain.length;
-    let newConfig = config10;
+    let newConfig = config11;
     i3 = 0;
     while (i3 < len) {
       const onFulfilled = requestInterceptorChain[i3++];
@@ -52731,25 +52749,25 @@ var Axios = class {
     }
     return promise;
   }
-  getUri(config10) {
-    config10 = mergeConfig(this.defaults, config10);
-    const fullPath = buildFullPath(config10.baseURL, config10.url);
-    return buildURL(fullPath, config10.params, config10.paramsSerializer);
+  getUri(config11) {
+    config11 = mergeConfig(this.defaults, config11);
+    const fullPath = buildFullPath(config11.baseURL, config11.url);
+    return buildURL(fullPath, config11.params, config11.paramsSerializer);
   }
 };
 utils_default.forEach(["delete", "get", "head", "options"], function forEachMethodNoData(method) {
-  Axios.prototype[method] = function(url2, config10) {
-    return this.request(mergeConfig(config10 || {}, {
+  Axios.prototype[method] = function(url2, config11) {
+    return this.request(mergeConfig(config11 || {}, {
       method,
       url: url2,
-      data: (config10 || {}).data
+      data: (config11 || {}).data
     }));
   };
 });
 utils_default.forEach(["post", "put", "patch"], function forEachMethodWithData(method) {
   function generateHTTPMethod(isForm) {
-    return function httpMethod(url2, data, config10) {
-      return this.request(mergeConfig(config10 || {}, {
+    return function httpMethod(url2, data, config11) {
+      return this.request(mergeConfig(config11 || {}, {
         method,
         headers: isForm ? {
           "Content-Type": "multipart/form-data"
@@ -52795,11 +52813,11 @@ var CancelToken = class {
       };
       return promise;
     };
-    executor(function cancel(message, config10, request3) {
+    executor(function cancel(message, config11, request3) {
       if (token.reason) {
         return;
       }
-      token.reason = new CanceledError_default(message, config10, request3);
+      token.reason = new CanceledError_default(message, config11, request3);
       resolvePromise(token.reason);
     });
   }
@@ -59826,10 +59844,35 @@ var Azure = class {
 };
 var azure = new Azure();
 
+// src/engine/llmservice.ts
+var config7 = getConfig();
+var LlmService = class {
+  async generateCommitMessage(messages) {
+    const gitDiff = messages[messages.length - 1]?.content;
+    const url2 = `http://${config7?.OCO_BACKEND_ENDPOINT}/${config7?.OCO_BACKEND_PATH}`;
+    const payload = {
+      system_prompt: messages[0]?.content,
+      user_prompt: gitDiff
+    };
+    try {
+      const response = await axios_default.post(url2, payload, {
+        headers: {
+          "Content-Type": "application/json"
+        }
+      });
+      const message = response.data;
+      return message;
+    } catch (err) {
+      const message = err.response?.data?.error ?? err.message;
+      throw new Error("local model issues. details: " + message);
+    }
+  }
+};
+
 // src/utils/engine.ts
 function getEngine() {
-  const config10 = getConfig();
-  const provider4 = config10?.OCO_AI_PROVIDER;
+  const config11 = getConfig();
+  const provider4 = config11?.OCO_AI_PROVIDER;
   if (provider4?.startsWith("ollama")) {
     const ollamaAi = new OllamaAi();
     const model = provider4.split("/")[1];
@@ -59844,13 +59887,15 @@ function getEngine() {
     return new Gemini();
   } else if (provider4 == "azure") {
     return new Azure();
+  } else if (provider4 == "llmservice") {
+    return new LlmService();
   }
   return new OpenAi();
 }
 
 // src/modules/commitlint/config.ts
-var config7 = getConfig();
-var translation2 = i18n[config7?.OCO_LANGUAGE || "en"];
+var config8 = getConfig();
+var translation2 = i18n[config8?.OCO_LANGUAGE || "en"];
 var configureCommitlintIntegration = async (force = false) => {
   const spin = le();
   spin.start("Loading @commitlint configuration");
@@ -59903,15 +59948,15 @@ function removeConventionalCommitWord(message) {
 }
 
 // src/prompts.ts
-var config8 = getConfig();
-var translation3 = i18n[config8?.OCO_LANGUAGE || "en"];
+var config9 = getConfig();
+var translation3 = i18n[config9?.OCO_LANGUAGE || "en"];
 var IDENTITY = "You are to act as the author of a commit message in git.";
 var INIT_MAIN_PROMPT2 = (language, fullGitMojiSpec) => ({
   role: import_openai4.ChatCompletionRequestMessageRoleEnum.System,
   content: `${IDENTITY} Your mission is to create clean and comprehensive commit messages as per the ${fullGitMojiSpec ? "GitMoji specification" : "conventional commit convention"} and explain WHAT were the changes and mainly WHY the changes were done. I'll send you an output of 'git diff --staged' command, and you are to convert it into a commit message.
-  ${config8?.OCO_EMOJI ? `Use GitMoji convention to preface the commit. Here are some help to choose the right emoji (emoji, description): \u{1F41B}, Fix a bug; \u2728, Introduce new features; \u{1F4DD}, Add or update documentation; \u{1F680}, Deploy stuff; \u2705, Add, update, or pass tests; \u267B\uFE0F, Refactor code; \u2B06\uFE0F, Upgrade dependencies; \u{1F527}, Add or update configuration files; \u{1F310}, Internationalization and localization; \u{1F4A1}, Add or update comments in source code; ${fullGitMojiSpec ? "\u{1F3A8}, Improve structure / format of the code; \u26A1\uFE0F, Improve performance; \u{1F525}, Remove code or files; \u{1F691}\uFE0F, Critical hotfix; \u{1F484}, Add or update the UI and style files; \u{1F389}, Begin a project; \u{1F512}\uFE0F, Fix security issues; \u{1F510}, Add or update secrets; \u{1F516}, Release / Version tags; \u{1F6A8}, Fix compiler / linter warnings; \u{1F6A7}, Work in progress; \u{1F49A}, Fix CI Build; \u2B07\uFE0F, Downgrade dependencies; \u{1F4CC}, Pin dependencies to specific versions; \u{1F477}, Add or update CI build system; \u{1F4C8}, Add or update analytics or track code; \u2795, Add a dependency; \u2796, Remove a dependency; \u{1F528}, Add or update development scripts; \u270F\uFE0F, Fix typos; \u{1F4A9}, Write bad code that needs to be improved; \u23EA\uFE0F, Revert changes; \u{1F500}, Merge branches; \u{1F4E6}\uFE0F, Add or update compiled files or packages; \u{1F47D}\uFE0F, Update code due to external API changes; \u{1F69A}, Move or rename resources (e.g.: files, paths, routes); \u{1F4C4}, Add or update license; \u{1F4A5}, Introduce breaking changes; \u{1F371}, Add or update assets; \u267F\uFE0F, Improve accessibility; \u{1F37B}, Write code drunkenly; \u{1F4AC}, Add or update text and literals; \u{1F5C3}\uFE0F, Perform database related changes; \u{1F50A}, Add or update logs; \u{1F507}, Remove logs; \u{1F465}, Add or update contributor(s); \u{1F6B8}, Improve user experience / usability; \u{1F3D7}\uFE0F, Make architectural changes; \u{1F4F1}, Work on responsive design; \u{1F921}, Mock things; \u{1F95A}, Add or update an easter egg; \u{1F648}, Add or update a .gitignore file; \u{1F4F8}, Add or update snapshots; \u2697\uFE0F, Perform experiments; \u{1F50D}\uFE0F, Improve SEO; \u{1F3F7}\uFE0F, Add or update types; \u{1F331}, Add or update seed files; \u{1F6A9}, Add, update, or remove feature flags; \u{1F945}, Catch errors; \u{1F4AB}, Add or update animations and transitions; \u{1F5D1}\uFE0F, Deprecate code that needs to be cleaned up; \u{1F6C2}, Work on code related to authorization, roles and permissions; \u{1FA79}, Simple fix for a non-critical issue; \u{1F9D0}, Data exploration/inspection; \u26B0\uFE0F, Remove dead code; \u{1F9EA}, Add a failing test; \u{1F454}, Add or update business logic; \u{1FA7A}, Add or update healthcheck; \u{1F9F1}, Infrastructure related changes; \u{1F9D1}\u200D\u{1F4BB}, Improve developer experience; \u{1F4B8}, Add sponsorships or money related infrastructure; \u{1F9F5}, Add or update code related to multithreading or concurrency; \u{1F9BA}, Add or update code related to validation." : ""}` : "Do not preface the commit with anything. Conventional commit keywords:fix, feat, build, chore, ci, docs, style, refactor, perf, test."}  
-    ${config8?.OCO_DESCRIPTION ? `Add a short description of WHY the changes are done after the commit message. Don't start it with "This commit", just describe the changes.` : "Don't add any descriptions to the commit, only commit message."}
-    ${config8?.OCO_ONE_LINE_COMMIT ? "Craft a concise commit message that encapsulates all changes made, with an emphasis on the primary updates. If the modifications share a common theme or scope, mention it succinctly; otherwise, leave the scope out to maintain focus. The goal is to provide a clear and unified overview of the changes in a one single message, without diverging into a list of commit per file change." : ""}
+  ${config9?.OCO_EMOJI ? `Use GitMoji convention to preface the commit. Here are some help to choose the right emoji (emoji, description): \u{1F41B}, Fix a bug; \u2728, Introduce new features; \u{1F4DD}, Add or update documentation; \u{1F680}, Deploy stuff; \u2705, Add, update, or pass tests; \u267B\uFE0F, Refactor code; \u2B06\uFE0F, Upgrade dependencies; \u{1F527}, Add or update configuration files; \u{1F310}, Internationalization and localization; \u{1F4A1}, Add or update comments in source code; ${fullGitMojiSpec ? "\u{1F3A8}, Improve structure / format of the code; \u26A1\uFE0F, Improve performance; \u{1F525}, Remove code or files; \u{1F691}\uFE0F, Critical hotfix; \u{1F484}, Add or update the UI and style files; \u{1F389}, Begin a project; \u{1F512}\uFE0F, Fix security issues; \u{1F510}, Add or update secrets; \u{1F516}, Release / Version tags; \u{1F6A8}, Fix compiler / linter warnings; \u{1F6A7}, Work in progress; \u{1F49A}, Fix CI Build; \u2B07\uFE0F, Downgrade dependencies; \u{1F4CC}, Pin dependencies to specific versions; \u{1F477}, Add or update CI build system; \u{1F4C8}, Add or update analytics or track code; \u2795, Add a dependency; \u2796, Remove a dependency; \u{1F528}, Add or update development scripts; \u270F\uFE0F, Fix typos; \u{1F4A9}, Write bad code that needs to be improved; \u23EA\uFE0F, Revert changes; \u{1F500}, Merge branches; \u{1F4E6}\uFE0F, Add or update compiled files or packages; \u{1F47D}\uFE0F, Update code due to external API changes; \u{1F69A}, Move or rename resources (e.g.: files, paths, routes); \u{1F4C4}, Add or update license; \u{1F4A5}, Introduce breaking changes; \u{1F371}, Add or update assets; \u267F\uFE0F, Improve accessibility; \u{1F37B}, Write code drunkenly; \u{1F4AC}, Add or update text and literals; \u{1F5C3}\uFE0F, Perform database related changes; \u{1F50A}, Add or update logs; \u{1F507}, Remove logs; \u{1F465}, Add or update contributor(s); \u{1F6B8}, Improve user experience / usability; \u{1F3D7}\uFE0F, Make architectural changes; \u{1F4F1}, Work on responsive design; \u{1F921}, Mock things; \u{1F95A}, Add or update an easter egg; \u{1F648}, Add or update a .gitignore file; \u{1F4F8}, Add or update snapshots; \u2697\uFE0F, Perform experiments; \u{1F50D}\uFE0F, Improve SEO; \u{1F3F7}\uFE0F, Add or update types; \u{1F331}, Add or update seed files; \u{1F6A9}, Add, update, or remove feature flags; \u{1F945}, Catch errors; \u{1F4AB}, Add or update animations and transitions; \u{1F5D1}\uFE0F, Deprecate code that needs to be cleaned up; \u{1F6C2}, Work on code related to authorization, roles and permissions; \u{1FA79}, Simple fix for a non-critical issue; \u{1F9D0}, Data exploration/inspection; \u26B0\uFE0F, Remove dead code; \u{1F9EA}, Add a failing test; \u{1F454}, Add or update business logic; \u{1FA7A}, Add or update healthcheck; \u{1F9F1}, Infrastructure related changes; \u{1F9D1}\u200D\u{1F4BB}, Improve developer experience; \u{1F4B8}, Add sponsorships or money related infrastructure; \u{1F9F5}, Add or update code related to multithreading or concurrency; \u{1F9BA}, Add or update code related to validation." : ""}` : "Do not preface the commit with anything. Conventional commit keywords:fix, feat, build, chore, ci, docs, style, refactor, perf, test."}  
+    ${config9?.OCO_DESCRIPTION ? `Add a short description of WHY the changes are done after the commit message. Don't start it with "This commit", just describe the changes.` : "Don't add any descriptions to the commit, only commit message."}
+    ${config9?.OCO_ONE_LINE_COMMIT ? "Craft a concise commit message that encapsulates all changes made, with an emphasis on the primary updates. If the modifications share a common theme or scope, mention it succinctly; otherwise, leave the scope out to maintain focus. The goal is to provide a clear and unified overview of the changes in a one single message, without diverging into a list of commit per file change." : ""}
     Use the present tense. Lines must not be longer than 74 characters. Use ${language} for the commit message.`
 });
 var INIT_DIFF_PROMPT = {
@@ -59943,12 +59988,12 @@ var INIT_DIFF_PROMPT = {
 };
 var INIT_CONSISTENCY_PROMPT = (translation4) => ({
   role: import_openai4.ChatCompletionRequestMessageRoleEnum.Assistant,
-  content: `${config8?.OCO_EMOJI ? `\u{1F41B} ${removeConventionalCommitWord(translation4.commitFix)}` : translation4.commitFix}
-${config8?.OCO_EMOJI ? `\u2728 ${removeConventionalCommitWord(translation4.commitFeat)}` : translation4.commitFeat}
-${config8?.OCO_DESCRIPTION ? translation4.commitDescription : ""}`
+  content: `${config9?.OCO_EMOJI ? `\u{1F41B} ${removeConventionalCommitWord(translation4.commitFix)}` : translation4.commitFix}
+${config9?.OCO_EMOJI ? `\u2728 ${removeConventionalCommitWord(translation4.commitFeat)}` : translation4.commitFeat}
+${config9?.OCO_DESCRIPTION ? translation4.commitDescription : ""}`
 });
 var getMainCommitPrompt = async (fullGitMojiSpec) => {
-  switch (config8?.OCO_PROMPT_MODULE) {
+  switch (config9?.OCO_PROMPT_MODULE) {
     case "@commitlint":
       if (!await commitlintLLMConfigExists()) {
         ie(
@@ -59993,9 +60038,9 @@ function mergeDiffs(arr, maxStringLength) {
 }
 
 // src/generateCommitMessageFromGitDiff.ts
-var config9 = getConfig();
-var MAX_TOKENS_INPUT4 = config9?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */;
-var MAX_TOKENS_OUTPUT4 = config9?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */;
+var config10 = getConfig();
+var MAX_TOKENS_INPUT4 = config10?.OCO_TOKENS_MAX_INPUT || 4096 /* DEFAULT_MAX_TOKENS_INPUT */;
+var MAX_TOKENS_OUTPUT4 = config10?.OCO_TOKENS_MAX_OUTPUT || 500 /* DEFAULT_MAX_TOKENS_OUTPUT */;
 var generateCommitMessageChatCompletionPrompt = async (diff, fullGitMojiSpec) => {
   const INIT_MESSAGES_PROMPT = await getMainCommitPrompt(fullGitMojiSpec);
   const chatContextAsCompletionRequest = [...INIT_MESSAGES_PROMPT];
diff --git a/src/commands/config.ts b/src/commands/config.ts
index 8987144a..2dd88b31 100644
--- a/src/commands/config.ts
+++ b/src/commands/config.ts
@@ -33,7 +33,9 @@ export enum CONFIG_KEYS {
   OCO_AZURE_ENDPOINT = 'OCO_AZURE_ENDPOINT',
   OCO_TEST_MOCK_TYPE = 'OCO_TEST_MOCK_TYPE',
   OCO_API_URL = 'OCO_API_URL',
-  OCO_OLLAMA_API_URL = 'OCO_OLLAMA_API_URL'
+  OCO_OLLAMA_API_URL = 'OCO_OLLAMA_API_URL',
+  OCO_BACKEND_ENDPOINT = 'OCO_BACKEND_ENDPOINT',
+  OCO_BACKEND_PATH = 'OCO_BACKEND_PATH'
 }
 
 export enum CONFIG_MODES {
@@ -130,6 +132,7 @@ export const configValidators = {
         config.OCO_ANTHROPIC_API_KEY ||
         config.OCO_AI_PROVIDER.startsWith('ollama') ||
         config.OCO_AZURE_API_KEY ||
+        config.OCO_AI_PROVIDER == 'llmservice' ||
         config.OCO_AI_PROVIDER == 'test',
       'You need to provide an OpenAI/Anthropic/Azure API key'
     );
@@ -149,6 +152,7 @@ export const configValidators = {
         config.OCO_OPENAI_API_KEY ||
         config.OCO_AZURE_API_KEY ||
         config.OCO_AI_PROVIDER == 'ollama' ||
+        config.OCO_AI_PROVIDER == 'llmservice' ||
         config.OCO_AI_PROVIDER == 'test',
       'You need to provide an OpenAI/Anthropic/Azure API key'
     );
@@ -175,6 +179,7 @@ export const configValidators = {
       value ||
         config.OCO_OPENAI_API_KEY ||
         config.OCO_AI_PROVIDER == 'ollama' ||
+        config.OCO_AI_PROVIDER == 'llmservice' ||
         config.OCO_AI_PROVIDER == 'test',
       'You need to provide an OpenAI/Anthropic API key'
     );
@@ -268,6 +273,7 @@ export const configValidators = {
       ].includes(value) ||
         config.OCO_AI_PROVIDER == 'ollama' ||
         config.OCO_AI_PROVIDER == 'azure' ||
+        config.OCO_AI_PROVIDER == 'llmservice' ||
         config.OCO_AI_PROVIDER == 'test',
       `${value} is not supported yet, use:\n\n ${[
         ...MODEL_LIST.openai,
@@ -308,9 +314,9 @@ export const configValidators = {
   [CONFIG_KEYS.OCO_AI_PROVIDER](value: any) {
     validateConfig(
       CONFIG_KEYS.OCO_AI_PROVIDER,
-      ['', 'openai', 'anthropic', 'gemini', 'azure', 'test'].includes(value) ||
+      ['', 'openai', 'anthropic', 'gemini', 'azure', 'llmservice', 'test'].includes(value) ||
         value.startsWith('ollama'),
-      `${value} is not supported yet, use 'ollama', 'anthropic', 'azure', 'gemini' or 'openai' (default)`
+      `${value} is not supported yet, use 'ollama', 'llmservice', 'anthropic', 'azure', 'gemini', or 'openai' (default)`
     );
     return value;
   },
@@ -352,7 +358,26 @@ export const configValidators = {
       `${value} is not a valid URL`
     );
     return value;
+  },
+
+  [CONFIG_KEYS.OCO_BACKEND_ENDPOINT](value: any) {
+    validateConfig(
+      CONFIG_KEYS.OCO_BACKEND_ENDPOINT,
+      typeof value === 'string',
+      'Must be string'
+    );
+    return value;
+  },
+
+  [CONFIG_KEYS.OCO_BACKEND_PATH](value: any) {
+    validateConfig(
+      CONFIG_KEYS.OCO_BACKEND_PATH,
+      typeof value === 'string',
+      'Must be string'
+    );
+    return value;
   }
+
 };
 
 export type ConfigType = {
@@ -396,7 +421,9 @@ export const getConfig = ({
     OCO_ONE_LINE_COMMIT:
       process.env.OCO_ONE_LINE_COMMIT === 'true' ? true : false,
     OCO_AZURE_ENDPOINT: process.env.OCO_AZURE_ENDPOINT || undefined,
-    OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE || 'commit-message'
+    OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE || 'commit-message',
+    OCO_BACKEND_ENDPOINT: process.env.OCO_BACKEND_ENDPOINT || 'localhost:8000',
+    OCO_BACKEND_PATH: process.env.OCO_BACKEND_PATH || 'api/generate'
   };
 
   const configExists = existsSync(configPath);
diff --git a/src/engine/llmservice.ts b/src/engine/llmservice.ts
new file mode 100644
index 00000000..7f51b335
--- /dev/null
+++ b/src/engine/llmservice.ts
@@ -0,0 +1,38 @@
+import axios, { AxiosError } from 'axios';
+import { ChatCompletionRequestMessage } from 'openai';
+import { AiEngine } from './Engine';
+import {
+  getConfig
+} from '../commands/config';
+
+const config = getConfig();
+
+
+export class LlmService implements AiEngine {
+
+  async generateCommitMessage(
+    messages: Array<ChatCompletionRequestMessage>
+  ): Promise<string | undefined> {
+
+    const gitDiff = messages[ messages.length - 1 ]?.content;
+    const url = `http://${config?.OCO_BACKEND_ENDPOINT}/${config?.OCO_BACKEND_PATH}`; // this key is specific to flowise
+    const payload = {
+        user_prompt: gitDiff
+    }
+
+    try {
+      const response = await axios.post(url, payload, {
+        headers: {
+          'Content-Type': 'application/json'
+        }
+      });
+      const message = response.data;
+      // have to check the returned message from flowise, it's not documented in their api page
+
+      return message;
+    } catch (err: any) {
+      const message = err.response?.data?.error ?? err.message;
+      throw new Error('local model issues. details: ' + message);
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/utils/engine.ts b/src/utils/engine.ts
index ac9fdfda..7e92fd09 100644
--- a/src/utils/engine.ts
+++ b/src/utils/engine.ts
@@ -6,6 +6,7 @@ import { OllamaAi } from '../engine/ollama';
 import { AnthropicAi } from '../engine/anthropic'
 import { TestAi } from '../engine/testAi';
 import { Azure } from '../engine/azure';
+import { LlmService } from '../engine/llmservice';
 
 export function getEngine(): AiEngine {
   const config = getConfig();
@@ -25,6 +26,8 @@ export function getEngine(): AiEngine {
     return new Gemini();  
   } else if (provider == 'azure') {
   	return new Azure();
+  } else if(provider == 'llmservice'){
+    return new LlmService();
   }
   
   //open ai gpt by default

From dc804418873e28a3bb9f7bcf56a652c871b2a027 Mon Sep 17 00:00:00 2001
From: JMN09 <157629053+JMN09@users.noreply.github.com>
Date: Mon, 19 Aug 2024 12:07:56 +0300
Subject: [PATCH 2/2] Removed comments

---
 src/engine/llmservice.ts | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/engine/llmservice.ts b/src/engine/llmservice.ts
index 7f51b335..31534804 100644
--- a/src/engine/llmservice.ts
+++ b/src/engine/llmservice.ts
@@ -15,7 +15,7 @@ export class LlmService implements AiEngine {
   ): Promise<string | undefined> {
 
     const gitDiff = messages[ messages.length - 1 ]?.content;
-    const url = `http://${config?.OCO_BACKEND_ENDPOINT}/${config?.OCO_BACKEND_PATH}`; // this key is specific to flowise
+    const url = `http://${config?.OCO_BACKEND_ENDPOINT}/${config?.OCO_BACKEND_PATH}`; 
     const payload = {
         user_prompt: gitDiff
     }
@@ -27,7 +27,6 @@ export class LlmService implements AiEngine {
         }
       });
       const message = response.data;
-      // have to check the returned message from flowise, it's not documented in their api page
 
       return message;
     } catch (err: any) {