Skip to content

Latest commit

 

History

History
138 lines (107 loc) · 18.9 KB

CHANGELOG.md

File metadata and controls

138 lines (107 loc) · 18.9 KB

Changelog

All notable changes to this package are documented in this file. The format follows Keep a Changelog, and versions follow Semantic Versioning.

Compatibility promise: the public API is additive-only. Anything public is deprecated before it is removed, and every pull request is compared with the latest release by swift package diagnose-api-breaking-changes in CI. See the API stability section of CONTRIBUTING.md.

Added

  • Model.gpt_image_1_5 for gpt-image-1.5 and Model.omniModerationLatest for omni-moderation-latest (#485).

Changed

  • CI: the API Breakage allowlist is emptied, because the 0.6.0 release is now the comparison baseline for the breaks it listed.

Fixed

  • Components.Schemas.ResponseOutputTextAnnotationAddedEvent.description printed a present annotation as Optional(...); it now prints the annotation itself, or nil.
  • Demo: an error from a request made while polling an assistant run in Chats was silently ignored and the request repeated every second. It now stops the polling and is shown in the conversation. Link preview failures are logged instead of discarded.
  • JSON requests never checked the HTTP status, so an HTML gateway body surfaced as a DecodingError, and with ParsingOptions.relaxed a status of 400 or above whose body was missing required fields could decode as a successful result. Completion-handler, async, and Combine JSON calls now throw for a status of 400 or above, as raw and streaming calls already did: the decoded APIErrorResponse or GeminiAPIErrorResponse, or OpenAIError.statusError when the body isn't an API error (#471).

0.6.0 - 2026-10-27

Added

  • openAI.files (FilesEndpointProtocol) for the Files API: create(query:), retrieve(id:), list(query:) and list(), delete(id:) and content(id:), in callback, async and Combine variants. The names match the official Java and Python SDKs' files.create/retrieve/list/delete/content. ListFilesQuery carries the purpose, limit, order and after parameters, content(id:) returns the file's contents as Data, and delete(id:) returns the generated Components.Schemas.DeleteFileResponse (#401).
  • CreateFileQuery.expiresAfter, sent as expires_after, to set a file's expiration policy (#401).
  • OpenAIFile and ListFilesResponse, hand-written replacements for the generated schemas of the same names. The spec's purpose enum on the file object omits evals, although evals is a valid upload purpose, so the generated type would fail to decode a file uploaded for evals; OpenAIFile.Purpose is an open type that decodes any value. ListFilesResponse.firstId and lastId are optional, because the API returns null for both on an empty page although the spec marks them required (#401).
  • Demo: a Files screen (Misc → Files) that lists, uploads, retrieves, downloads and deletes files through openAI.files (#470).

Changed

  • Breaking: OpenAIProtocol gained a files requirement. Code that only calls openAI.files is unaffected, but custom conformances (e.g. test doubles) need to implement it (#401).
  • FilesQuery was renamed to CreateFileQuery, matching files.create(query:). FilesQuery remains as a deprecated typealias, so existing code compiles unchanged. The API breakage check still reports that files(query:) changed its parameter type from FilesQuery to CreateFileQuery, because it compares type names; these reports are allowlisted (#401).

Deprecated

  • files(query:) on OpenAIProtocol, OpenAIAsync and OpenAICombine; use openAI.files.create(query:), which returns the full OpenAIFile rather than a FilesResult with only an id and a name the API doesn't return (#401).

Fixed

  • audioCreateSpeech and files.content(id:) returned an API error response's JSON body as if it were the audio or file content, because responses read as raw data never had their HTTP status checked. They now throw for a status of 400 or above: the decoded APIErrorResponse, or OpenAIError.statusError when the body isn't an API error, as streaming requests already did (#401).
  • Demo: streamed chat replies kept updating long after the stream had ended; with a web search reply in Responses, the last update came 15.5 s later. ExyteChat's ChatView applies each change to its messages as a separate animated update of about half a second, while the stores published a change every 100 ms. The Chats and Responses screens now pass on at most one update every 500 ms, always with the latest messages (#475).
  • Demo: deleting a conversation in Chats didn't remove it from ChatStore, so it came back the next time the conversations changed. It's now deleted, except while a reply is in progress, when an alert explains that it can't be (#475).

0.5.3 - 2026-10-08

Added

  • Model.gpt_audio_1_5, Model.gpt_audio and Model.gpt_audio_mini, the audio-in, audio-out models for Chat Completions, also returned by Model.allModels(satisfying:). The README gained an Audio input and output with Chat Completions section covering modalities, audioOptions, audio input parts and streaming (#397).

Changed

  • Model.gpt_4o_audio_preview is deprecated, since OpenAI shut the model down on May 7th, 2026; use Model.gpt_audio_1_5. It is no longer returned by Model.allModels(satisfying:) (#397).
  • swift-openapi-runtime 1.12.0 → 1.12.2, which also moves swift-http-types from 1.3.1 to 1.8.0 (#439, #459).
  • CI: the API Breakage allowlist is emptied, because the 0.5.2 release is now the comparison baseline for the breaks it listed.

Fixed

  • Demo: ResponsesStore.replyFunctionCall included the completed .functionToolCall in the next request along with its .functionCallOutputItemParam while previous_response_id was already set, so the Responses API rejected the follow-up with Duplicate item found with id fc_.... The follow-up now sends only the function-call output, and the pending call stays available if that request fails (#457).

0.5.2 - 2026-10-07

Added

  • ModelSpec, describing a model's capabilities as its OpenAI docs page lists them: endpoints, features, Responses API tools, supported reasoning efforts, and limitations the docs note, such as Chat Completions function calling being unsupported or requiring reasoning_effort: none (ModelSpec.Endpoint, .Feature, .Tool, .ReasoningEffort and .Limitation). ModelSpec.all currently covers the GPT-6 models; Model.allModels(satisfying:) filters them by their spec. Model.Filter.Endpoint, .Feature and .Tool are now typealiases for the ModelSpec types. ModelSpec.ReasoningEffort converts to Components.Schemas.ReasoningEffort and ChatQuery.ReasoningEffort (xhigh and max become .customValue, as ChatQuery.ReasoningEffort has no cases for them).
  • Model.gpt6_astra, Model.gpt6_sol and Model.gpt6_luna, also returned by Model.allModels(satisfying:) for the Chat Completions and Responses endpoints and the MCP tool.
  • Model.Filter.Tool.mcp and Model.Filter.requiredTools, so Model.allModels(satisfying:) can narrow results to models that support remote MCP servers in the Responses API.
  • ResponseStreamEvent.shellCall, covering the new shell-call streaming events (response.shell_call_command.added/delta/done, response.shell_call_output_content.delta/done) added by the latest OpenAPI spec.
  • Tool.programmaticToolCallingTool, the tool case paired with the OutputItem.program/.programOutput response items; without it, decoding a response whose tools array contains a programmatic_tool_calling tool would throw.
  • ResponseStreamEvent.customToolCallInput, covering the previously unhandled response.custom_tool_call_input.delta/done streaming events; without it, a custom-tool streaming response would fail the whole stream with an unknownEventType error.
  • InputItem.compactionTriggerItemParam, .programItemParam, and .programOutputItemParam, the item cases added by the latest OpenAPI spec; without them, decoding an input item with type: "compaction_trigger", "program", or "program_output" would throw unknownOneOfDiscriminator.
  • ResponsesEndpoint.retrieveResponse(query:) and cancelResponse(id:), in callback, async and Combine variants, for GET /responses/{response_id} and POST /responses/{response_id}/cancel. RetrieveModelResponseQuery.include is sent as include[] query parameters. Cancelling takes just the response ID, matching the official Python SDK's client.responses.cancel(response_id), and only applies to responses created with background: true.
  • CreateModelResponseQuery.contextManagement, encoded as context_management, for configuring server-side context compaction.
  • CI: an API Breakage workflow fails a pull request that changes the public API compared with the latest release tag. Consciously accepted breaks are listed in .github/api-breakage-allowlist.txt with a matching changelog entry.
  • CI: the Swift Build workflow now builds and tests on Linux with Swift 5.10, 6.0 and 6.3 containers, tests on macOS and the iOS Simulator, and builds for tvOS, watchOS and visionOS with Xcode. Tests written with Swift Testing only exist on toolchains that ship it (Swift 6); the XCTest suite runs everywhere.
  • CONTRIBUTING.md: API stability policy, including how new endpoint groups are added as namespaces and how generated Components.Schemas types are treated.
  • This changelog.

Changed

  • Breaking: ResponsesEndpointProtocol, ResponsesEndpointAsync and ResponsesEndpointCombine gained retrieveResponse and cancelResponse requirements. Code that only calls openAI.responses is unaffected, but custom conformances (e.g. test doubles) need to implement them.
  • Breaking: GetModelResponseQuery was renamed to RetrieveModelResponseQuery to match retrieveResponse(query:). It had no public initializer before, so it couldn't be constructed outside the package.
  • CreateModelResponseQuery.init gained a contextManagement parameter (defaulting to nil). Existing call sites compile unchanged; only code referring to the initializer by its full name, such as CreateModelResponseQuery.init(input:model:...) used as a function value, needs updating.
  • Breaking: Regenerated Components.Schemas from the latest OpenAPI spec. Most of the reported breaks are mechanical (new cases added to generated enums, and generated memberwise initializers gaining parameters for new optional fields) and are allowlisted in .github/api-breakage-allowlist.txt without individual call-outs, matching how the 0.5.1 regeneration was documented. The changes worth knowing about if you read or construct these types directly:
    • ResponseObject.instructions changed from String? to ResponseObject.Instructions?, letting instructions be either a plain string or a list of input items. Instructions is a generated two-case enum (.case1(String) for the string form, .case2([InputItem]) for the list form); code that read instructions as a String needs to switch over it instead. This mirrors how the official Python SDK models the same field (Union[str, List[ResponseInputItem], None]) rather than adding a second property under a new name.
    • Components.Schemas.ServiceTier was renamed to ServiceTierResponses.
    • Components.Schemas.Conversation2 was removed; Response.conversation and ResponseProperties-derived types now use ResponseConversation instead.
    • MCPToolCall.error changed from String? to MCPToolCallError?.
    • ResponseOutputTextAnnotationAddedEvent.annotation changed from OpenAPIObjectContainer to Annotation?, matching the stricter Annotation schema.
    • FunctionToolCallOutput.callId and FunctionCallOutputItemParam.callId changed from String to String?.
    • ResponseStreamEvent.reasoning was renamed to .reasoningText, with its payload changing from ReasoningEvent to ReasoningTextEvent.
    • ResponseObject.toolChoice changed from Schemas.ToolChoiceParam? to Schemas.ToolChoiceParam. The generated ResponseProperties.toolChoice is optional only because that schema is shared with request bodies, where tool_choice may be omitted; an actual Response always includes it, which we verified against the API docs and the official Python SDK (Response.tool_choice: ToolChoice, non-optional). This corrects a facade type that didn't match the real response shape, but is still a source-breaking type change for callers who read toolChoice as optional.
    • OutputItem.webSearchToolCall's payload changed from Components.Schemas.WebSearchToolCall to a new hand-written WebSearchToolCall type whose action is optional. The spec marks action required, but the live API can emit a web_search_call output item without one (e.g. a response.output_item.added event while status is still in_progress), and decoding threw a keyNotFound error for action whenever that happened. This is an acknowledged upstream spec bug (openai/openai-openapi#572), not something specific to any one status. Callers that read .webSearchToolCall(let call) need to unwrap call.action instead of accessing it directly.

Fixed

  • Demo: a non-streaming Responses request to a reasoning model (e.g. gpt-5) always includes a .reasoning output item, and ResponsesStore.createResponse(query:) didn't handle it (or the MCP output item cases), so it threw unhandledOutputItem instead of completing.
  • Components.Schemas.InputItem and the InputItem facade failed to decode a valid { "type": "item_reference", "id": "..." } payload with unknownOneOfDiscriminator. The generator only matched discriminator values declared as a plain string enum, but ItemReferenceParam.type is declared as a nullable anyOf: [<string enum>, {type: null}], which it didn't unwrap; the InputItem facade also fixed the same bug independently, plus a stale "ItemReference" discriminator string (missing the Param suffix) and a missing "message" match for EasyInputMessage.
  • ResponseStreamEvent and OutputItem didn't round-trip through JSONEncoder/JSONDecoder: both have a hand-written init(from:) that decodes the API's type discriminator, but no encode(to:), so the compiler-synthesized one wrapped values by enum case name instead of matching the API's shape; the hand-written ResponseOutputItemAddedEvent/ResponseOutputItemDoneEvent also gained a sequenceNumber field they were missing, since re-encoding through them dropped sequence_number.
  • ResponseStreamEvent.reasoningText streaming events never decoded: ModelResponseStreamEventType listened for response.reasoning.delta/.done, but the API sends response.reasoning_text.delta/.done, so reasoning-text deltas always failed with an unknownEventType error.
  • make download-spec could leave the tracked openapi.yaml truncated if curl was interrupted mid-transfer; it now downloads to a temp file and moves it into place only on success.
  • Build warning in ModelResponseEventsStreamInterpreter when logging a failed stream event decode in debug builds.
  • The test target compiles for the package's minimum iOS deployment target again; it used Regex, which requires iOS 16.
  • Building on Linux with Swift 5.10 works again. swift-corelibs-foundation gained the async URLSession APIs only in Swift 6, so the async client now bridges the completion-handler API on older Linux toolchains.

0.5.1 - 2026-07-21

Added

  • refusal field on the streaming chat completion delta (#408).
  • reasoningContent on assistant chat messages for providers that return reasoning (#402).
  • annotations on ChatStreamResult (#399).

Changed

  • Regenerated Components.Schemas from the updated OpenAPI spec (#433). This changed public generated types: transcription segment and word timestamps moved from Float to Double, ImageGenTool.SizePayload lost its fixed cases, responseId was removed from the response audio events, and ChatResult.Choice.Message.Annotation moved to a top-level Annotation type. Two ChatCompletionMessageParam initializers were removed.
  • swift-openapi-runtime 1.11.0 → 1.12.0 (#424).

0.5.0 - 2026-06-05

Added

  • model is optional in CreateModelResponseQuery for the stored-prompt (prompt_id) flow (#419).

Changed

  • Regenerated Components.Schemas from the fresh OpenAPI spec (#423); the release notes flagged possible breaking changes.
  • swift-openapi-runtime 1.8.2 → 1.11.0 (#416).

Fixed

  • Missing name field on ResponseFunctionCallArgumentsDoneEvent (#420).

0.4.9 - 2026-04-30

Added

  • completion_tokens_details on CompletionUsage (#411).
  • prompt_cache_key on CreateModelResponseQuery (#412).
  • Dependabot configuration for GitHub Actions and Swift dependencies (#414).

Changed

  • ChoiceDeltaToolCall.index is required again (#388).
  • ChatQuery description output is easier to read (#394).
  • Documentation: response_format versus text for structured outputs (#413); security policy points to the private reporting channel (#410).

Older releases are documented on the GitHub Releases page.