Skip to content

Contracts Project: Introduction and Upgrade Guide

Tolga Kayhan edited this page Nov 2, 2025 · 1 revision

Contracts Project: Introduction and Upgrade Guide

This document introduces the new Betalgo.Ranul.OpenAI.Contracts project, explains why we’re adopting it, outlines what changed, and shows how to upgrade your code.

Overview

  • New project: Betalgo.Ranul.OpenAI.Contracts centralizes request/response models, enums/value types, and capability interfaces.
  • Direction: We’ll roll this pattern out gradually across the SDK as models and APIs grow in complexity.
  • Roadmap: The next update targets GPT‑5 features and the Reasoning API.
  • Stability: These changes will be tested for a while and may evolve; we’ve kept them minimal to reduce friction.

Why this change

  • Complex model structures and API variants demand stronger, decoupled contracts.
  • Centralized contracts give us clearer versioning, reusability, and easier migrations.

What changed (high level)

  • Added Betalgo.Ranul.OpenAI.Contracts with:
    • Requests: Requests.Image.CreateImageRequest, CreateImageEditRequest, CreateImageVariationRequest
    • Responses: Responses.Image.ImageResponse, shared base: Responses.Base.ResponseBase, ResponseBaseHeaderValues, ResponseError, RateLimitInfo, OpenAIInfo
    • Enums/value types: Enums.* and Enums.Image.* (e.g., ImageSize, ImageOutputFormat, ImageResponseFormat, ImageModeration, Voice, roles)
    • Types: Types.FormFile, Types.FormFileOrList, Types.StringOrList
    • Interfaces: Interfaces.IHasImageSize, IHasImageBackground, IHasImageOutputFormat, IHasImageQuality, IHasModelImage
  • Removed legacy image request models from OpenAI.SDK/ObjectModels/RequestModels and replaced with Contracts requests.
  • Introduced V2 HTTP helpers wired to ResponseBase; legacy helpers retained for backward compatibility.
  • Request/response models are now classes instead of records; usage stays the same (object initializers and JSON names unchanged).

