Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Sources/OllamaKit/OllamaKit+Chat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ extension OllamaKit {
/// - Returns: An `AsyncThrowingStream<OKChatResponse, Error>` emitting the live stream of chat responses from the Ollama API.
public func chat(data: OKChatRequestData) -> AsyncThrowingStream<OKChatResponse, Error> {
do {
let request = try OKRouter.chat(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.chat(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.stream(request: request, with: OKChatResponse.self)
} catch {
Expand Down Expand Up @@ -197,7 +197,7 @@ extension OllamaKit {
/// - Returns: An `AnyPublisher<OKChatResponse, Error>` emitting the live stream of chat responses from the Ollama API.
public func chat(data: OKChatRequestData) -> AnyPublisher<OKChatResponse, Error> {
do {
let request = try OKRouter.chat(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.chat(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.stream(request: request, with: OKChatResponse.self)
} catch {
Expand Down
4 changes: 2 additions & 2 deletions Sources/OllamaKit/OllamaKit+CopyModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extension OllamaKit {
/// - Parameter data: The ``OKCopyModelRequestData`` containing the details needed to copy the model.
/// - Throws: An error if the request to copy the model fails.
public func copyModel(data: OKCopyModelRequestData) async throws -> Void {
let request = try OKRouter.copyModel(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.copyModel(data: data).asURLRequest(with: baseURL, with: bearerToken)

try await OKHTTPClient.shared.send(request: request)
}
Expand All @@ -48,7 +48,7 @@ extension OllamaKit {
/// - Returns: A `AnyPublisher<Void, Error>` that completes when the copy operation is done.
public func copyModel(data: OKCopyModelRequestData) -> AnyPublisher<Void, Error> {
do {
let request = try OKRouter.copyModel(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.copyModel(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.send(request: request)
} catch {
Expand Down
4 changes: 2 additions & 2 deletions Sources/OllamaKit/OllamaKit+DeleteModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extension OllamaKit {
/// - Parameter data: The ``OKDeleteModelRequestData`` containing the details needed to delete the model.
/// - Throws: An error if the request to delete the model fails.
public func deleteModel(data: OKDeleteModelRequestData) async throws -> Void {
let request = try OKRouter.deleteModel(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.deleteModel(data: data).asURLRequest(with: baseURL, with: bearerToken)

try await OKHTTPClient.shared.send(request: request)
}
Expand All @@ -48,7 +48,7 @@ extension OllamaKit {
/// - Returns: A `AnyPublisher<Void, Error>` that completes when the deletion operation is done.
public func deleteModel(data: OKDeleteModelRequestData) -> AnyPublisher<Void, Error> {
do {
let request = try OKRouter.deleteModel(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.deleteModel(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.send(request: request)
} catch {
Expand Down
4 changes: 2 additions & 2 deletions Sources/OllamaKit/OllamaKit+Embeddings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension OllamaKit {
/// - Returns: An ``OKEmbeddingsResponse`` containing the embeddings from the model.
/// - Throws: An error if the request fails or the response can't be decoded.
public func embeddings(data: OKEmbeddingsRequestData) async throws -> OKEmbeddingsResponse {
let request = try OKRouter.embeddings(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.embeddings(data: data).asURLRequest(with: baseURL, with: bearerToken)

return try await OKHTTPClient.shared.send(request: request, with: OKEmbeddingsResponse.self)
}
Expand All @@ -49,7 +49,7 @@ extension OllamaKit {
/// - Returns: A `AnyPublisher<OKEmbeddingsResponse, Error>` that emits embeddings.
public func embeddings(data: OKEmbeddingsRequestData) -> AnyPublisher<OKEmbeddingsResponse, Error> {
do {
let request = try OKRouter.embeddings(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.embeddings(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.send(request: request, with: OKEmbeddingsResponse.self)
} catch {
Expand Down
4 changes: 2 additions & 2 deletions Sources/OllamaKit/OllamaKit+Generate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extension OllamaKit {
/// - Returns: An `AsyncThrowingStream<OKGenerateResponse, Error>` emitting the live stream of responses from the Ollama API.
public func generate(data: OKGenerateRequestData) -> AsyncThrowingStream<OKGenerateResponse, Error> {
do {
let request = try OKRouter.generate(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.generate(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.stream(request: request, with: OKGenerateResponse.self)
} catch {
Expand Down Expand Up @@ -63,7 +63,7 @@ extension OllamaKit {
/// - Returns: An `AnyPublisher<OKGenerateResponse, Error>` emitting the live stream of responses from the Ollama API.
public func generate(data: OKGenerateRequestData) -> AnyPublisher<OKGenerateResponse, Error> {
do {
let request = try OKRouter.generate(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.generate(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.stream(request: request, with: OKGenerateResponse.self)
} catch {
Expand Down
4 changes: 2 additions & 2 deletions Sources/OllamaKit/OllamaKit+ModelInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension OllamaKit {
/// - Returns: An ``OKModelInfoResponse`` containing detailed information about the model.
/// - Throws: An error if the request fails or the response can't be decoded.
public func modelInfo(data: OKModelInfoRequestData) async throws -> OKModelInfoResponse {
let request = try OKRouter.modelInfo(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.modelInfo(data: data).asURLRequest(with: baseURL, with: bearerToken)

return try await OKHTTPClient.shared.send(request: request, with: OKModelInfoResponse.self)
}
Expand All @@ -49,7 +49,7 @@ extension OllamaKit {
/// - Returns: A `AnyPublisher<OKModelInfoResponse, Error>` that emits detailed information about the model.
public func modelInfo(data: OKModelInfoRequestData) -> AnyPublisher<OKModelInfoResponse, Error> {
do {
let request = try OKRouter.modelInfo(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.modelInfo(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.send(request: request, with: OKModelInfoResponse.self)
} catch {
Expand Down
4 changes: 2 additions & 2 deletions Sources/OllamaKit/OllamaKit+Models.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extension OllamaKit {
/// - Returns: An ``OKModelResponse`` object listing the available models.
/// - Throws: An error if the request fails or the response can't be decoded.
public func models() async throws -> OKModelResponse {
let request = try OKRouter.models.asURLRequest(with: baseURL)
let request = try OKRouter.models.asURLRequest(with: baseURL, with: bearerToken)

return try await OKHTTPClient.shared.send(request: request, with: OKModelResponse.self)
}
Expand All @@ -45,7 +45,7 @@ extension OllamaKit {
/// - Returns: A `AnyPublisher<OKModelResponse, Error>` that emits the list of available models.
public func models() -> AnyPublisher<OKModelResponse, Error> {
do {
let request = try OKRouter.models.asURLRequest(with: baseURL)
let request = try OKRouter.models.asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.send(request: request, with: OKModelResponse.self)
} catch {
Expand Down
4 changes: 2 additions & 2 deletions Sources/OllamaKit/OllamaKit+PullModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extension OllamaKit {
/// - Returns: An asynchronous stream that emits ``OKPullModelResponse``.
public func pullModel(data: OKPullModelRequestData) -> AsyncThrowingStream<OKPullModelResponse, Error> {
do {
let request = try OKRouter.pullModel(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.pullModel(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.stream(request: request, with: OKPullModelResponse.self)
} catch {
Expand Down Expand Up @@ -67,7 +67,7 @@ extension OllamaKit {
/// - Returns: A combine publisher that emits ``OKPullModelResponse``.
public func pullModel(data: OKPullModelRequestData) -> AnyPublisher<OKPullModelResponse, Error> {
do {
let request = try OKRouter.pullModel(data: data).asURLRequest(with: baseURL)
let request = try OKRouter.pullModel(data: data).asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.stream(request: request, with: OKPullModelResponse.self)
} catch {
Expand Down
4 changes: 2 additions & 2 deletions Sources/OllamaKit/OllamaKit+Reachable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extension OllamaKit {
/// - Returns: `true` if the Ollama API is reachable, `false` otherwise.
public func reachable() async -> Bool {
do {
let request = try OKRouter.root.asURLRequest(with: baseURL)
let request = try OKRouter.root.asURLRequest(with: baseURL, with: bearerToken)
try await OKHTTPClient.shared.send(request: request)

return true
Expand All @@ -47,7 +47,7 @@ extension OllamaKit {
/// - Returns: A `AnyPublisher<Bool, Never>` that emits `true` if the API is reachable, `false` otherwise.
public func reachable() -> AnyPublisher<Bool, Never> {
do {
let request = try OKRouter.root.asURLRequest(with: baseURL)
let request = try OKRouter.root.asURLRequest(with: baseURL, with: bearerToken)

return OKHTTPClient.shared.send(request: request)
.map { _ in true }
Expand Down
34 changes: 30 additions & 4 deletions Sources/OllamaKit/OllamaKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@ public struct OllamaKit: Sendable {
var router: OKRouter.Type
var decoder: JSONDecoder = .default
var baseURL: URL
var bearerToken: String?

/// Initializes a new instance of `OllamaKit` with the default base URL for the Ollama API.
/// Initializes a new instance of `OllamaKit` with the default base URL and no bearer token for the Ollama API.
///
/// ```swift
/// let ollamaKit = OllamaKit()
/// ```
public init() {
let router = OKRouter.self
self.router = router
self.baseURL = URL(string: "http://localhost:11434")!
self.init(baseURL: URL(string: "http://localhost:11434")!, bearerToken: nil)
}

/// Initializes a new instance of `OllamaKit` with a custom base URL for the Ollama API.
Expand All @@ -33,8 +32,35 @@ public struct OllamaKit: Sendable {
///
/// - Parameter baseURL: The base URL to use for API requests.
public init(baseURL: URL) {
self.init(baseURL: baseURL, bearerToken: nil)
}

/// Initializes a new instance of `OllamaKit` with a bearer token for the Ollama API.
///
/// ```swift
/// let bearerToken = "super-sected-token"
/// let ollamaKit = OllamaKit(bearerToken: bearerToken)
/// ```
///
/// - Parameter bearerToken: The bearer token to use for API requests.
public init(bearerToken: String) {
self.init(baseURL: URL(string: "http://localhost:11434")!, bearerToken: bearerToken)
}

/// Initializes a new instance of `OllamaKit` with a custom base URL and bearer token for the Ollama API.
///
/// ```swift
/// let bearerToken = "super-sected-token"
/// let customBaseURL = URL(string: "https://api.customollama.com")!
/// let ollamaKit = OllamaKit(baseURL: customBaseURL, bearerToken: bearerToken)
/// ```
///
/// - Parameter baseURL: The base URL to use for API requests.
/// - Parameter bearerToken: The bearer token to use for API requests.
public init(baseURL: URL, bearerToken: String?) {
let router = OKRouter.self
self.router = router
self.baseURL = baseURL
self.bearerToken = bearerToken
}
}
117 changes: 63 additions & 54 deletions Sources/OllamaKit/Utils/OKRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,47 +20,47 @@ internal enum OKRouter {

internal var path: String {
switch self {
case .root:
return "/"
case .models:
return "/api/tags"
case .modelInfo:
return "/api/show"
case .generate:
return "/api/generate"
case .chat:
return "/api/chat"
case .copyModel:
return "/api/copy"
case .deleteModel:
return "/api/delete"
case .pullModel:
return "/api/pull"
case .embeddings:
return "/api/embeddings"
case .root:
return "/"
case .models:
return "/api/tags"
case .modelInfo:
return "/api/show"
case .generate:
return "/api/generate"
case .chat:
return "/api/chat"
case .copyModel:
return "/api/copy"
case .deleteModel:
return "/api/delete"
case .pullModel:
return "/api/pull"
case .embeddings:
return "/api/embeddings"
}
}

internal var method: String {
switch self {
case .root:
return "HEAD"
case .models:
return "GET"
case .modelInfo:
return "POST"
case .generate:
return "POST"
case .chat:
return "POST"
case .copyModel:
return "POST"
case .deleteModel:
return "DELETE"
case .pullModel:
return "POST"
case .embeddings:
return "POST"
case .root:
return "HEAD"
case .models:
return "GET"
case .modelInfo:
return "POST"
case .generate:
return "POST"
case .chat:
return "POST"
case .copyModel:
return "POST"
case .deleteModel:
return "DELETE"
case .pullModel:
return "POST"
case .embeddings:
return "POST"
}
}

Expand All @@ -70,30 +70,39 @@ internal enum OKRouter {
}

extension OKRouter {
func asURLRequest(with baseURL: URL) throws -> URLRequest {
func asURLRequest(with baseURL: URL, with bearerToken: String?) throws -> URLRequest {
let hasBearerToken = bearerToken != nil && bearerToken!.isEmpty == false
let url = baseURL.appendingPathComponent(path)

var request = URLRequest(url: url)
request.httpMethod = method
request.allHTTPHeaderFields = headers

if (hasBearerToken) {
request.allHTTPHeaderFields = [
"Authorization": "Bearer " + bearerToken!,
"Content-Type": "application/json"
]
} else {
request.allHTTPHeaderFields = headers
}

switch self {
case .modelInfo(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .generate(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .chat(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .copyModel(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .deleteModel(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .pullModel(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .embeddings(let data):
request.httpBody = try JSONEncoder.default.encode(data)
default:
break
case .modelInfo(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .generate(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .chat(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .copyModel(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .deleteModel(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .pullModel(let data):
request.httpBody = try JSONEncoder.default.encode(data)
case .embeddings(let data):
request.httpBody = try JSONEncoder.default.encode(data)
default:
break
}

return request
Expand Down