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
10 changes: 10 additions & 0 deletions dotnet/src/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,8 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig config, Cance
RequestExtensions: config.RequestExtensions,
ExtensionSdkPath: config.ExtensionSdkPath,
ExtensionInfo: config.ExtensionInfo,
Providers: config.Providers,
Models: config.Models,
ToolFilterPrecedence: toolFilter.ToolFilterPrecedence);

var rpcTimestamp = Stopwatch.GetTimestamp();
Expand Down Expand Up @@ -1207,6 +1209,8 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
ExtensionSdkPath: config.ExtensionSdkPath,
ExtensionInfo: config.ExtensionInfo,
OpenCanvases: config.OpenCanvases,
Providers: config.Providers,
Models: config.Models,
ToolFilterPrecedence: toolFilter.ToolFilterPrecedence);

var rpcTimestamp = Stopwatch.GetTimestamp();
Expand Down Expand Up @@ -2402,6 +2406,8 @@ internal record CreateSessionRequest(
bool? RequestExtensions = null,
string? ExtensionSdkPath = null,
ExtensionInfo? ExtensionInfo = null,
IList<NamedProviderConfig>? Providers = null,
IList<ProviderModelConfig>? Models = null,
OptionsUpdateToolFilterPrecedence? ToolFilterPrecedence = null);
#pragma warning restore GHCP001

Expand Down Expand Up @@ -2494,6 +2500,8 @@ internal record ResumeSessionRequest(
string? ExtensionSdkPath = null,
ExtensionInfo? ExtensionInfo = null,
IList<OpenCanvasInstance>? OpenCanvases = null,
IList<NamedProviderConfig>? Providers = null,
IList<ProviderModelConfig>? Models = null,
OptionsUpdateToolFilterPrecedence? ToolFilterPrecedence = null);
#pragma warning restore GHCP001

Expand Down Expand Up @@ -2569,6 +2577,8 @@ internal record HooksInvokeResponse(
[JsonSerializable(typeof(EmbeddingCacheStorageMode))]
[JsonSerializable(typeof(ModelCapabilitiesOverride))]
[JsonSerializable(typeof(ProviderConfig))]
[JsonSerializable(typeof(NamedProviderConfig))]
[JsonSerializable(typeof(ProviderModelConfig))]
[JsonSerializable(typeof(ResumeSessionRequest))]
[JsonSerializable(typeof(ResumeSessionResponse))]
[JsonSerializable(typeof(SessionCapabilities))]
Expand Down
146 changes: 146 additions & 0 deletions dotnet/src/Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2070,6 +2070,135 @@ public sealed class AzureOptions
public string? ApiVersion { get; set; }
}

/// <summary>
/// A named BYOK provider connection (transport + credentials only), referenced by
/// <see cref="ProviderModelConfig"/> entries via <see cref="Name"/>.
/// <para>
/// Unlike the singular, whole-session <see cref="ProviderConfig"/> — which bypasses
/// Copilot API authentication — named providers are additive and coexist with Copilot
/// API auth, so models from CAPI and one or more BYOK providers can be mixed within a
/// single session and across sub-agents. Combining named providers/models with
/// <see cref="SessionConfigBase.Provider"/> is rejected.
/// </para>
/// </summary>
[Experimental(Diagnostics.Experimental)]
public sealed class NamedProviderConfig
{
/// <summary>
/// Stable identifier referenced by <see cref="ProviderModelConfig.Provider"/>.
/// Must not contain '/'.
/// </summary>
[JsonPropertyName("name")]
public string Name { get; set; } = string.Empty;

/// <summary>
/// Provider type. Defaults to "openai" for generic OpenAI-compatible APIs.
/// </summary>
[JsonPropertyName("type")]
public string? Type { get; set; }

/// <summary>
/// Wire API format (openai/azure only). Defaults to "completions".
/// </summary>
[JsonPropertyName("wireApi")]
public string? WireApi { get; set; }

/// <summary>
/// API endpoint URL.
/// </summary>
[JsonPropertyName("baseUrl")]
public string BaseUrl { get; set; } = string.Empty;

/// <summary>
/// API key. Optional for local providers like Ollama.
/// </summary>
[JsonPropertyName("apiKey")]
public string? ApiKey { get; set; }

/// <summary>
/// Bearer token for authentication. Sets the Authorization header directly.
/// Takes precedence over <see cref="ApiKey"/> when both are set.
/// </summary>
[JsonPropertyName("bearerToken")]
public string? BearerToken { get; set; }

/// <summary>
/// Azure-specific configuration options.
/// </summary>
[JsonPropertyName("azure")]
public AzureOptions? Azure { get; set; }

/// <summary>
/// Custom HTTP headers to include in all outbound requests to the provider.
/// </summary>
[JsonPropertyName("headers")]
public IDictionary<string, string>? Headers { get; set; }
}