Impacted files (selected)

  • Added: Betalgo.Ranul.OpenAI.Contracts/**
  • Removed: OpenAI.SDK/ObjectModels/RequestModels/ImageCreateRequest.cs, ImageEditCreateRequest.cs, ImageVariationCreateRequest.cs, SharedImageRequestBaseModel.cs
  • Updated: OpenAI.SDK/Interfaces/IImageService.cs, OpenAI.SDK/Managers/OpenAIImage.cs, Playground image tests
  • Added (compat): OpenAI.SDK/Extensions/HttpclientExtensionsLegacy.cs

Breaking changes and replacements

Old type/namespace New type/namespace
OpenAI.SDK.ObjectModels.RequestModels.ImageCreateRequest Betalgo.Ranul.OpenAI.Contracts.Requests.Image.CreateImageRequest
OpenAI.SDK.ObjectModels.RequestModels.ImageEditCreateRequest Betalgo.Ranul.OpenAI.Contracts.Requests.Image.CreateImageEditRequest
OpenAI.SDK.ObjectModels.RequestModels.ImageVariationCreateRequest Betalgo.Ranul.OpenAI.Contracts.Requests.Image.CreateImageVariationRequest
OpenAI.SDK.ObjectModels.SharedModels.SharedImageRequestBaseModel Replaced by small capability interfaces under Betalgo.Ranul.OpenAI.Contracts.Interfaces
Enums.VoiceEnum Betalgo.Ranul.OpenAI.Contracts.Enums.Voice (value type)
Enums.MessageRole Betalgo.Ranul.OpenAI.Contracts.Enums.ChatCompletionRole and/or AssistantMessageRole
Top-level Enums.Image* Betalgo.Ranul.OpenAI.Contracts.Enums.Image.* (moved/clarified)
Responses.Base.ResponseHeaderValues Betalgo.Ranul.OpenAI.Contracts.Responses.Base.ResponseBaseHeaderValues

Additional API change:

  • IImageService methods CreateImageEdit and CreateImageVariation now return ImageResponse (previously returned ImageCreateResponse).

IImageService now consumes Contracts models and returns Contracts ImageResponse for all image operations:

Task<ImageResponse> CreateImage(CreateImageRequest imageCreate, CancellationToken cancellationToken = default);
Task<ImageResponse> CreateImageEdit(CreateImageEditRequest imageEditCreateRequest, CancellationToken cancellationToken = default);
Task<ImageResponse> CreateImageVariation(CreateImageVariationRequest imageEditCreateRequest, CancellationToken cancellationToken = default);

Notes:

  • All three methods return Contracts.Responses.Image.ImageResponse, unifying image responses on the Contracts model.

What you need to update

  1. Update usings/namespaces
  • Remove: using OpenAI.SDK.ObjectModels.RequestModels;
  • Add:
    • using Betalgo.Ranul.OpenAI.Contracts.Requests.Image;
    • using Betalgo.Ranul.OpenAI.Contracts.Enums.Image;
    • Optionally: using Betalgo.Ranul.OpenAI.Contracts.Types;
    • For roles/voices: using Betalgo.Ranul.OpenAI.Contracts.Enums;
  1. Switch to Contracts request models
  • Image create:
var imageResult = await sdk.Image.CreateImage(new()
{
    Prompt = "Laser cat eyes",
    N = 1,
    Size = ImageSize.Size256
});
  • Image edit (supports single or multiple images via FormFileOrList):
var imageResult = await sdk.Image.CreateImageEdit(new()
{
    Image = new FormFile(originalFileName, originalFile), // or: new List<FormFile> { ... }
    Mask = new(maskFileName, maskFile),
    Prompt = "A sunlit indoor lounge area with a pool containing a cat",
    N = 4,
    Size = ImageSize.Size1024,
    ResponseFormat = ImageResponseFormat.Url,
    User = "TestUser"
});
  • Image variation:
var imageResult = await sdk.Image.CreateImageVariation(new()
{
    Image = new(originalFileName, originalFile),
    N = 2,
    Size = ImageSize.Size256,
    ResponseFormat = ImageResponseFormat.Url,
    User = "TestUser"
});
  1. Use the new file/union types where needed
public class FormFile(string name, Stream data)
{
    public string Name { get; set; } = name;
    public Stream Data { get; set; } = data;
}

// Single or list with implicit conversions
FormFileOrList single = new FormFile("cat.png", stream);
FormFileOrList many = new List<FormFile> { new("a.png", a), new("b.png", b) };
  1. Update enums/value types
  • Roles:
var role = ChatCompletionRole.Assistant; // developer, system, user, assistant, tool
  • Voices:
var voice = Voice.Alloy; // echo, fable, nova, onyx, shimmer
  • Image response/output formats and size:
var format = ImageOutputFormat.Png;        // jpeg, webp
var responseFormat = ImageResponseFormat.Url; // or: ImageResponseFormat.Base64
var size = ImageSize.Size1024;             // 256, 512, 1024, 1792x1024, 1024x1792

About the new enum types (future‑proof value types)

We replaced many traditional C# enums with small, immutable value types (e.g., ImageResponseFormat, ImageOutputFormat, ImageSize, Voice, ChatCompletionRole). These types are designed to be both type‑safe and future‑proof:

  • IDE IntelliSense: Known values are exposed as static properties, so your IDE will autocomplete them (as shown in the screenshot). This makes code self‑documenting and prevents typos.
  • Future‑proofing: These types support implicit conversion to/from string. If OpenAI adds a new value we haven’t shipped yet, you can still use it immediately by assigning a raw string. No waiting for a library update.
  • JSON friendly: Each type includes a JsonConverter so it serializes/deserializes as a simple string in requests/responses.
  • Case‑insensitive equality: Comparisons are insensitive to letter case, making checks straightforward.

Examples image-d3f6fc89-a7d1-4486-8875-2370bf7c9655

This approach gives you the best of both worlds: discoverability and safety via IntelliSense for known values, plus immediate access to new values as plain strings without breaking changes.

  1. Response handling and headers
  • All image endpoints return ImageResponse, which implements IDefaultResult<string> and IDefaultResults<string>:
var first = imageResponse.Result;      // first URL or base64
var all = imageResponse.Results;       // all URLs/base64 strings
  • Headers via ResponseBaseHeaderValues:
var headers = imageResponse.HeaderValues;
var requestId = headers?.XRequestId;

Notable additions

  • ImageModeration value type (low, auto) for gpt-image-1 moderation.
  • StringOrList and FormFileOrList unions with converters for flexible JSON shape.
  • ResponseBase now exposes HttpStatusCode, HeaderValues, Error, and IsDelta helpers.

Compatibility and minimal disruption

  • Legacy HTTP helpers (OpenAI.SDK/Extensions/HttpclientExtensionsLegacy.cs) remain for existing flows.
  • Image enums were reorganized but preserve literal values; mostly namespace changes plus clarified names.
  • Image create/edit/variation now share the same ImageResponse return type.

Known limitations and next steps

  • This is the first pass; Contracts usage will expand across the SDK.
  • Upcoming: GPT‑5 features, Reasoning API alignment, and unifying image edit/variation responses on Contracts base types.
  • Expect minor adjustments during testing; we’ll keep migrations straightforward.
Clone this wiki locally