diff --git a/Sources/OpenAI/OpenAI.swift b/Sources/OpenAI/OpenAI.swift index 4712fdda..8a2133eb 100644 --- a/Sources/OpenAI/OpenAI.swift +++ b/Sources/OpenAI/OpenAI.swift @@ -429,6 +429,10 @@ extension APIPath { .init(stringValue: "responses/\(responseId)/input_items") } + static func cancelModelResponse(responseId: String) -> Responses { + .init(stringValue: "responses/\(responseId)/cancel") + } + let stringValue: String } diff --git a/Sources/OpenAI/Public/Models/Responses API/CancelModelResponseQuery.swift b/Sources/OpenAI/Public/Models/Responses API/CancelModelResponseQuery.swift new file mode 100644 index 00000000..35413b7d --- /dev/null +++ b/Sources/OpenAI/Public/Models/Responses API/CancelModelResponseQuery.swift @@ -0,0 +1,22 @@ +// +// CancelModelResponseQuery.swift +// OpenAI +// +// Created by Tqtifnypmb on 2026/8/8. +// + +import Foundation + +/// Cancels a model response with the given ID. Only responses created with the background parameter set to true can be cancelled. +public struct CancelModelResponseQuery: Codable, Equatable, Sendable { + /// The ID of the response to cancel. + public let responseId: String + + public init(responseId: String) { + self.responseId = responseId + } + + private enum CodingKeys: String, CodingKey { + case responseId = "response_id" + } +} diff --git a/Sources/OpenAI/Public/Models/Responses API/CreateModelResponseQuery.swift b/Sources/OpenAI/Public/Models/Responses API/CreateModelResponseQuery.swift index aad64dc9..596788f4 100644 --- a/Sources/OpenAI/Public/Models/Responses API/CreateModelResponseQuery.swift +++ b/Sources/OpenAI/Public/Models/Responses API/CreateModelResponseQuery.swift @@ -40,6 +40,9 @@ public struct CreateModelResponseQuery: Codable, Equatable, Sendable { /// Whether to run the model response in the background. [Learn more](https://platform.openai.com/docs/guides/background). public let background: Bool? + /// Context management configuration for this request. + public let contextManagement: [Schemas.ContextManagementParam]? + /// Inserts a system (or developer) message as the first item in the model's context. /// /// When using along with `previousResponseId`, the instructions from a previous response will not be carried over to the next response. @@ -137,6 +140,7 @@ public struct CreateModelResponseQuery: Codable, Equatable, Sendable { model: String? = nil, include: [Schemas.IncludeEnum]? = nil, background: Bool? = nil, + contextManagement: [Schemas.ContextManagementParam]? = nil, instructions: String? = nil, maxOutputTokens: Int? = nil, metadata: Schemas.Metadata? = nil, @@ -160,6 +164,7 @@ public struct CreateModelResponseQuery: Codable, Equatable, Sendable { self.model = model self.include = include self.background = background + self.contextManagement = contextManagement self.instructions = instructions self.maxOutputTokens = maxOutputTokens self.metadata = metadata @@ -185,6 +190,7 @@ public struct CreateModelResponseQuery: Codable, Equatable, Sendable { case model case include case background + case contextManagement = "context_management" case instructions case maxOutputTokens = "max_output_tokens" case metadata diff --git a/Sources/OpenAI/Public/Models/Responses API/GetModelResponseQuery.swift b/Sources/OpenAI/Public/Models/Responses API/GetModelResponseQuery.swift index 57cffbf0..4b28105d 100644 --- a/Sources/OpenAI/Public/Models/Responses API/GetModelResponseQuery.swift +++ b/Sources/OpenAI/Public/Models/Responses API/GetModelResponseQuery.swift @@ -17,6 +17,11 @@ public struct GetModelResponseQuery: Codable, Equatable, Sendable { /// * `computer_call_output.output.image_url`: Include image urls from the computer call output. public let include: [Components.Schemas.IncludeEnum]? + public init(responseId: String, include: [Components.Schemas.IncludeEnum]?) { + self.responseId = responseId + self.include = include + } + private enum CodingKeys: String, CodingKey { case responseId = "response_id" case include diff --git a/Sources/OpenAI/Public/Protocols/ResponsesEndpointAsync.swift b/Sources/OpenAI/Public/Protocols/ResponsesEndpointAsync.swift index 295949d1..c7abcb25 100644 --- a/Sources/OpenAI/Public/Protocols/ResponsesEndpointAsync.swift +++ b/Sources/OpenAI/Public/Protocols/ResponsesEndpointAsync.swift @@ -10,4 +10,6 @@ import Foundation public protocol ResponsesEndpointAsync: Sendable { func createResponse(query: CreateModelResponseQuery) async throws -> ResponseObject func createResponseStreaming(query: CreateModelResponseQuery) -> AsyncThrowingStream + func retrieveResponse(query: GetModelResponseQuery) async throws -> ResponseObject + func cancelResponse(query: CancelModelResponseQuery) async throws -> ResponseObject } diff --git a/Sources/OpenAI/Public/Protocols/ResponsesEndpointCombine.swift b/Sources/OpenAI/Public/Protocols/ResponsesEndpointCombine.swift index 9eeb00c7..b43d7fd3 100644 --- a/Sources/OpenAI/Public/Protocols/ResponsesEndpointCombine.swift +++ b/Sources/OpenAI/Public/Protocols/ResponsesEndpointCombine.swift @@ -12,5 +12,7 @@ import Combine public protocol ResponsesEndpointCombine: Sendable { func createResponse(query: CreateModelResponseQuery) -> AnyPublisher func createResponseStreaming(query: CreateModelResponseQuery) -> AnyPublisher, Error> + func retrieveResponse(query: GetModelResponseQuery) -> AnyPublisher + func cancelResponse(query: CancelModelResponseQuery) -> AnyPublisher } #endif diff --git a/Sources/OpenAI/Public/Protocols/ResponsesEndpointProtocol.swift b/Sources/OpenAI/Public/Protocols/ResponsesEndpointProtocol.swift index 330cbb40..a6ffc098 100644 --- a/Sources/OpenAI/Public/Protocols/ResponsesEndpointProtocol.swift +++ b/Sources/OpenAI/Public/Protocols/ResponsesEndpointProtocol.swift @@ -18,4 +18,15 @@ public protocol ResponsesEndpointProtocol: ResponsesEndpointModern { onResult: @escaping @Sendable (Result) -> Void, completion: (@Sendable (Error?) -> Void)? ) -> CancellableRequest + + func retrieveResponse( + query: GetModelResponseQuery, + completion: @escaping @Sendable (Result) -> Void + ) -> CancellableRequest + + func cancelResponse( + query: CancelModelResponseQuery, + completion: @escaping @Sendable (Result) -> Void + ) -> CancellableRequest + } diff --git a/Sources/OpenAI/ResponsesEndpoint+Async.swift b/Sources/OpenAI/ResponsesEndpoint+Async.swift index bc025984..4ec61d3d 100644 --- a/Sources/OpenAI/ResponsesEndpoint+Async.swift +++ b/Sources/OpenAI/ResponsesEndpoint+Async.swift @@ -32,4 +32,12 @@ extension ResponsesEndpoint: ResponsesEndpointAsync { } } } + + public func retrieveResponse(query: GetModelResponseQuery) async throws -> ResponseObject { + try await asyncClient.performRequest(request: makeRetrieveResponseRequest(query: query)) + } + + public func cancelResponse(query: CancelModelResponseQuery) async throws -> ResponseObject { + try await asyncClient.performRequest(request: makeCancelResponseRequest(query: query)) + } } diff --git a/Sources/OpenAI/ResponsesEndpoint+Combine.swift b/Sources/OpenAI/ResponsesEndpoint+Combine.swift index fd1f0cdd..ac307e14 100644 --- a/Sources/OpenAI/ResponsesEndpoint+Combine.swift +++ b/Sources/OpenAI/ResponsesEndpoint+Combine.swift @@ -37,5 +37,13 @@ extension ResponsesEndpoint: ResponsesEndpointCombine { }) .eraseToAnyPublisher() } + + public func retrieveResponse(query: GetModelResponseQuery) -> AnyPublisher { + combineClient.performRequest(request: makeRetrieveResponseRequest(query: query)) + } + + public func cancelResponse(query: CancelModelResponseQuery) -> AnyPublisher { + combineClient.performRequest(request: makeCancelResponseRequest(query: query)) + } } #endif diff --git a/Sources/OpenAI/ResponsesEndpoint.swift b/Sources/OpenAI/ResponsesEndpoint.swift index 6628f45a..90ff1356 100644 --- a/Sources/OpenAI/ResponsesEndpoint.swift +++ b/Sources/OpenAI/ResponsesEndpoint.swift @@ -69,3 +69,33 @@ public final class ResponsesEndpoint: ResponsesEndpointProtocol, Sendable { .buildURL() } } + +// MARK: - Retrieve Response + +extension ResponsesEndpoint { + + public func retrieveResponse(query: GetModelResponseQuery, completion: @escaping @Sendable (Result) -> Void) -> any CancellableRequest { + client.performRequest(request: makeRetrieveResponseRequest(query: query), + completion: completion) + } + + func makeRetrieveResponseRequest(query: GetModelResponseQuery) -> JSONRequest { + let path = String.Responses.getModelResponse(responseId: query.responseId).stringValue + return .init(url: buildURL(path: path), method: "GET") + } +} + +// MARK: - Cancel Response + +extension ResponsesEndpoint { + + public func cancelResponse(query: CancelModelResponseQuery, completion: @escaping (Result) -> Void) -> any CancellableRequest { + client.performRequest(request: makeCancelResponseRequest(query: query), + completion: completion) + } + + func makeCancelResponseRequest(query: CancelModelResponseQuery) -> JSONRequest { + let path = String.Responses.cancelModelResponse(responseId: query.responseId).stringValue + return .init(body: query, url: buildURL(path: path)) + } +}