/// <summary>
/// A BYOK model definition that references a <see cref="NamedProviderConfig"/> by name
/// and is added to the session's selectable model list. The session-wide selection id
/// (shown in the model list and passed to model switching) is the provider-qualified
/// <c>provider/id</c>, so BYOK ids never collide with bare CAPI ids.
/// </summary>
[Experimental(Diagnostics.Experimental)]
public sealed class ProviderModelConfig
{
/// <summary>
/// Provider-local model id, unique within its provider.
/// </summary>
[JsonPropertyName("id")]
public string Id { get; set; } = string.Empty;

/// <summary>
/// Name of the <see cref="NamedProviderConfig"/> that serves this model.
/// </summary>
[JsonPropertyName("provider")]
public string Provider { get; set; } = string.Empty;

/// <summary>
/// The model name sent to the provider API for inference. Defaults to <see cref="Id"/>.
/// </summary>
[JsonPropertyName("wireModel")]
public string? WireModel { get; set; }

/// <summary>
/// Well-known base model id used for behavior/capability/config lookup. Defaults to <see cref="Id"/>.
/// </summary>
[JsonPropertyName("modelId")]
public string? ModelId { get; set; }

/// <summary>
/// Display name for model pickers. Defaults to the provider-qualified selection id.
/// </summary>
[JsonPropertyName("name")]
public string? Name { get; set; }

/// <summary>
/// Maximum prompt/input tokens for the model.
/// </summary>
[JsonPropertyName("maxPromptTokens")]
public int? MaxPromptTokens { get; set; }

/// <summary>
/// Maximum context window tokens for the model.
/// </summary>
[JsonPropertyName("maxContextWindowTokens")]
public int? MaxContextWindowTokens { get; set; }

/// <summary>
/// Maximum output tokens for the model.
/// </summary>
[JsonPropertyName("maxOutputTokens")]
public int? MaxOutputTokens { get; set; }

/// <summary>
/// Optional capability overrides (vision, tool_calls, reasoning, etc.) for the synthesized model.
/// </summary>
[JsonPropertyName("capabilities")]
public ModelCapabilitiesOverride? Capabilities { get; set; }
}

// ============================================================================
// MCP Server Configuration Types
// ============================================================================
Expand Down Expand Up @@ -2494,6 +2623,8 @@ protected SessionConfigBase(SessionConfigBase? other)
OnPermissionRequest = other.OnPermissionRequest;
OnUserInputRequest = other.OnUserInputRequest;
Provider = other.Provider;
Providers = other.Providers is not null ? [.. other.Providers] : null;
Models = other.Models is not null ? [.. other.Models] : null;
EnableSessionTelemetry = other.EnableSessionTelemetry;
SkipCustomInstructions = other.SkipCustomInstructions;
CustomAgentsLocalOnly = other.CustomAgentsLocalOnly;
Expand Down Expand Up @@ -2649,6 +2780,21 @@ protected SessionConfigBase(SessionConfigBase? other)
/// <summary>Custom model provider configuration for the session.</summary>
public ProviderConfig? Provider { get; set; }

/// <summary>
/// Named BYOK provider connections (transport + credentials). Additive to Copilot
/// API authentication (unlike <see cref="Provider"/>); combine with <see cref="Models"/>.
/// Cannot be combined with <see cref="Provider"/>.
/// </summary>
[Experimental(Diagnostics.Experimental)]
public IList<NamedProviderConfig>? Providers { get; set; }

/// <summary>
/// BYOK model definitions added to the session's selectable model list, each
/// referencing a <see cref="Providers"/> entry by name.
/// </summary>
[Experimental(Diagnostics.Experimental)]
public IList<ProviderModelConfig>? Models { get; set; }

/// <summary>
/// Enables or disables internal session telemetry for this session.
/// When <c>false</c>, disables session telemetry. When <c>null</c> (the default) or <c>true</c>,
Expand Down
Loading
Loading