This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is the OpenAI provider implementation for OpenFoundationModels framework. It enables using OpenAI's latest GPT and Reasoning models (GPT-4o, o1, o3, o4-mini) through Apple's Foundation Models API interface with a unified, self-contained architecture.
# Build the package
swift build
# Run all tests
swift test
# Run tests with verbose output
swift test --verbose
# Run a specific test
swift test --filter OpenAILanguageModelTests
# Clean build artifacts
swift package clean
# Update dependencies
swift package update
# Generate Xcode project (if needed)
swift package generate-xcodeproj-
OpenAILanguageModel: Main provider class implementing the
LanguageModelprotocol from OpenFoundationModels- Transcript-based interface: Processes complete conversation context via
Transcript - Unified interface for all OpenAI models (GPT and Reasoning)
- Automatic constraint handling based on model type
- Built-in streaming support with Server-Sent Events
- Actor-based rate limiting and retry logic
- Transcript-based interface: Processes complete conversation context via
-
OpenAIModel: Unified model enumeration
- Single enum covering GPT-4o, Reasoning models (o1, o3, o4-mini)
- Internal model type detection for automatic parameter validation
- Model-specific capabilities and constraints
-
Custom HTTP Client: Self-contained networking layer
- No external dependencies beyond OpenFoundationModels
- URLSession-based implementation with streaming support
- Built-in error mapping and response handling
-
Request/Response Handlers: Model-specific processing
- Separate builders for GPT vs Reasoning model requests
- Automatic parameter filtering based on model constraints
- Specialized error handling per model type
When implementing the OpenAILanguageModel, ensure:
-
Protocol Conformance (Transcript-based):
generate(transcript:options:)- ReturnsTranscript.Entrywith complete responsestream(transcript:options:)- ReturnsAsyncStream<Transcript.Entry>for streamingisAvailable- Synchronous property checking API availabilitysupports(locale:)- Returns true (OpenAI supports most languages)- Extracts tools from
Transcript.Instructions.toolDefinitions - Converts
Transcript.Entrytypes to OpenAI message format
-
Structured Generation:
- Use OpenAI Function Calling for
Generabletypes - Convert
GenerationSchemato JSON Schema format - Handle function call responses and map back to Swift types
- Use OpenAI Function Calling for
-
Error Handling:
- Map OpenAI API errors to
OpenAIErrorenum - Handle rate limits with proper retry-after headers
- Convert network errors appropriately
- Map OpenAI API errors to
-
Streaming Implementation:
- Use
AsyncStreamwith proper continuation handling - Yield partial content from delta responses
- Handle errors within the stream
- Use
- OpenFoundationModels: Core framework providing protocols and types (only dependency)
- Self-contained HTTP client implementation (no external API clients)
- Zero third-party dependencies for maximum flexibility
Sources/OpenFoundationModelsOpenAI/
├── OpenAILanguageModel.swift # Main provider implementation
├── OpenAIConfiguration.swift # Configuration and model definitions
├── OpenFoundationModelsOpenAI.swift # Public API and convenience initializers
├── Models/
│ └── OpenAIModel.swift # Unified model enum with capabilities
├── HTTP/
│ └── OpenAIHTTPClient.swift # Custom HTTP client implementation
├── API/
│ └── OpenAIAPITypes.swift # OpenAI API data structures
└── Internal/
├── RequestBuilders.swift # Model-specific request builders
├── ResponseHandlers.swift # Model-specific response handlers
└── StreamingHandler.swift # Advanced streaming implementation
- Mock the OpenAI client for unit tests
- Use environment variable for API key in integration tests
- Test rate limiting behavior with mock timestamps
- Verify error mapping for all OpenAI error codes
- Test streaming with various response patterns
-
Transcript-Centric Architecture: Fully embraces OpenFoundationModels' Transcript-based design:
- Stateless model interface - all context provided via Transcript
- Converts Transcript entries (Instructions, Prompt, Response, ToolCalls, ToolOutput) to OpenAI format
- Extracts tool definitions from Instructions for function calling
-
Unified Model Interface: Single OpenAIModel enum that internally handles GPT vs Reasoning model differences, providing a seamless user experience without model-specific APIs.
-
Self-Contained Architecture: No external dependencies beyond OpenFoundationModels, using custom URLSession-based HTTP client for maximum flexibility and control.
-
Automatic Constraint Handling: Internal model type detection automatically applies correct parameter constraints (e.g., temperature not supported for Reasoning models).
-
Actor-Based Concurrency: Rate limiting and HTTP client use Swift actors for thread-safe operation and optimal performance.
-
Direct Instantiation Pattern: Direct instantiation of request builders and response handlers based on model type, following Swift conventions without factory pattern.
-
Advanced Streaming: Server-Sent Events implementation with buffering, accumulation, and error handling for reliable real-time responses.
The OpenAI provider now fully supports OpenFoundationModels' Transcript-based interface, providing complete conversation context management.
// Convert Transcript entries to OpenAI ChatMessage format
internal extension Array where Element == ChatMessage {
static func from(transcript: Transcript) -> [ChatMessage] {
var messages: [ChatMessage] = []
for entry in transcript.entries {
switch entry {
case .instructions(let instructions):
// System message with instructions
let content = extractText(from: instructions.segments)
messages.append(ChatMessage.system(content))
case .prompt(let prompt):
// User message
let content = extractText(from: prompt.segments)
messages.append(ChatMessage.user(content))
case .response(let response):
// Assistant message
let content = extractText(from: response.segments)
messages.append(ChatMessage.assistant(content))
case .toolCalls:
// Tool execution (placeholder for now)
messages.append(ChatMessage.assistant("Tool calls executed"))
case .toolOutput(let toolOutput):
// Tool result
messages.append(ChatMessage.system("Tool output: \(toolOutput.toolName)"))
}
}
return messages
}
}private func extractTools(from transcript: Transcript) -> [Transcript.ToolDefinition]? {
for entry in transcript.entries {
if case .instructions(let instructions) = entry {
return instructions.toolDefinitions
}
}
return nil
}- Stateless Design: Model doesn't maintain conversation state
- Complete Context: Every request includes full conversation history
- Tool Support: Automatic extraction of tool definitions from Instructions
- Flexible Segments: Handles both text and structured segments
- Provider Agnostic: Clean separation between OpenFoundationModels and OpenAI APIs
The current implementation correctly conforms to the LanguageModel protocol from OpenFoundationModels:
public protocol LanguageModel: Sendable {
func generate(transcript: Transcript, options: GenerationOptions?) async throws -> Transcript.Entry
func stream(transcript: Transcript, options: GenerationOptions?) -> AsyncStream<Transcript.Entry>
var isAvailable: Bool { get }
func supports(locale: Locale) -> Bool
}Implementation Status:
- ✅
generate(transcript:options:)- ReturnsTranscript.Entrywith complete response - ✅
stream(transcript:options:)- ReturnsAsyncStream<Transcript.Entry>for streaming - ✅
isAvailable- Synchronous property (returnstrue) - ✅
supports(locale:)- Returnstruefor all locales (OpenAI supports most languages)
- ✅ Build succeeds:
swift buildcompletes without errors - ✅ All tests pass: 205 tests in 11 suites
- ✅ No TODO/FIXME comments in source code
The implementation correctly handles all Transcript.Entry types:
public enum Transcript.Entry {
case instructions(Transcript.Instructions)
case prompt(Transcript.Prompt)
case response(Transcript.Response)
case toolCalls(Transcript.ToolCalls)
case toolOutput(Transcript.ToolOutput)
}The TranscriptConverter utility handles conversion between OpenFoundationModels Transcript format and OpenAI API format:
- Converts Transcript entries to OpenAI ChatMessage array
- Extracts tool definitions for function calling
- Handles response format extraction for structured generation
- Supports JSON-based extraction with fallback methods
Remark is a Swift library and command-line tool that converts HTML to Markdown and enables viewing JavaScript-containing pages. This is particularly useful for documentation generation and web content processing.
dependencies: [
.package(url: "https://github.com/1amageek/Remark.git", branch: "main")
]git clone https://github.com/1amageek/Remark.git
cd Remark
make install# Basic HTML to Markdown conversion
remark https://example.com
# Include front matter for static site generators
remark --include-front-matter https://platform.openai.com/docs/models
# Process JavaScript-heavy pages
remark https://docs.openai.com/apiimport Remark
// Convert HTML to Markdown
let htmlContent = """
<h1>OpenAI Models</h1>
<p>GPT-4o is a multimodal model...</p>
"""
let remark = try Remark(htmlContent)
let markdown = remark.page
print(markdown)Use Remark to convert OpenAI documentation pages to Markdown for local reference:
# Convert model documentation
remark --include-front-matter https://platform.openai.com/docs/models > models.md
# Convert API reference
remark https://platform.openai.com/docs/api-reference/chat > api-reference.mdWhen building applications that need to process web content with OpenAI:
import Remark
import OpenFoundationModelsOpenAI
import OpenFoundationModels
// Extract content from web pages
let url = "https://example.com/article"
let htmlContent = try String(contentsOf: URL(string: url)!)
let remark = try Remark(htmlContent)
// Use extracted content with OpenAI via Transcript
let openAI = OpenAILanguageModel(apiKey: apiKey)
var transcript = Transcript()
transcript.append(.prompt(Transcript.Prompt(segments: [
.text(Transcript.TextSegment(content: "Summarize this article:\n\(remark.page)"))
])))
let response = try await openAI.generate(transcript: transcript, options: nil)Remark automatically extracts Open Graph metadata, useful for content analysis:
let remark = try Remark(htmlContent)
print("Title: \(remark.title)")
print("Description: \(remark.description)")
print("Image: \(remark.image)")- API Documentation Processing: Convert OpenAI's API docs to Markdown for offline reference
- Content Ingestion: Process web articles for AI analysis
- Static Site Generation: Extract content with proper front matter
- Research Material: Convert research papers and documentation to readable format
This project follows a structured testing approach using Swift Testing framework to ensure comprehensive coverage and reliable validation of the OpenAI provider implementation.
-
Incremental Implementation: Tests are implemented one at a time, with each test fully completed and validated before proceeding to the next.
-
Failure Analysis Protocol: When any test fails, follow this analysis procedure:
- Step 1: Determine if the test itself is incorrect (test bug)
- Step 2: Analyze if the implementation has a defect (implementation bug)
- Step 3: Verify expected behavior against OpenAI API documentation
- Step 4: Make targeted fixes based on root cause analysis
-
Structural Test Design: Tests are organized in a hierarchical structure using Swift Testing's
@Suitefor logical grouping and clear separation of concerns.
- Foundation Phase: Core component tests (OpenAILanguageModel, basic functionality)
- API Layer Phase: Request builders, response handlers, and serialization
- Streaming Phase: Async operations, Server-Sent Events processing
- Error Handling Phase: Comprehensive error scenarios and recovery
- Integration Phase: End-to-end testing with live API (optional, requires API key)
When a test fails:
-
Test Validation:
// Verify test expectations are correct #expect(actualValue == expectedValue, "Clear description of what should happen")
-
Implementation Analysis:
// Add debug logging to understand actual behavior print("Expected: \(expected), Actual: \(actual)")
-
Documentation Cross-Reference:
- Check OpenAI API documentation for correct behavior
- Verify OpenFoundationModels protocol requirements
- Validate against Apple Foundation Models β SDK compatibility
-
Targeted Fix Implementation:
- Fix only the specific issue identified
- Ensure fix doesn't break existing tests
- Re-run affected test suite to validate
- Unit Tests: Use mock implementations to isolate components
- Integration Tests: Use real HTTP client with stubbed responses
- Live Tests: Optional tests with real API for final validation
- Core Functionality: 100% coverage of public APIs
- Error Scenarios: All documented error codes and network failures
- Edge Cases: Boundary conditions, rate limits, timeouts
- Concurrency: Thread safety and actor isolation compliance
- Brittle Test Prevention: Avoid testing implementation details
- Clear Test Intent: Each test has single, clear responsibility
- Maintainable Assertions: Use descriptive failure messages
@Suite("OpenAI Language Model Tests")
struct OpenAILanguageModelTests {
@Test("Basic text generation")
func testBasicGeneration() async throws {
// Implementation
}
@Test("Generation with different models", arguments: [
OpenAIModel.gpt4o,
OpenAIModel.gpt4oMini,
OpenAIModel.o3Mini
])
func testGenerationWithModels(model: OpenAIModel) async throws {
// Parameterized test implementation
}
}@Test("Streaming content delivery")
func testStreaming() async throws {
var transcript = Transcript()
transcript.append(.prompt(Transcript.Prompt(segments: [
.text(Transcript.TextSegment(content: "test"))
])))
await confirmation("Stream delivers content") { confirm in
for await entry in model.stream(transcript: transcript, options: nil) {
confirm()
break
}
}
}- Test execution time monitoring
- Flaky test identification and resolution
- Coverage gap analysis and remediation
- Test results inform implementation documentation
- Edge case discoveries update API usage examples
- Performance insights guide optimization recommendations
This methodology ensures high-quality, maintainable tests that provide confidence in the OpenAI provider implementation while supporting future development and debugging efforts.