From 3bb4f5907ad8108923dc528c5f8a0ae1ae84bf46 Mon Sep 17 00:00:00 2001 From: Shonchik Date: Thu, 8 Aug 2024 15:33:15 +0700 Subject: [PATCH] add concurrency --- .../Extensions/AnyPublisher+Concurrency.swift | 55 +++++++++++++++++++ Sources/ExyteOpenAI/OpenAI+Assistants.swift | 28 ++++++++++ Sources/ExyteOpenAI/OpenAI+Chats.swift | 12 ++++ Sources/ExyteOpenAI/OpenAI+Files.swift | 28 ++++++++++ Sources/ExyteOpenAI/OpenAI+Messages.swift | 24 ++++++++ Sources/ExyteOpenAI/OpenAI+Models.swift | 20 +++++++ Sources/ExyteOpenAI/OpenAI+Runs.swift | 48 ++++++++++++++++ Sources/ExyteOpenAI/OpenAI+Threads.swift | 24 ++++++++ 8 files changed, 239 insertions(+) create mode 100644 Sources/ExyteOpenAI/Networking/Extensions/AnyPublisher+Concurrency.swift diff --git a/Sources/ExyteOpenAI/Networking/Extensions/AnyPublisher+Concurrency.swift b/Sources/ExyteOpenAI/Networking/Extensions/AnyPublisher+Concurrency.swift new file mode 100644 index 0000000..58bdb3f --- /dev/null +++ b/Sources/ExyteOpenAI/Networking/Extensions/AnyPublisher+Concurrency.swift @@ -0,0 +1,55 @@ +// +// AnyPublisher+Concurrency.swift +// +// Copyright (c) 2024 Exyte +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import Combine +import Foundation + +extension AnyPublisher { + func async() async throws -> Output { + try await withCheckedThrowingContinuation { continuation in + var cancellable: AnyCancellable? + var finishedWithoutValue = true + cancellable = first() + .sink( + receiveCompletion: { result in + switch result { + case .finished: + if finishedWithoutValue { + continuation.resume(throwing: OpenAIError.emptyResponse) + } + case .failure(let error): + continuation.resume(throwing: error) + } + cancellable?.cancel() + + }, + receiveValue: { value in + finishedWithoutValue = false + continuation.resume(with: .success(value)) + + } + ) + } + } +} diff --git a/Sources/ExyteOpenAI/OpenAI+Assistants.swift b/Sources/ExyteOpenAI/OpenAI+Assistants.swift index 1b8bc28..ec495ff 100644 --- a/Sources/ExyteOpenAI/OpenAI+Assistants.swift +++ b/Sources/ExyteOpenAI/OpenAI+Assistants.swift @@ -25,6 +25,8 @@ import Foundation import Combine +// MARK: - Combine + public extension OpenAI { func createAssistant(from payload: CreateAssistantPayload) -> AnyPublisher { @@ -68,3 +70,29 @@ public extension OpenAI { } } + +// MARK: - Concurrency + +public extension OpenAI { + + func createAssistant(from payload: CreateAssistantPayload) async throws -> Assistant { + try await createAssistant(from: payload).async() + } + + func modifyAssistant(id: String, payload: CreateAssistantPayload) async throws -> Assistant { + try await modifyAssistant(id: id, payload: payload).async() + } + + func deleteAssistant(id: String) async throws -> DeletionStatus { + try await deleteAssistant(id: id).async() + } + + func listAssistants(payload: ListPayload) async throws -> ObjectList { + try await listAssistants(payload: payload).async() + } + + func retrieveAssistant(id: String) async throws -> Assistant { + try await retrieveAssistant(id: id).async() + } + +} diff --git a/Sources/ExyteOpenAI/OpenAI+Chats.swift b/Sources/ExyteOpenAI/OpenAI+Chats.swift index 82cf325..8aaba7d 100644 --- a/Sources/ExyteOpenAI/OpenAI+Chats.swift +++ b/Sources/ExyteOpenAI/OpenAI+Chats.swift @@ -25,6 +25,8 @@ import Foundation import Combine +// MARK: - Combine + public extension OpenAI { func createChatCompletion(from payload: CreateChatCompletionPayload) -> AnyPublisher { @@ -35,3 +37,13 @@ public extension OpenAI { } } + +// MARK: - Concurrency + +public extension OpenAI { + + func createChatCompletion(from payload: CreateChatCompletionPayload) async throws -> ChatCompletion { + try await createChatCompletion(from: payload).async() + } + +} diff --git a/Sources/ExyteOpenAI/OpenAI+Files.swift b/Sources/ExyteOpenAI/OpenAI+Files.swift index 26eda23..7eb859f 100644 --- a/Sources/ExyteOpenAI/OpenAI+Files.swift +++ b/Sources/ExyteOpenAI/OpenAI+Files.swift @@ -25,6 +25,8 @@ import Foundation import Combine +// MARK: - Combine + public extension OpenAI { func uploadFile(payload: FilePayload) -> AnyPublisher { @@ -64,3 +66,29 @@ public extension OpenAI { } } + +// MARK: - Concurrency + +public extension OpenAI { + + func uploadFile(payload: FilePayload) async throws -> File { + try await uploadFile(payload: payload).async() + } + + func listFiles() async throws -> ObjectList { + try await listFiles().async() + } + + func retrieveFile(id: String) async throws -> File { + try await retrieveFile(id: id).async() + } + + func deleteFile(id: String) async throws -> DeletionStatus { + try await deleteFile(id: id).async() + } + + func retrieveFileContent(id: String, destinationURL: URL) async throws -> URL { + try await retrieveFileContent(id: id, destinationURL: destinationURL).async() + } + +} diff --git a/Sources/ExyteOpenAI/OpenAI+Messages.swift b/Sources/ExyteOpenAI/OpenAI+Messages.swift index c08551b..bf26442 100644 --- a/Sources/ExyteOpenAI/OpenAI+Messages.swift +++ b/Sources/ExyteOpenAI/OpenAI+Messages.swift @@ -25,6 +25,8 @@ import Foundation import Combine +// MARK: - Combine + public extension OpenAI { func createMessage(in threadId: String, payload: CreateMessagePayload) -> AnyPublisher { @@ -72,3 +74,25 @@ public extension OpenAI { } } + +// MARK: - Concurrency + +public extension OpenAI { + + func createMessage(in threadId: String, payload: CreateMessagePayload) async throws -> Message { + try await createMessage(in: threadId, payload: payload).async() + } + + func listMessages(from threadId: String, payload: ListPayload) async throws -> ObjectList { + try await listMessages(from: threadId, payload: payload).async() + } + + func retrieveMessage(id: String, from threadId: String) async throws -> Message { + try await retrieveMessage(id: id, from: threadId).async() + } + + func modifyMessage(id: String, from threadId: String, payload: ModifyPayload) async throws -> Message { + try await modifyMessage(id: id, from: threadId, payload: payload).async() + } + +} diff --git a/Sources/ExyteOpenAI/OpenAI+Models.swift b/Sources/ExyteOpenAI/OpenAI+Models.swift index 8a1059d..b80e035 100644 --- a/Sources/ExyteOpenAI/OpenAI+Models.swift +++ b/Sources/ExyteOpenAI/OpenAI+Models.swift @@ -25,6 +25,8 @@ import Foundation import Combine +// MARK: - Combine + public extension OpenAI { func listModels() -> AnyPublisher, OpenAIError> { @@ -49,3 +51,21 @@ public extension OpenAI { } } + +// MARK: - Concurrency + +public extension OpenAI { + + func listModels() async throws -> ObjectList { + try await listModels().async() + } + + func retrieveModel(with id: String) async throws -> Model { + try await retrieveModel(with: id).async() + } + + func deleteModel(with id: String) async throws -> DeletionStatus { + try await deleteModel(with: id).async() + } + +} diff --git a/Sources/ExyteOpenAI/OpenAI+Runs.swift b/Sources/ExyteOpenAI/OpenAI+Runs.swift index 532831d..174fcde 100644 --- a/Sources/ExyteOpenAI/OpenAI+Runs.swift +++ b/Sources/ExyteOpenAI/OpenAI+Runs.swift @@ -26,6 +26,8 @@ import Foundation import Combine import EventSourceHttpBody +// MARK: - Combine + public extension OpenAI { func createRun(in threadId: String, payload: CreateRunPayload) -> AnyPublisher { @@ -174,3 +176,49 @@ public extension OpenAI { } } + +// MARK: - Concurrency + +public extension OpenAI { + + func createRun(in threadId: String, payload: CreateRunPayload) async throws -> Run { + try await createRun(in: threadId, payload: payload).async() + } + + func createStreamRun(in threadId: String, payload: CreateStreamRunPayload) async throws -> StreamEvent { + try await createStreamRun(in: threadId, payload: payload).async() + } + + func createThreadAndRun(from payload: CreateThreadAndRunPayload) async throws -> Run { + try await createThreadAndRun(from: payload).async() + } + + func listRuns(from threadId: String, payload: ListPayload) async throws -> ObjectList { + try await listRuns(from: threadId, payload: payload).async() + } + + func retrieveRun(id: String, from threadId: String) async throws -> Run { + try await retrieveRun(id: id, from: threadId).async() + } + + func modifyRun(id: String, from threadId: String, payload: ModifyPayload) async throws -> Run { + try await modifyRun(id: id, from: threadId, payload: payload).async() + } + + func cancelRun(id: String, from threadId: String) async throws -> Run { + try await cancelRun(id: id, from: threadId).async() + } + + func submitToolOutputs(to runId: String, from threadId: String, payload: SubmitToolOutputsPayload) async throws -> Run { + try await submitToolOutputs(to: runId, from: threadId, payload: payload).async() + } + + func listRunSteps(from runId: String, in threadId: String, payload: ListPayload) async throws -> ObjectList { + try await listRunSteps(from: runId, in: threadId, payload: payload).async() + } + + func retrieveRunStep(id: String, from runId: String, in threadId: String) async throws -> RunStep { + try await retrieveRunStep(id: id, from: runId, in: threadId).async() + } + +} diff --git a/Sources/ExyteOpenAI/OpenAI+Threads.swift b/Sources/ExyteOpenAI/OpenAI+Threads.swift index 24a57b0..9e60c13 100644 --- a/Sources/ExyteOpenAI/OpenAI+Threads.swift +++ b/Sources/ExyteOpenAI/OpenAI+Threads.swift @@ -25,6 +25,8 @@ import Foundation import Combine +// MARK: - Combine + public extension OpenAI { func createThread(from payload: CreateThreadPayload) -> AnyPublisher { @@ -61,3 +63,25 @@ public extension OpenAI { } } + +// MARK: - Concurrency + +public extension OpenAI { + + func createThread(from payload: CreateThreadPayload) async throws -> Thread { + try await createThread(from: payload).async() + } + + func retrieveThread(id: String) async throws -> Thread { + try await retrieveThread(id: id).async() + } + + func modifyThread(id: String, payload: ModifyPayload) async throws -> Thread { + try await modifyThread(id: id, payload: payload).async() + } + + func deleteThread(id: String) async throws -> DeletionStatus { + try await deleteThread(id: id).async() + } + +}