Merged
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
118 changes: 118 additions & 0 deletions Sources/OpenAI/Common/Content.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
//
// Content.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

public enum Content: Encodable, Sendable {
case inputText(TextInput)
case inputImage(ImageInput)
case inputFile(FileInput)

enum TypeCodingKeys: String, CodingKey {
case type
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()

switch self {
case .inputText(let textInput):
try container.encode(textInput)
case .inputImage(let imageInput):
try container.encode(imageInput)
case .inputFile(let fileInput):
try container.encode(fileInput)
}

}
}

/// A text input to the model.
public struct TextInput: Codable, Sendable {
/// The text input to the model.
public let text: String

/// The type of the input item. Always `input_text`.
public let type: ContentType

enum CodingKeys: CodingKey {
case text
case type
}

public init(text: String) {
self.text = text
self.type = .inputText
}
}

/// An image input to the model.
public struct ImageInput: Codable, Sendable {
/// The detail level of the image to be sent to the model.
///
/// One of `high`, `low`, or `auto`. Defaults to `auto`.
public let detail: ImageDetail

/// The type of the input item. Always `input_image`.
public let type: ContentType

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the image to be sent to the model.
///
/// A fully qualified URL or base64 encoded image in a data URL.
public let imageUrl: String?

public init(detail: ImageDetail = .auto, fileId: String? = nil, imageUrl: String? = nil) {
self.detail = detail
self.type = .inputImage
self.fileId = fileId
self.imageUrl = imageUrl
}
}

/// A file input to the model.
public struct FileInput: Codable, Sendable {
/// The type of the input item. Always `input_file`.
public let type: ContentType

/// The content of the file to be sent to the model.
public let fileData: String?

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the file to be sent to the model.
public let fileUrl: String?

/// The name of the file to be sent to the model.
public let filename: String?

public init(
fileData: String? = nil,
fileId: String? = nil,
fileUrl: String? = nil,
filename: String? = nil
) {
self.type = .inputFile
self.fileData = fileData
self.fileId = fileId
self.fileUrl = fileUrl
self.filename = filename
}
}

public enum ContentType: String, Codable, Sendable {
case inputText = "input_text"
case outputText = "output_text"
case inputFile = "input_file"
case inputImage = "input_image"
}


public enum ImageDetail: String, Codable, Sendable {
case auto, low, high
}
27 changes: 27 additions & 0 deletions Sources/OpenAI/Common/Prompt.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
//
// Prompt.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

// TODO: Implement file input https://platform.openai.com/docs/guides/text#reusable-prompts

public struct Prompt: Encodable, Sendable {
/// The unique identifier of the prompt template to use.
public let id: String

/// Optional map of values to substitute in for variables in your prompt.
///
/// The substitution values can either be strings, or other Response input types like images or files.
public let variables: [String: String]?

/// Optional version of the prompt template.
public let version: String?

public init(id: String, variables: [String: String]? = nil, version: String? = nil) {
self.id = id
self.variables = variables
self.version = version
}
}
78 changes: 78 additions & 0 deletions Sources/OpenAI/Model.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,86 @@
// Created by Firdavs Khaydarov on 01/08/2025.
//

/// Model type to define OpenAI models.
///
/// For more information about models and their capabilities visit https://platform.openai.com/docs/models
public typealias Model = String

// MARK: - o-series

extension Model {
/// o1 models think before they answer, producing a long internal chain of thought before responding to the user.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1: Model = "o1"

/// The o1-pro model uses more compute to think harder and provide consistently better answers.
///
/// o1-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1_pro: Model = "o1-pro"

/// o3 is a well-rounded and powerful model across domains.
///
/// Use it to think through multi-step problems that involve analysis across text, code, and images.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3: Model = "o3"

/// The o3-pro model uses more compute to think harder and provide consistently better answers.
///
/// o3-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
/// Since o3-pro is designed to tackle tough problems, some requests may take several minutes to
/// finish. To avoid timeouts, try using background mode.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_pro: Model = "o3-pro"

/// o3-mini is our newest small reasoning model, providing high intelligence at the same cost
/// and latency targets of o1-mini.
///
/// o3-mini supports key developer features, like Structured Outputs, function calling, and Batch API.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_mini: Model = "o3-mini"

/// o3-deep-research is the most advanced model for deep research, designed to tackle complex,
/// multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own data—brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_deep_research: Model = "o3-deep-research"

/// o4-mini is the latest small o-series model.
///
/// It's optimized for fast, effective reasoning with exceptionally efficient performance in
/// coding and visual tasks.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini: Model = "o4-mini"

/// o4-mini-deep-research is a faster, more affordable deep research model—ideal for tackling
/// complex, multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own
/// data, brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini_deep_research: Model = "o4-mini-deep-research"
}

// MARK: - GPT-5

