Skip to content
Open
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
18 changes: 18 additions & 0 deletions sdk_v2/cs/src/FoundryLocalManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,24 @@ await Utils.CallWithExceptionHandling(() => EnsureEpsDownloadedImplAsync(ct),
.ConfigureAwait(false);
}

/// <summary>
/// Creates an OpenAI Responses API client.
/// The web service must be started first via <see cref="StartWebServiceAsync"/>.
/// </summary>
/// <param name="modelId">Optional default model ID for requests.</param>
/// <returns>An <see cref="OpenAIResponsesClient"/> instance.</returns>
/// <exception cref="FoundryLocalException">If the web service is not running.</exception>
public OpenAIResponsesClient GetResponsesClient(string? modelId = null)
{
if (Urls == null || Urls.Length == 0)
{
throw new FoundryLocalException(
"Web service is not running. Call StartWebServiceAsync before creating a ResponsesClient.", _logger);
}

return new OpenAIResponsesClient(Urls[0], modelId);
}

private FoundryLocalManager(Configuration configuration, ILogger logger)
{
_config = configuration ?? throw new ArgumentNullException(nameof(configuration));
Expand Down
9 changes: 9 additions & 0 deletions sdk_v2/cs/src/IModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,13 @@ Task DownloadAsync(Action<float>? downloadProgress = null,
/// <param name="ct">Optional cancellation token.</param>
/// <returns>OpenAI.AudioClient</returns>
Task<OpenAIAudioClient> GetAudioClientAsync(CancellationToken? ct = null);

/// <summary>
/// Get an OpenAI Responses API client.
/// Unlike Chat/Audio clients (which use FFI), the Responses API is HTTP-based,
/// so the web service must be started first via <see cref="FoundryLocalManager.StartWebServiceAsync"/>.
/// </summary>
/// <param name="ct">Optional cancellation token.</param>
/// <returns>OpenAI.ResponsesClient</returns>
Task<OpenAIResponsesClient> GetResponsesClientAsync(CancellationToken? ct = null);
}
5 changes: 5 additions & 0 deletions sdk_v2/cs/src/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ public async Task<OpenAIAudioClient> GetAudioClientAsync(CancellationToken? ct =
return await SelectedVariant.GetAudioClientAsync(ct).ConfigureAwait(false);
}

public async Task<OpenAIResponsesClient> GetResponsesClientAsync(CancellationToken? ct = null)
{
return await SelectedVariant.GetResponsesClientAsync(ct).ConfigureAwait(false);
}

public async Task UnloadAsync(CancellationToken? ct = null)
{
await SelectedVariant.UnloadAsync(ct).ConfigureAwait(false);
Expand Down
24 changes: 24 additions & 0 deletions sdk_v2/cs/src/ModelVariant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ public async Task<OpenAIAudioClient> GetAudioClientAsync(CancellationToken? ct =
.ConfigureAwait(false);
}

public async Task<OpenAIResponsesClient> GetResponsesClientAsync(CancellationToken? ct = null)
{
return await Utils.CallWithExceptionHandling(() => GetResponsesClientImplAsync(ct),
"Error getting responses client for model", _logger)
.ConfigureAwait(false);
}

private async Task<bool> IsLoadedImplAsync(CancellationToken? ct = null)
{
var loadedModels = await _modelLoadManager.ListLoadedModelsAsync(ct).ConfigureAwait(false);
Expand Down Expand Up @@ -190,4 +197,21 @@ private async Task<OpenAIAudioClient> GetAudioClientImplAsync(CancellationToken?

return new OpenAIAudioClient(Id);
}

private async Task<OpenAIResponsesClient> GetResponsesClientImplAsync(CancellationToken? ct = null)
{
if (!await IsLoadedAsync(ct))
{
throw new FoundryLocalException($"Model {Id} is not loaded. Call LoadAsync first.");
}

var urls = FoundryLocalManager.Instance.Urls;
if (urls == null || urls.Length == 0)
{
throw new FoundryLocalException(
"Web service is not running. Call StartWebServiceAsync before creating a ResponsesClient.");
}

return new OpenAIResponsesClient(urls[0], Id);
}
}
Loading