45 from the 'ollama' server was received |
45 from the 'ollama' server was received |
46 @signal modelsList(modelNames:list[str]) emitted after the list of model |
46 @signal modelsList(modelNames:list[str]) emitted after the list of model |
47 names was obtained from the 'ollama' server |
47 names was obtained from the 'ollama' server |
48 @signal pullStatus(msg:str, id:str, total:int, completed:int) emitted to indicate |
48 @signal pullStatus(msg:str, id:str, total:int, completed:int) emitted to indicate |
49 the status of a pull request as reported by the 'ollama' server |
49 the status of a pull request as reported by the 'ollama' server |
|
50 @signal pullError(msg:str) emitted to indicate an error during a pull operation |
50 @signal serverVersion(version:str) emitted after the server version was obtained |
51 @signal serverVersion(version:str) emitted after the server version was obtained |
51 from the 'ollama' server |
52 from the 'ollama' server |
52 @signal finished() emitted to indicate the completion of a request |
53 @signal finished() emitted to indicate the completion of a request |
53 @signal errorOccurred(error:str) emitted to indicate a network error occurred |
54 @signal errorOccurred(error:str) emitted to indicate a network error occurred |
54 while processing the request |
55 while processing the request |
56 responsiveness |
57 responsiveness |
57 """ |
58 """ |
58 |
59 |
59 replyReceived = pyqtSignal(str, str, bool) |
60 replyReceived = pyqtSignal(str, str, bool) |
60 modelsList = pyqtSignal(list) |
61 modelsList = pyqtSignal(list) |
61 pullStatus = pyqtSignal(str, str, int, int) |
62 pullStatus = pyqtSignal(str, str, "unsigned long int", "unsigned long int") |
|
63 pullError = pyqtSignal(str) |
62 serverVersion = pyqtSignal(str) |
64 serverVersion = pyqtSignal(str) |
63 finished = pyqtSignal() |
65 finished = pyqtSignal() |
64 errorOccurred = pyqtSignal(str) |
66 errorOccurred = pyqtSignal(str) |
65 serverStateChanged = pyqtSignal(bool) |
67 serverStateChanged = pyqtSignal(bool) |
66 |
68 |
75 """ |
77 """ |
76 super().__init__(parent=parent) |
78 super().__init__(parent=parent) |
77 |
79 |
78 self.__plugin = plugin |
80 self.__plugin = plugin |
79 self.__replies = [] |
81 self.__replies = [] |
|
82 self.__pullReply = None |
80 |
83 |
81 self.__networkManager = QNetworkAccessManager(self) |
84 self.__networkManager = QNetworkAccessManager(self) |
82 self.__networkManager.proxyAuthenticationRequired.connect( |
85 self.__networkManager.proxyAuthenticationRequired.connect( |
83 proxyAuthenticationRequired |
86 proxyAuthenticationRequired |
84 ) |
87 ) |
191 Private method to process a pull response of the 'ollama' server. |
193 Private method to process a pull response of the 'ollama' server. |
192 |
194 |
193 @param response dictionary containing the pull response |
195 @param response dictionary containing the pull response |
194 @type dict |
196 @type dict |
195 """ |
197 """ |
196 with contextlib.suppress(KeyError): |
198 if "error" in response: |
197 status = response["status"] |
199 self.pullError.emit(response["error"]) |
198 idStr = response.get("digest", "")[:20] |
200 else: |
199 total = response.get("total", 0) |
201 with contextlib.suppress(KeyError): |
200 completed = response.get("completed", 0) |
202 status = response["status"] |
201 self.pullStatus.emit(status, idStr, total, completed) |
203 idStr = response.get("digest", "")[:20] |
|
204 total = response.get("total", 0) |
|
205 completed = response.get("completed", 0) |
|
206 self.pullStatus.emit(status, idStr, total, completed) |
|
207 |
|
208 def abortPull(self): |
|
209 """ |
|
210 Public method to abort an ongoing pull operation. |
|
211 """ |
|
212 if self.__pullReply is not None: |
|
213 self.__pullReply.close() |
202 |
214 |
203 def remove(self, model): |
215 def remove(self, model): |
204 """ |
216 """ |
205 Public method to ask the 'ollama' server to delete the given model. |
217 Public method to ask the 'ollama' server to delete the given model. |
206 |
218 |
397 self.__state = OllamaClientState.Requesting |
409 self.__state = OllamaClientState.Requesting |
398 |
410 |
399 reply = self.__getServerReply(endpoint=endpoint, data=data) |
411 reply = self.__getServerReply(endpoint=endpoint, data=data) |
400 reply.finished.connect(lambda: self.__replyFinished(reply)) |
412 reply.finished.connect(lambda: self.__replyFinished(reply)) |
401 reply.readyRead.connect(lambda: self.__processData(reply, processResponse)) |
413 reply.readyRead.connect(lambda: self.__processData(reply, processResponse)) |
402 self.__replies.append(reply) |
414 if endpoint == "pull": |
|
415 self.__pullReply = reply |
|
416 else: |
|
417 self.__replies.append(reply) |
403 |
418 |
404 def __replyFinished(self, reply): |
419 def __replyFinished(self, reply): |
405 """ |
420 """ |
406 Private method to handle the finished signal of the reply. |
421 Private method to handle the finished signal of the reply. |
407 |
422 |
408 @param reply reference to the finished network reply object |
423 @param reply reference to the finished network reply object |
409 @type QNetworkReply |
424 @type QNetworkReply |
410 """ |
425 """ |
411 self.__state = OllamaClientState.Finished |
426 self.__state = OllamaClientState.Finished |
412 |
427 |
413 if reply in self.__replies: |
428 if reply == self.__pullReply: |
|
429 self.__pullReply = None |
|
430 elif reply in self.__replies: |
414 self.__replies.remove(reply) |
431 self.__replies.remove(reply) |
415 |
432 |
416 reply.deleteLater() |
433 reply.deleteLater() |
|
434 |
|
435 self.finished.emit() |
417 |
436 |
418 def __errorOccurred(self, errorCode, reply): |
437 def __errorOccurred(self, errorCode, reply): |
419 """ |
438 """ |
420 Private method to handle a network error of the given reply. |
439 Private method to handle a network error of the given reply. |
421 |
440 |
422 @param errorCode error code reported by the reply |
441 @param errorCode error code reported by the reply |
423 @type QNetworkReply.NetworkError |
442 @type QNetworkReply.NetworkError |
424 @param reply reference to the network reply object |
443 @param reply reference to the network reply object |
425 @type QNetworkReply |
444 @type QNetworkReply |
426 """ |
445 """ |
427 if errorCode != QNetworkReply.NetworkError.NoError: |
446 if errorCode not in ( |
|
447 QNetworkReply.NetworkError.NoError, |
|
448 QNetworkReply.NetworkError.OperationCanceledError, |
|
449 ): |
428 self.errorOccurred.emit( |
450 self.errorOccurred.emit( |
429 self.tr("<p>A network error occurred.</p><p>Error: {0}</p>").format( |
451 self.tr("<p>A network error occurred.</p><p>Error: {0}</p>").format( |
430 reply.errorString() |
452 reply.errorString() |
431 ) |
453 ) |
432 ) |
454 ) |