extension Model {
Expand Down
19 changes: 14 additions & 5 deletions Sources/OpenAI/Responses/ResponsesBody.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,13 +8,13 @@
import Foundation

public extension Responses {
struct Body: Codable {
struct Body: Encodable {
/// Whether to run the model response in the background.
public var background: Bool?
/// Specify additional output data to include in the model response.
public var include: [AdditionalOutput]?
///
public var input: String?
/// Text, image, or file inputs to the model, used to generate a response.
public var input: [Input]?
/// A system (or developer) message inserted into the model's context.
///
/// When using along with `previous_response_id`, the instructions from a previous response
Expand DownExpand Up@@ -45,8 +45,8 @@ public extension Responses {
public var parallelToolCalls: Bool?
/// The unique ID of the previous response to the model. Use this to create multi-turn conversations.
public var previousResponseId: String?
///
public var prompt: String?
/// Reference to a prompt template and its variables.
public var prompt: Prompt?
/// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
public var promptCacheKey: String?
///
Expand DownExpand Up@@ -122,5 +122,14 @@ public extension Responses {
/// an organization is enrolled in the zero data retention program).
case reasoningEncryptedContent = "reasoning.encrypted_content"
}

public struct Input: Encodable, Sendable {
/// The role of the message input. One of `user`, `assistant`, `system`, or `developer`.
public let role: Role

/// Text, image, or audio input to the model, used to generate a response. Can also contain
/// previous assistant responses.
public let content: [Content]
}
}
}
8 changes: 4 additions & 4 deletions Sources/OpenAI/Responses/ResponsesWrapper.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,15 +12,15 @@ public struct ResponsesWrapper {
public func create(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand DownExpand Up@@ -65,15 +65,15 @@ public struct ResponsesWrapper {
public func createStream(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
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
118 changes: 118 additions & 0 deletions Sources/OpenAI/Common/Content.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
//
// Content.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

public enum Content: Encodable, Sendable {
case inputText(TextInput)
case inputImage(ImageInput)
case inputFile(FileInput)

enum TypeCodingKeys: String, CodingKey {
case type
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()

switch self {
case .inputText(let textInput):
try container.encode(textInput)
case .inputImage(let imageInput):
try container.encode(imageInput)
case .inputFile(let fileInput):
try container.encode(fileInput)
}

}
}

/// A text input to the model.
public struct TextInput: Codable, Sendable {
/// The text input to the model.
public let text: String

/// The type of the input item. Always `input_text`.
public let type: ContentType

enum CodingKeys: CodingKey {
case text
case type
}

public init(text: String) {
self.text = text
self.type = .inputText
}
}

/// An image input to the model.
public struct ImageInput: Codable, Sendable {
/// The detail level of the image to be sent to the model.
///
/// One of `high`, `low`, or `auto`. Defaults to `auto`.
public let detail: ImageDetail

/// The type of the input item. Always `input_image`.
public let type: ContentType

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the image to be sent to the model.
///
/// A fully qualified URL or base64 encoded image in a data URL.
public let imageUrl: String?

public init(detail: ImageDetail = .auto, fileId: String? = nil, imageUrl: String? = nil) {
self.detail = detail
self.type = .inputImage
self.fileId = fileId
self.imageUrl = imageUrl
}
}

/// A file input to the model.
public struct FileInput: Codable, Sendable {
/// The type of the input item. Always `input_file`.
public let type: ContentType

/// The content of the file to be sent to the model.
public let fileData: String?

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the file to be sent to the model.
public let fileUrl: String?

/// The name of the file to be sent to the model.
public let filename: String?

public init(
fileData: String? = nil,
fileId: String? = nil,
fileUrl: String? = nil,
filename: String? = nil
) {
self.type = .inputFile
self.fileData = fileData
self.fileId = fileId
self.fileUrl = fileUrl
self.filename = filename
}
}

public enum ContentType: String, Codable, Sendable {
case inputText = "input_text"
case outputText = "output_text"
case inputFile = "input_file"
case inputImage = "input_image"
}


public enum ImageDetail: String, Codable, Sendable {
case auto, low, high
}
27 changes: 27 additions & 0 deletions Sources/OpenAI/Common/Prompt.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
//
// Prompt.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

// TODO: Implement file input https://platform.openai.com/docs/guides/text#reusable-prompts

public struct Prompt: Encodable, Sendable {
/// The unique identifier of the prompt template to use.
public let id: String

/// Optional map of values to substitute in for variables in your prompt.
///
/// The substitution values can either be strings, or other Response input types like images or files.
public let variables: [String: String]?

/// Optional version of the prompt template.
public let version: String?

public init(id: String, variables: [String: String]? = nil, version: String? = nil) {
self.id = id
self.variables = variables
self.version = version
}
}
78 changes: 78 additions & 0 deletions Sources/OpenAI/Model.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,86 @@
// Created by Firdavs Khaydarov on 01/08/2025.
//

/// Model type to define OpenAI models.
///
/// For more information about models and their capabilities visit https://platform.openai.com/docs/models
public typealias Model = String

// MARK: - o-series

extension Model {
/// o1 models think before they answer, producing a long internal chain of thought before responding to the user.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1: Model = "o1"

/// The o1-pro model uses more compute to think harder and provide consistently better answers.
///
/// o1-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1_pro: Model = "o1-pro"

/// o3 is a well-rounded and powerful model across domains.
///
/// Use it to think through multi-step problems that involve analysis across text, code, and images.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3: Model = "o3"

/// The o3-pro model uses more compute to think harder and provide consistently better answers.
///
/// o3-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
/// Since o3-pro is designed to tackle tough problems, some requests may take several minutes to
/// finish. To avoid timeouts, try using background mode.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_pro: Model = "o3-pro"

/// o3-mini is our newest small reasoning model, providing high intelligence at the same cost
/// and latency targets of o1-mini.
///
/// o3-mini supports key developer features, like Structured Outputs, function calling, and Batch API.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_mini: Model = "o3-mini"

/// o3-deep-research is the most advanced model for deep research, designed to tackle complex,
/// multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own data—brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_deep_research: Model = "o3-deep-research"

/// o4-mini is the latest small o-series model.
///
/// It's optimized for fast, effective reasoning with exceptionally efficient performance in
/// coding and visual tasks.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini: Model = "o4-mini"

/// o4-mini-deep-research is a faster, more affordable deep research model—ideal for tackling
/// complex, multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own
/// data, brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini_deep_research: Model = "o4-mini-deep-research"
}

// MARK: - GPT-5

extension Model {
Expand Down
19 changes: 14 additions & 5 deletions Sources/OpenAI/Responses/ResponsesBody.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,13 +8,13 @@
import Foundation

public extension Responses {
struct Body: Codable {
struct Body: Encodable {
/// Whether to run the model response in the background.
public var background: Bool?
/// Specify additional output data to include in the model response.
public var include: [AdditionalOutput]?
///
public var input: String?
/// Text, image, or file inputs to the model, used to generate a response.
public var input: [Input]?
/// A system (or developer) message inserted into the model's context.
///
/// When using along with `previous_response_id`, the instructions from a previous response
Expand DownExpand Up@@ -45,8 +45,8 @@ public extension Responses {
public var parallelToolCalls: Bool?
/// The unique ID of the previous response to the model. Use this to create multi-turn conversations.
public var previousResponseId: String?
///
public var prompt: String?
/// Reference to a prompt template and its variables.
public var prompt: Prompt?
/// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
public var promptCacheKey: String?
///
Expand DownExpand Up@@ -122,5 +122,14 @@ public extension Responses {
/// an organization is enrolled in the zero data retention program).
case reasoningEncryptedContent = "reasoning.encrypted_content"
}

public struct Input: Encodable, Sendable {
/// The role of the message input. One of `user`, `assistant`, `system`, or `developer`.
public let role: Role

/// Text, image, or audio input to the model, used to generate a response. Can also contain
/// previous assistant responses.
public let content: [Content]
}
}
}
8 changes: 4 additions & 4 deletions Sources/OpenAI/Responses/ResponsesWrapper.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,15 +12,15 @@ public struct ResponsesWrapper {
public func create(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand DownExpand Up@@ -65,15 +65,15 @@ public struct ResponsesWrapper {
public func createStream(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
118 changes: 118 additions & 0 deletions Sources/OpenAI/Common/Content.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
//
// Content.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

public enum Content: Encodable, Sendable {
case inputText(TextInput)
case inputImage(ImageInput)
case inputFile(FileInput)

enum TypeCodingKeys: String, CodingKey {
case type
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()

switch self {
case .inputText(let textInput):
try container.encode(textInput)
case .inputImage(let imageInput):
try container.encode(imageInput)
case .inputFile(let fileInput):
try container.encode(fileInput)
}

}
}

/// A text input to the model.
public struct TextInput: Codable, Sendable {
/// The text input to the model.
public let text: String

/// The type of the input item. Always `input_text`.
public let type: ContentType

enum CodingKeys: CodingKey {
case text
case type
}

public init(text: String) {
self.text = text
self.type = .inputText
}
}

/// An image input to the model.
public struct ImageInput: Codable, Sendable {
/// The detail level of the image to be sent to the model.
///
/// One of `high`, `low`, or `auto`. Defaults to `auto`.
public let detail: ImageDetail

/// The type of the input item. Always `input_image`.
public let type: ContentType

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the image to be sent to the model.
///
/// A fully qualified URL or base64 encoded image in a data URL.
public let imageUrl: String?

public init(detail: ImageDetail = .auto, fileId: String? = nil, imageUrl: String? = nil) {
self.detail = detail
self.type = .inputImage
self.fileId = fileId
self.imageUrl = imageUrl
}
}

/// A file input to the model.
public struct FileInput: Codable, Sendable {
/// The type of the input item. Always `input_file`.
public let type: ContentType

/// The content of the file to be sent to the model.
public let fileData: String?

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the file to be sent to the model.
public let fileUrl: String?

/// The name of the file to be sent to the model.
public let filename: String?

public init(
fileData: String? = nil,
fileId: String? = nil,
fileUrl: String? = nil,
filename: String? = nil
) {
self.type = .inputFile
self.fileData = fileData
self.fileId = fileId
self.fileUrl = fileUrl
self.filename = filename
}
}

public enum ContentType: String, Codable, Sendable {
case inputText = "input_text"
case outputText = "output_text"
case inputFile = "input_file"
case inputImage = "input_image"
}


public enum ImageDetail: String, Codable, Sendable {
case auto, low, high
}
27 changes: 27 additions & 0 deletions Sources/OpenAI/Common/Prompt.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
//
// Prompt.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

// TODO: Implement file input https://platform.openai.com/docs/guides/text#reusable-prompts

public struct Prompt: Encodable, Sendable {
/// The unique identifier of the prompt template to use.
public let id: String

/// Optional map of values to substitute in for variables in your prompt.
///
/// The substitution values can either be strings, or other Response input types like images or files.
public let variables: [String: String]?

/// Optional version of the prompt template.
public let version: String?

public init(id: String, variables: [String: String]? = nil, version: String? = nil) {
self.id = id
self.variables = variables
self.version = version
}
}
78 changes: 78 additions & 0 deletions Sources/OpenAI/Model.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,86 @@
// Created by Firdavs Khaydarov on 01/08/2025.
//

/// Model type to define OpenAI models.
///
/// For more information about models and their capabilities visit https://platform.openai.com/docs/models
public typealias Model = String

// MARK: - o-series

extension Model {
/// o1 models think before they answer, producing a long internal chain of thought before responding to the user.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1: Model = "o1"

/// The o1-pro model uses more compute to think harder and provide consistently better answers.
///
/// o1-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1_pro: Model = "o1-pro"

/// o3 is a well-rounded and powerful model across domains.
///
/// Use it to think through multi-step problems that involve analysis across text, code, and images.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3: Model = "o3"

/// The o3-pro model uses more compute to think harder and provide consistently better answers.
///
/// o3-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
/// Since o3-pro is designed to tackle tough problems, some requests may take several minutes to
/// finish. To avoid timeouts, try using background mode.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_pro: Model = "o3-pro"

/// o3-mini is our newest small reasoning model, providing high intelligence at the same cost
/// and latency targets of o1-mini.
///
/// o3-mini supports key developer features, like Structured Outputs, function calling, and Batch API.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_mini: Model = "o3-mini"

/// o3-deep-research is the most advanced model for deep research, designed to tackle complex,
/// multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own data—brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_deep_research: Model = "o3-deep-research"

/// o4-mini is the latest small o-series model.
///
/// It's optimized for fast, effective reasoning with exceptionally efficient performance in
/// coding and visual tasks.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini: Model = "o4-mini"

/// o4-mini-deep-research is a faster, more affordable deep research model—ideal for tackling
/// complex, multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own
/// data, brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini_deep_research: Model = "o4-mini-deep-research"
}

// MARK: - GPT-5

extension Model {
Expand Down
19 changes: 14 additions & 5 deletions Sources/OpenAI/Responses/ResponsesBody.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,13 +8,13 @@
import Foundation

public extension Responses {
struct Body: Codable {
struct Body: Encodable {
/// Whether to run the model response in the background.
public var background: Bool?
/// Specify additional output data to include in the model response.
public var include: [AdditionalOutput]?
///
public var input: String?
/// Text, image, or file inputs to the model, used to generate a response.
public var input: [Input]?
/// A system (or developer) message inserted into the model's context.
///
/// When using along with `previous_response_id`, the instructions from a previous response
Expand DownExpand Up@@ -45,8 +45,8 @@ public extension Responses {
public var parallelToolCalls: Bool?
/// The unique ID of the previous response to the model. Use this to create multi-turn conversations.
public var previousResponseId: String?
///
public var prompt: String?
/// Reference to a prompt template and its variables.
public var prompt: Prompt?
/// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
public var promptCacheKey: String?
///
Expand DownExpand Up@@ -122,5 +122,14 @@ public extension Responses {
/// an organization is enrolled in the zero data retention program).
case reasoningEncryptedContent = "reasoning.encrypted_content"
}

public struct Input: Encodable, Sendable {
/// The role of the message input. One of `user`, `assistant`, `system`, or `developer`.
public let role: Role

/// Text, image, or audio input to the model, used to generate a response. Can also contain
/// previous assistant responses.
public let content: [Content]
}
}
}
8 changes: 4 additions & 4 deletions Sources/OpenAI/Responses/ResponsesWrapper.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,15 +12,15 @@ public struct ResponsesWrapper {
public func create(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand DownExpand Up@@ -65,15 +65,15 @@ public struct ResponsesWrapper {
public func createStream(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
118 changes: 118 additions & 0 deletions Sources/OpenAI/Common/Content.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
//
// Content.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

public enum Content: Encodable, Sendable {
case inputText(TextInput)
case inputImage(ImageInput)
case inputFile(FileInput)

enum TypeCodingKeys: String, CodingKey {
case type
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()

switch self {
case .inputText(let textInput):
try container.encode(textInput)
case .inputImage(let imageInput):
try container.encode(imageInput)
case .inputFile(let fileInput):
try container.encode(fileInput)
}

}
}

/// A text input to the model.
public struct TextInput: Codable, Sendable {
/// The text input to the model.
public let text: String

/// The type of the input item. Always `input_text`.
public let type: ContentType

enum CodingKeys: CodingKey {
case text
case type
}

public init(text: String) {
self.text = text
self.type = .inputText
}
}

/// An image input to the model.
public struct ImageInput: Codable, Sendable {
/// The detail level of the image to be sent to the model.
///
/// One of `high`, `low`, or `auto`. Defaults to `auto`.
public let detail: ImageDetail

/// The type of the input item. Always `input_image`.
public let type: ContentType

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the image to be sent to the model.
///
/// A fully qualified URL or base64 encoded image in a data URL.
public let imageUrl: String?

public init(detail: ImageDetail = .auto, fileId: String? = nil, imageUrl: String? = nil) {
self.detail = detail
self.type = .inputImage
self.fileId = fileId
self.imageUrl = imageUrl
}
}

/// A file input to the model.
public struct FileInput: Codable, Sendable {
/// The type of the input item. Always `input_file`.
public let type: ContentType

/// The content of the file to be sent to the model.
public let fileData: String?

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the file to be sent to the model.
public let fileUrl: String?

/// The name of the file to be sent to the model.
public let filename: String?

public init(
fileData: String? = nil,
fileId: String? = nil,
fileUrl: String? = nil,
filename: String? = nil
) {
self.type = .inputFile
self.fileData = fileData
self.fileId = fileId
self.fileUrl = fileUrl
self.filename = filename
}
}

public enum ContentType: String, Codable, Sendable {
case inputText = "input_text"
case outputText = "output_text"
case inputFile = "input_file"
case inputImage = "input_image"
}


public enum ImageDetail: String, Codable, Sendable {
case auto, low, high
}
27 changes: 27 additions & 0 deletions Sources/OpenAI/Common/Prompt.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
//
// Prompt.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

// TODO: Implement file input https://platform.openai.com/docs/guides/text#reusable-prompts

public struct Prompt: Encodable, Sendable {
/// The unique identifier of the prompt template to use.
public let id: String

/// Optional map of values to substitute in for variables in your prompt.
///
/// The substitution values can either be strings, or other Response input types like images or files.
public let variables: [String: String]?

/// Optional version of the prompt template.
public let version: String?

public init(id: String, variables: [String: String]? = nil, version: String? = nil) {
self.id = id
self.variables = variables
self.version = version
}
}
78 changes: 78 additions & 0 deletions Sources/OpenAI/Model.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,86 @@
// Created by Firdavs Khaydarov on 01/08/2025.
//

/// Model type to define OpenAI models.
///
/// For more information about models and their capabilities visit https://platform.openai.com/docs/models
public typealias Model = String

// MARK: - o-series

extension Model {
/// o1 models think before they answer, producing a long internal chain of thought before responding to the user.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1: Model = "o1"

/// The o1-pro model uses more compute to think harder and provide consistently better answers.
///
/// o1-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1_pro: Model = "o1-pro"

/// o3 is a well-rounded and powerful model across domains.
///
/// Use it to think through multi-step problems that involve analysis across text, code, and images.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3: Model = "o3"

/// The o3-pro model uses more compute to think harder and provide consistently better answers.
///
/// o3-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
/// Since o3-pro is designed to tackle tough problems, some requests may take several minutes to
/// finish. To avoid timeouts, try using background mode.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_pro: Model = "o3-pro"

/// o3-mini is our newest small reasoning model, providing high intelligence at the same cost
/// and latency targets of o1-mini.
///
/// o3-mini supports key developer features, like Structured Outputs, function calling, and Batch API.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_mini: Model = "o3-mini"

/// o3-deep-research is the most advanced model for deep research, designed to tackle complex,
/// multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own data—brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_deep_research: Model = "o3-deep-research"

/// o4-mini is the latest small o-series model.
///
/// It's optimized for fast, effective reasoning with exceptionally efficient performance in
/// coding and visual tasks.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini: Model = "o4-mini"

/// o4-mini-deep-research is a faster, more affordable deep research model—ideal for tackling
/// complex, multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own
/// data, brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini_deep_research: Model = "o4-mini-deep-research"
}

// MARK: - GPT-5

extension Model {
Expand Down
19 changes: 14 additions & 5 deletions Sources/OpenAI/Responses/ResponsesBody.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,13 +8,13 @@
import Foundation

public extension Responses {
struct Body: Codable {
struct Body: Encodable {
/// Whether to run the model response in the background.
public var background: Bool?
/// Specify additional output data to include in the model response.
public var include: [AdditionalOutput]?
///
public var input: String?
/// Text, image, or file inputs to the model, used to generate a response.
public var input: [Input]?
/// A system (or developer) message inserted into the model's context.
///
/// When using along with `previous_response_id`, the instructions from a previous response
Expand DownExpand Up@@ -45,8 +45,8 @@ public extension Responses {
public var parallelToolCalls: Bool?
/// The unique ID of the previous response to the model. Use this to create multi-turn conversations.
public var previousResponseId: String?
///
public var prompt: String?
/// Reference to a prompt template and its variables.
public var prompt: Prompt?
/// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
public var promptCacheKey: String?
///
Expand DownExpand Up@@ -122,5 +122,14 @@ public extension Responses {
/// an organization is enrolled in the zero data retention program).
case reasoningEncryptedContent = "reasoning.encrypted_content"
}

public struct Input: Encodable, Sendable {
/// The role of the message input. One of `user`, `assistant`, `system`, or `developer`.
public let role: Role

/// Text, image, or audio input to the model, used to generate a response. Can also contain
/// previous assistant responses.
public let content: [Content]
}
}
}
8 changes: 4 additions & 4 deletions Sources/OpenAI/Responses/ResponsesWrapper.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,15 +12,15 @@ public struct ResponsesWrapper {
public func create(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand DownExpand Up@@ -65,15 +65,15 @@ public struct ResponsesWrapper {
public func createStream(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
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
118 changes: 118 additions & 0 deletions Sources/OpenAI/Common/Content.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
//
// Content.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

public enum Content: Encodable, Sendable {
case inputText(TextInput)
case inputImage(ImageInput)
case inputFile(FileInput)

enum TypeCodingKeys: String, CodingKey {
case type
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()

switch self {
case .inputText(let textInput):
try container.encode(textInput)
case .inputImage(let imageInput):
try container.encode(imageInput)
case .inputFile(let fileInput):
try container.encode(fileInput)
}

}
}

/// A text input to the model.
public struct TextInput: Codable, Sendable {
/// The text input to the model.
public let text: String

/// The type of the input item. Always `input_text`.
public let type: ContentType

enum CodingKeys: CodingKey {
case text
case type
}

public init(text: String) {
self.text = text
self.type = .inputText
}
}

/// An image input to the model.
public struct ImageInput: Codable, Sendable {
/// The detail level of the image to be sent to the model.
///
/// One of `high`, `low`, or `auto`. Defaults to `auto`.
public let detail: ImageDetail

/// The type of the input item. Always `input_image`.
public let type: ContentType

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the image to be sent to the model.
///
/// A fully qualified URL or base64 encoded image in a data URL.
public let imageUrl: String?

public init(detail: ImageDetail = .auto, fileId: String? = nil, imageUrl: String? = nil) {
self.detail = detail
self.type = .inputImage
self.fileId = fileId
self.imageUrl = imageUrl
}
}

/// A file input to the model.
public struct FileInput: Codable, Sendable {
/// The type of the input item. Always `input_file`.
public let type: ContentType

/// The content of the file to be sent to the model.
public let fileData: String?

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the file to be sent to the model.
public let fileUrl: String?

/// The name of the file to be sent to the model.
public let filename: String?

public init(
fileData: String? = nil,
fileId: String? = nil,
fileUrl: String? = nil,
filename: String? = nil
) {
self.type = .inputFile
self.fileData = fileData
self.fileId = fileId
self.fileUrl = fileUrl
self.filename = filename
}
}

public enum ContentType: String, Codable, Sendable {
case inputText = "input_text"
case outputText = "output_text"
case inputFile = "input_file"
case inputImage = "input_image"
}


public enum ImageDetail: String, Codable, Sendable {
case auto, low, high
}
27 changes: 27 additions & 0 deletions Sources/OpenAI/Common/Prompt.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
//
// Prompt.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

// TODO: Implement file input https://platform.openai.com/docs/guides/text#reusable-prompts

public struct Prompt: Encodable, Sendable {
/// The unique identifier of the prompt template to use.
public let id: String

/// Optional map of values to substitute in for variables in your prompt.
///
/// The substitution values can either be strings, or other Response input types like images or files.
public let variables: [String: String]?

/// Optional version of the prompt template.
public let version: String?

public init(id: String, variables: [String: String]? = nil, version: String? = nil) {
self.id = id
self.variables = variables
self.version = version
}
}
78 changes: 78 additions & 0 deletions Sources/OpenAI/Model.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,86 @@
// Created by Firdavs Khaydarov on 01/08/2025.
//

/// Model type to define OpenAI models.
///
/// For more information about models and their capabilities visit https://platform.openai.com/docs/models
public typealias Model = String

// MARK: - o-series

extension Model {
/// o1 models think before they answer, producing a long internal chain of thought before responding to the user.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1: Model = "o1"

/// The o1-pro model uses more compute to think harder and provide consistently better answers.
///
/// o1-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1_pro: Model = "o1-pro"

/// o3 is a well-rounded and powerful model across domains.
///
/// Use it to think through multi-step problems that involve analysis across text, code, and images.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3: Model = "o3"

/// The o3-pro model uses more compute to think harder and provide consistently better answers.
///
/// o3-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
/// Since o3-pro is designed to tackle tough problems, some requests may take several minutes to
/// finish. To avoid timeouts, try using background mode.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_pro: Model = "o3-pro"

/// o3-mini is our newest small reasoning model, providing high intelligence at the same cost
/// and latency targets of o1-mini.
///
/// o3-mini supports key developer features, like Structured Outputs, function calling, and Batch API.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_mini: Model = "o3-mini"

/// o3-deep-research is the most advanced model for deep research, designed to tackle complex,
/// multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own data—brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_deep_research: Model = "o3-deep-research"

/// o4-mini is the latest small o-series model.
///
/// It's optimized for fast, effective reasoning with exceptionally efficient performance in
/// coding and visual tasks.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini: Model = "o4-mini"

/// o4-mini-deep-research is a faster, more affordable deep research model—ideal for tackling
/// complex, multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own
/// data, brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini_deep_research: Model = "o4-mini-deep-research"
}

// MARK: - GPT-5

extension Model {
Expand Down
19 changes: 14 additions & 5 deletions Sources/OpenAI/Responses/ResponsesBody.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,13 +8,13 @@
import Foundation

public extension Responses {
struct Body: Codable {
struct Body: Encodable {
/// Whether to run the model response in the background.
public var background: Bool?
/// Specify additional output data to include in the model response.
public var include: [AdditionalOutput]?
///
public var input: String?
/// Text, image, or file inputs to the model, used to generate a response.
public var input: [Input]?
/// A system (or developer) message inserted into the model's context.
///
/// When using along with `previous_response_id`, the instructions from a previous response
Expand DownExpand Up@@ -45,8 +45,8 @@ public extension Responses {
public var parallelToolCalls: Bool?
/// The unique ID of the previous response to the model. Use this to create multi-turn conversations.
public var previousResponseId: String?
///
public var prompt: String?
/// Reference to a prompt template and its variables.
public var prompt: Prompt?
/// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
public var promptCacheKey: String?
///
Expand DownExpand Up@@ -122,5 +122,14 @@ public extension Responses {
/// an organization is enrolled in the zero data retention program).
case reasoningEncryptedContent = "reasoning.encrypted_content"
}

public struct Input: Encodable, Sendable {
/// The role of the message input. One of `user`, `assistant`, `system`, or `developer`.
public let role: Role

/// Text, image, or audio input to the model, used to generate a response. Can also contain
/// previous assistant responses.
public let content: [Content]
}
}
}
8 changes: 4 additions & 4 deletions Sources/OpenAI/Responses/ResponsesWrapper.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,15 +12,15 @@ public struct ResponsesWrapper {
public func create(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand DownExpand Up@@ -65,15 +65,15 @@ public struct ResponsesWrapper {
public func createStream(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
118 changes: 118 additions & 0 deletions Sources/OpenAI/Common/Content.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
//
// Content.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

public enum Content: Encodable, Sendable {
case inputText(TextInput)
case inputImage(ImageInput)
case inputFile(FileInput)

enum TypeCodingKeys: String, CodingKey {
case type
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()

switch self {
case .inputText(let textInput):
try container.encode(textInput)
case .inputImage(let imageInput):
try container.encode(imageInput)
case .inputFile(let fileInput):
try container.encode(fileInput)
}

}
}

/// A text input to the model.
public struct TextInput: Codable, Sendable {
/// The text input to the model.
public let text: String

/// The type of the input item. Always `input_text`.
public let type: ContentType

enum CodingKeys: CodingKey {
case text
case type
}

public init(text: String) {
self.text = text
self.type = .inputText
}
}

/// An image input to the model.
public struct ImageInput: Codable, Sendable {
/// The detail level of the image to be sent to the model.
///
/// One of `high`, `low`, or `auto`. Defaults to `auto`.
public let detail: ImageDetail

/// The type of the input item. Always `input_image`.
public let type: ContentType

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the image to be sent to the model.
///
/// A fully qualified URL or base64 encoded image in a data URL.
public let imageUrl: String?

public init(detail: ImageDetail = .auto, fileId: String? = nil, imageUrl: String? = nil) {
self.detail = detail
self.type = .inputImage
self.fileId = fileId
self.imageUrl = imageUrl
}
}

/// A file input to the model.
public struct FileInput: Codable, Sendable {
/// The type of the input item. Always `input_file`.
public let type: ContentType

/// The content of the file to be sent to the model.
public let fileData: String?

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the file to be sent to the model.
public let fileUrl: String?

/// The name of the file to be sent to the model.
public let filename: String?

public init(
fileData: String? = nil,
fileId: String? = nil,
fileUrl: String? = nil,
filename: String? = nil
) {
self.type = .inputFile
self.fileData = fileData
self.fileId = fileId
self.fileUrl = fileUrl
self.filename = filename
}
}

public enum ContentType: String, Codable, Sendable {
case inputText = "input_text"
case outputText = "output_text"
case inputFile = "input_file"
case inputImage = "input_image"
}


public enum ImageDetail: String, Codable, Sendable {
case auto, low, high
}
27 changes: 27 additions & 0 deletions Sources/OpenAI/Common/Prompt.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
//
// Prompt.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

// TODO: Implement file input https://platform.openai.com/docs/guides/text#reusable-prompts

public struct Prompt: Encodable, Sendable {
/// The unique identifier of the prompt template to use.
public let id: String

/// Optional map of values to substitute in for variables in your prompt.
///
/// The substitution values can either be strings, or other Response input types like images or files.
public let variables: [String: String]?

/// Optional version of the prompt template.
public let version: String?

public init(id: String, variables: [String: String]? = nil, version: String? = nil) {
self.id = id
self.variables = variables
self.version = version
}
}
78 changes: 78 additions & 0 deletions Sources/OpenAI/Model.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,86 @@
// Created by Firdavs Khaydarov on 01/08/2025.
//

/// Model type to define OpenAI models.
///
/// For more information about models and their capabilities visit https://platform.openai.com/docs/models
public typealias Model = String

// MARK: - o-series

extension Model {
/// o1 models think before they answer, producing a long internal chain of thought before responding to the user.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1: Model = "o1"

/// The o1-pro model uses more compute to think harder and provide consistently better answers.
///
/// o1-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1_pro: Model = "o1-pro"

/// o3 is a well-rounded and powerful model across domains.
///
/// Use it to think through multi-step problems that involve analysis across text, code, and images.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3: Model = "o3"

/// The o3-pro model uses more compute to think harder and provide consistently better answers.
///
/// o3-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
/// Since o3-pro is designed to tackle tough problems, some requests may take several minutes to
/// finish. To avoid timeouts, try using background mode.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_pro: Model = "o3-pro"

/// o3-mini is our newest small reasoning model, providing high intelligence at the same cost
/// and latency targets of o1-mini.
///
/// o3-mini supports key developer features, like Structured Outputs, function calling, and Batch API.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_mini: Model = "o3-mini"

/// o3-deep-research is the most advanced model for deep research, designed to tackle complex,
/// multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own data—brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_deep_research: Model = "o3-deep-research"

/// o4-mini is the latest small o-series model.
///
/// It's optimized for fast, effective reasoning with exceptionally efficient performance in
/// coding and visual tasks.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini: Model = "o4-mini"

/// o4-mini-deep-research is a faster, more affordable deep research model—ideal for tackling
/// complex, multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own
/// data, brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini_deep_research: Model = "o4-mini-deep-research"
}

// MARK: - GPT-5

extension Model {
Expand Down
19 changes: 14 additions & 5 deletions Sources/OpenAI/Responses/ResponsesBody.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,13 +8,13 @@
import Foundation

public extension Responses {
struct Body: Codable {
struct Body: Encodable {
/// Whether to run the model response in the background.
public var background: Bool?
/// Specify additional output data to include in the model response.
public var include: [AdditionalOutput]?
///
public var input: String?
/// Text, image, or file inputs to the model, used to generate a response.
public var input: [Input]?
/// A system (or developer) message inserted into the model's context.
///
/// When using along with `previous_response_id`, the instructions from a previous response
Expand DownExpand Up@@ -45,8 +45,8 @@ public extension Responses {
public var parallelToolCalls: Bool?
/// The unique ID of the previous response to the model. Use this to create multi-turn conversations.
public var previousResponseId: String?
///
public var prompt: String?
/// Reference to a prompt template and its variables.
public var prompt: Prompt?
/// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
public var promptCacheKey: String?
///
Expand DownExpand Up@@ -122,5 +122,14 @@ public extension Responses {
/// an organization is enrolled in the zero data retention program).
case reasoningEncryptedContent = "reasoning.encrypted_content"
}

public struct Input: Encodable, Sendable {
/// The role of the message input. One of `user`, `assistant`, `system`, or `developer`.
public let role: Role

/// Text, image, or audio input to the model, used to generate a response. Can also contain
/// previous assistant responses.
public let content: [Content]
}
}
}
8 changes: 4 additions & 4 deletions Sources/OpenAI/Responses/ResponsesWrapper.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,15 +12,15 @@ public struct ResponsesWrapper {
public func create(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand DownExpand Up@@ -65,15 +65,15 @@ public struct ResponsesWrapper {
public func createStream(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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
118 changes: 118 additions & 0 deletions Sources/OpenAI/Common/Content.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
//
// Content.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

public enum Content: Encodable, Sendable {
case inputText(TextInput)
case inputImage(ImageInput)
case inputFile(FileInput)

enum TypeCodingKeys: String, CodingKey {
case type
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()

switch self {
case .inputText(let textInput):
try container.encode(textInput)
case .inputImage(let imageInput):
try container.encode(imageInput)
case .inputFile(let fileInput):
try container.encode(fileInput)
}

}
}

/// A text input to the model.
public struct TextInput: Codable, Sendable {
/// The text input to the model.
public let text: String

/// The type of the input item. Always `input_text`.
public let type: ContentType

enum CodingKeys: CodingKey {
case text
case type
}

public init(text: String) {
self.text = text
self.type = .inputText
}
}

/// An image input to the model.
public struct ImageInput: Codable, Sendable {
/// The detail level of the image to be sent to the model.
///
/// One of `high`, `low`, or `auto`. Defaults to `auto`.
public let detail: ImageDetail

/// The type of the input item. Always `input_image`.
public let type: ContentType

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the image to be sent to the model.
///
/// A fully qualified URL or base64 encoded image in a data URL.
public let imageUrl: String?

public init(detail: ImageDetail = .auto, fileId: String? = nil, imageUrl: String? = nil) {
self.detail = detail
self.type = .inputImage
self.fileId = fileId
self.imageUrl = imageUrl
}
}

/// A file input to the model.
public struct FileInput: Codable, Sendable {
/// The type of the input item. Always `input_file`.
public let type: ContentType

/// The content of the file to be sent to the model.
public let fileData: String?

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the file to be sent to the model.
public let fileUrl: String?

/// The name of the file to be sent to the model.
public let filename: String?

public init(
fileData: String? = nil,
fileId: String? = nil,
fileUrl: String? = nil,
filename: String? = nil
) {
self.type = .inputFile
self.fileData = fileData
self.fileId = fileId
self.fileUrl = fileUrl
self.filename = filename
}
}

public enum ContentType: String, Codable, Sendable {
case inputText = "input_text"
case outputText = "output_text"
case inputFile = "input_file"
case inputImage = "input_image"
}


public enum ImageDetail: String, Codable, Sendable {
case auto, low, high
}
27 changes: 27 additions & 0 deletions Sources/OpenAI/Common/Prompt.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
//
// Prompt.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

// TODO: Implement file input https://platform.openai.com/docs/guides/text#reusable-prompts

public struct Prompt: Encodable, Sendable {
/// The unique identifier of the prompt template to use.
public let id: String

/// Optional map of values to substitute in for variables in your prompt.
///
/// The substitution values can either be strings, or other Response input types like images or files.
public let variables: [String: String]?

/// Optional version of the prompt template.
public let version: String?

public init(id: String, variables: [String: String]? = nil, version: String? = nil) {
self.id = id
self.variables = variables
self.version = version
}
}
78 changes: 78 additions & 0 deletions Sources/OpenAI/Model.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,86 @@
// Created by Firdavs Khaydarov on 01/08/2025.
//

/// Model type to define OpenAI models.
///
/// For more information about models and their capabilities visit https://platform.openai.com/docs/models
public typealias Model = String

// MARK: - o-series

extension Model {
/// o1 models think before they answer, producing a long internal chain of thought before responding to the user.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1: Model = "o1"

/// The o1-pro model uses more compute to think harder and provide consistently better answers.
///
/// o1-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1_pro: Model = "o1-pro"

/// o3 is a well-rounded and powerful model across domains.
///
/// Use it to think through multi-step problems that involve analysis across text, code, and images.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3: Model = "o3"

/// The o3-pro model uses more compute to think harder and provide consistently better answers.
///
/// o3-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
/// Since o3-pro is designed to tackle tough problems, some requests may take several minutes to
/// finish. To avoid timeouts, try using background mode.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_pro: Model = "o3-pro"

/// o3-mini is our newest small reasoning model, providing high intelligence at the same cost
/// and latency targets of o1-mini.
///
/// o3-mini supports key developer features, like Structured Outputs, function calling, and Batch API.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_mini: Model = "o3-mini"

/// o3-deep-research is the most advanced model for deep research, designed to tackle complex,
/// multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own data—brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_deep_research: Model = "o3-deep-research"

/// o4-mini is the latest small o-series model.
///
/// It's optimized for fast, effective reasoning with exceptionally efficient performance in
/// coding and visual tasks.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini: Model = "o4-mini"

/// o4-mini-deep-research is a faster, more affordable deep research model—ideal for tackling
/// complex, multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own
/// data, brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini_deep_research: Model = "o4-mini-deep-research"
}

// MARK: - GPT-5

extension Model {
Expand Down
19 changes: 14 additions & 5 deletions Sources/OpenAI/Responses/ResponsesBody.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,13 +8,13 @@
import Foundation

public extension Responses {
struct Body: Codable {
struct Body: Encodable {
/// Whether to run the model response in the background.
public var background: Bool?
/// Specify additional output data to include in the model response.
public var include: [AdditionalOutput]?
///
public var input: String?
/// Text, image, or file inputs to the model, used to generate a response.
public var input: [Input]?
/// A system (or developer) message inserted into the model's context.
///
/// When using along with `previous_response_id`, the instructions from a previous response
Expand DownExpand Up@@ -45,8 +45,8 @@ public extension Responses {
public var parallelToolCalls: Bool?
/// The unique ID of the previous response to the model. Use this to create multi-turn conversations.
public var previousResponseId: String?
///
public var prompt: String?
/// Reference to a prompt template and its variables.
public var prompt: Prompt?
/// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
public var promptCacheKey: String?
///
Expand DownExpand Up@@ -122,5 +122,14 @@ public extension Responses {
/// an organization is enrolled in the zero data retention program).
case reasoningEncryptedContent = "reasoning.encrypted_content"
}

public struct Input: Encodable, Sendable {
/// The role of the message input. One of `user`, `assistant`, `system`, or `developer`.
public let role: Role

/// Text, image, or audio input to the model, used to generate a response. Can also contain
/// previous assistant responses.
public let content: [Content]
}
}
}
8 changes: 4 additions & 4 deletions Sources/OpenAI/Responses/ResponsesWrapper.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,15 +12,15 @@ public struct ResponsesWrapper {
public func create(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand DownExpand Up@@ -65,15 +65,15 @@ public struct ResponsesWrapper {
public func createStream(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
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
118 changes: 118 additions & 0 deletions Sources/OpenAI/Common/Content.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
//
// Content.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

public enum Content: Encodable, Sendable {
case inputText(TextInput)
case inputImage(ImageInput)
case inputFile(FileInput)

enum TypeCodingKeys: String, CodingKey {
case type
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()

switch self {
case .inputText(let textInput):
try container.encode(textInput)
case .inputImage(let imageInput):
try container.encode(imageInput)
case .inputFile(let fileInput):
try container.encode(fileInput)
}

}
}

/// A text input to the model.
public struct TextInput: Codable, Sendable {
/// The text input to the model.
public let text: String

/// The type of the input item. Always `input_text`.
public let type: ContentType

enum CodingKeys: CodingKey {
case text
case type
}

public init(text: String) {
self.text = text
self.type = .inputText
}
}

/// An image input to the model.
public struct ImageInput: Codable, Sendable {
/// The detail level of the image to be sent to the model.
///
/// One of `high`, `low`, or `auto`. Defaults to `auto`.
public let detail: ImageDetail

/// The type of the input item. Always `input_image`.
public let type: ContentType

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the image to be sent to the model.
///
/// A fully qualified URL or base64 encoded image in a data URL.
public let imageUrl: String?

public init(detail: ImageDetail = .auto, fileId: String? = nil, imageUrl: String? = nil) {
self.detail = detail
self.type = .inputImage
self.fileId = fileId
self.imageUrl = imageUrl
}
}

/// A file input to the model.
public struct FileInput: Codable, Sendable {
/// The type of the input item. Always `input_file`.
public let type: ContentType

/// The content of the file to be sent to the model.
public let fileData: String?

/// The ID of the file to be sent to the model.
public let fileId: String?

/// The URL of the file to be sent to the model.
public let fileUrl: String?

/// The name of the file to be sent to the model.
public let filename: String?

public init(
fileData: String? = nil,
fileId: String? = nil,
fileUrl: String? = nil,
filename: String? = nil
) {
self.type = .inputFile
self.fileData = fileData
self.fileId = fileId
self.fileUrl = fileUrl
self.filename = filename
}
}

public enum ContentType: String, Codable, Sendable {
case inputText = "input_text"
case outputText = "output_text"
case inputFile = "input_file"
case inputImage = "input_image"
}


public enum ImageDetail: String, Codable, Sendable {
case auto, low, high
}
27 changes: 27 additions & 0 deletions Sources/OpenAI/Common/Prompt.swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
//
// Prompt.swift
// OpenAI
//
// Created by Firdavs Khaydarov on 08/08/2025.
//

// TODO: Implement file input https://platform.openai.com/docs/guides/text#reusable-prompts

public struct Prompt: Encodable, Sendable {
/// The unique identifier of the prompt template to use.
public let id: String

/// Optional map of values to substitute in for variables in your prompt.
///
/// The substitution values can either be strings, or other Response input types like images or files.
public let variables: [String: String]?

/// Optional version of the prompt template.
public let version: String?

public init(id: String, variables: [String: String]? = nil, version: String? = nil) {
self.id = id
self.variables = variables
self.version = version
}
}
78 changes: 78 additions & 0 deletions Sources/OpenAI/Model.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,86 @@
// Created by Firdavs Khaydarov on 01/08/2025.
//

/// Model type to define OpenAI models.
///
/// For more information about models and their capabilities visit https://platform.openai.com/docs/models
public typealias Model = String

// MARK: - o-series

extension Model {
/// o1 models think before they answer, producing a long internal chain of thought before responding to the user.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1: Model = "o1"

/// The o1-pro model uses more compute to think harder and provide consistently better answers.
///
/// o1-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o1_pro: Model = "o1-pro"

/// o3 is a well-rounded and powerful model across domains.
///
/// Use it to think through multi-step problems that involve analysis across text, code, and images.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3: Model = "o3"

/// The o3-pro model uses more compute to think harder and provide consistently better answers.
///
/// o3-pro is available in the Responses API only to enable support for multi-turn model
/// interactions before responding to API requests, and other advanced API features in the future.
/// Since o3-pro is designed to tackle tough problems, some requests may take several minutes to
/// finish. To avoid timeouts, try using background mode.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_pro: Model = "o3-pro"

/// o3-mini is our newest small reasoning model, providing high intelligence at the same cost
/// and latency targets of o1-mini.
///
/// o3-mini supports key developer features, like Structured Outputs, function calling, and Batch API.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_mini: Model = "o3-mini"

/// o3-deep-research is the most advanced model for deep research, designed to tackle complex,
/// multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own data—brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o3_deep_research: Model = "o3-deep-research"

/// o4-mini is the latest small o-series model.
///
/// It's optimized for fast, effective reasoning with exceptionally efficient performance in
/// coding and visual tasks.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini: Model = "o4-mini"

/// o4-mini-deep-research is a faster, more affordable deep research model—ideal for tackling
/// complex, multi-step research tasks.
///
/// It can search and synthesize information from across the internet as well as from your own
/// data, brought in through MCP connectors.
///
/// * Context window: 200,000
/// * Max output tokens: 100,000
public static let o4_mini_deep_research: Model = "o4-mini-deep-research"
}

// MARK: - GPT-5

extension Model {
Expand Down
19 changes: 14 additions & 5 deletions Sources/OpenAI/Responses/ResponsesBody.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,13 +8,13 @@
import Foundation

public extension Responses {
struct Body: Codable {
struct Body: Encodable {
/// Whether to run the model response in the background.
public var background: Bool?
/// Specify additional output data to include in the model response.
public var include: [AdditionalOutput]?
///
public var input: String?
/// Text, image, or file inputs to the model, used to generate a response.
public var input: [Input]?
/// A system (or developer) message inserted into the model's context.
///
/// When using along with `previous_response_id`, the instructions from a previous response
Expand DownExpand Up@@ -45,8 +45,8 @@ public extension Responses {
public var parallelToolCalls: Bool?
/// The unique ID of the previous response to the model. Use this to create multi-turn conversations.
public var previousResponseId: String?
///
public var prompt: String?
/// Reference to a prompt template and its variables.
public var prompt: Prompt?
/// Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
public var promptCacheKey: String?
///
Expand DownExpand Up@@ -122,5 +122,14 @@ public extension Responses {
/// an organization is enrolled in the zero data retention program).
case reasoningEncryptedContent = "reasoning.encrypted_content"
}

public struct Input: Encodable, Sendable {
/// The role of the message input. One of `user`, `assistant`, `system`, or `developer`.
public let role: Role

/// Text, image, or audio input to the model, used to generate a response. Can also contain
/// previous assistant responses.
public let content: [Content]
}
}
}
8 changes: 4 additions & 4 deletions Sources/OpenAI/Responses/ResponsesWrapper.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,15 +12,15 @@ public struct ResponsesWrapper {
public func create(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand DownExpand Up@@ -65,15 +65,15 @@ public struct ResponsesWrapper {
public func createStream(
background: Bool? = nil,
include: [Responses.Body.AdditionalOutput]? = nil,
input: String? = nil,
input: [Responses.Body.Input]? = nil,
instructions: String? = nil,
maxOutputTokens: Int? = nil,
maxToolCalls: Int? = nil,
metadata: [String : String]? = nil,
model: Model? = nil,
parallelToolCalls: Bool? = nil,
previousResponseId: String? = nil,
prompt: String? = nil,
prompt: Prompt? = nil,
promptCacheKey: String? = nil,
reasoning: String? = nil,
safetyIdentifier: String? = nil,
Expand Down