FSharp.ModelsDev 0.1.3

dotnet add package FSharp.ModelsDev --version 0.1.3
                    
NuGet\Install-Package FSharp.ModelsDev -Version 0.1.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FSharp.ModelsDev" Version="0.1.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FSharp.ModelsDev" Version="0.1.3" />
                    
Directory.Packages.props
<PackageReference Include="FSharp.ModelsDev" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FSharp.ModelsDev --version 0.1.3
                    
#r "nuget: FSharp.ModelsDev, 0.1.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FSharp.ModelsDev@0.1.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FSharp.ModelsDev&version=0.1.3
                    
Install as a Cake Addin
#tool nuget:?package=FSharp.ModelsDev&version=0.1.3
                    
Install as a Cake Tool

FSharp.ModelsDev

English | 简体中文

FSharp.ModelsDev is a .NET 8 LLM SDK written in F#. It combines native provider protocols, a compiled-in models.dev catalog, and a Microsoft.Extensions.AI adapter. The public API is usable from F# and C#.

The catalog works offline. Inference and authentication use HTTP directly; the library does not launch official CLIs or read their credential files. Applications supply credentials, browser interaction, and persistent token storage.

Install

dotnet add package FSharp.ModelsDev

The package targets net8.0. Its HTTP and JSON implementation uses .NET libraries; Microsoft.Extensions.AI.Abstractions provides the chat-client integration.

Chat

Set OPENAI_API_KEY in the application environment:

open System
open System.Threading
open FSharp.ModelsDev

let client = ChatClient.OpenAI(Environment.GetEnvironmentVariable("OPENAI_API_KEY"), "gpt-5")
let request = ChatRequest("gpt-5", [| ChatMessage.User "Explain discriminated unions in one sentence." |])
let response = client.Complete(request, CancellationToken.None).GetAwaiter().GetResult()
printfn "%s" response.Message.Text

The same API from C#:

using System;
using System.Threading;
using FSharp.ModelsDev;

var client = ChatClient.OpenAI(Environment.GetEnvironmentVariable("OPENAI_API_KEY"), "gpt-5");
var request = new ChatRequest("gpt-5", new[] { ChatMessage.User("Explain discriminated unions in one sentence.") });
var response = await client.Complete(request, CancellationToken.None);
Console.WriteLine(response.Message.Text);

Complete returns the assistant message, response ID, model, finish reason, and token usage. Optional request properties include MaxTokens, Temperature, ReasoningEffort, and ReasoningBudgetTokens; support depends on the selected backend and model.

Streaming and tools

Stream yields text deltas, tool argument deltas, usage, provider state, and a terminal event:

await foreach (var update in client.Stream(request, CancellationToken.None))
{
    if (update is TextDelta text) Console.Write(text.Text);
    if (update is Completed done) Console.WriteLine($"\n{done.FinishReason}");
}

Declare tools with ToolDefinition(name, description, parametersJson) and assign them to ChatRequest.Tools. Append the returned assistant message and ChatMessage.ToolResult(call.Id, result) to the next request, carrying the tool definitions forward. Preserve the complete assistant message, including ProviderStateJson: reasoning signatures and protected state may be required on the next turn.

Microsoft.Extensions.AI

AsIChatClient() exposes the same model through IChatClient, including streaming, function-call contents, usage, and multi-turn provider state:

open FSharp.ModelsDev.MEAi

let ask () = task {
    use ai = client.AsIChatClient()
    let messages = [| Microsoft.Extensions.AI.ChatMessage(Microsoft.Extensions.AI.ChatRole.User, "Hello") |]
    let! response = ai.GetResponseAsync(messages, null, CancellationToken.None)
    printfn "%s" response.Text
}
ask().GetAwaiter().GetResult()

Offline model selection

SnapshotCatalog queries F# data compiled from the snapshot without HTTP, credentials, a separate data download, or runtime JSON parsing. Model offerings are identified by provider and model ID; different providers may expose different limits for the same underlying model.

open FSharp.ModelsDev.Catalog

let catalog = SnapshotCatalog()
let filter =
    ModelFilter(
        RequiredInputModalities = [| "image" |],
        RequiredCapabilities = ModelCapabilities.ToolCalling,
        MinContextTokens = Nullable 131072L,
        MinOutputTokens = Nullable 8192L)

for model in ModelCatalogQuery.FindModels(catalog, filter) do
    printfn "%s/%s" model.ProviderId model.ModelId

ModelInfo exposes context, input and output token limits, input/output modalities, tool/reasoning/structured-output capabilities, attachment and temperature support, family, type, status, dates, and open-weight status. Missing numeric and Boolean metadata stays nullable; dates retain source precision. Input limits are not inferred from context minus output limits. Pricing is not currently exposed as a typed API.

FindModels searches a catalog; FilterModels applies the same conditions to an existing collection. Conditions combine with AND, identifier lists with OR, and required modalities/capabilities must all match. Strings use ordinal comparison. Unknown numeric/Boolean values do not satisfy a specified condition. Results sort by provider ID and model ID.

Catalog capabilities describe the source data; they do not establish SDK transport support or account entitlement. Account-specific discovery is a separate, explicit operation. SnapshotVersion identifies the embedded data.

Providers

Use ProviderFactory to select a backend and provide account-scoped credentials:

open FSharp.ModelsDev.Providers

let factory = ProviderFactory(catalog, ApiKeyCredentialProvider(Environment.GetEnvironmentVariable("OPENAI_API_KEY")))
let responses = factory.CreateClient("openai", "personal", "gpt-5", ProviderOptions(ProtocolId = "openai-responses"))
Provider ID Protocol Credentials
openai and compatible catalog providers openai-chat Bearer API key
openai with an explicit protocol openai-responses Bearer API key
openai-codex codex-responses Host-supplied ChatGPT access token and account header
google gemini ApiKeyCredentialProvider.Gemini(key)
anthropic anthropic-messages ApiKeyCredentialProvider.Anthropic(key)
google-vertex vertex-gemini Host-supplied Google Bearer token, project and location
google-vertex-anthropic vertex-anthropic Host-supplied Google Bearer token, project and location
antigravity antigravity Google OAuth session and Cloud Code project

ProviderOptions can override the protocol, base URL, project, location, headers, credentials, discovered model, and session ID. Use BearerTokenCredentialProvider for asynchronous host token retrieval. Client creation does not fetch credentials or discover account models.

Codex subscription endpoints require streaming HTTP. Their Complete implementation aggregates the terminal stream response, preserving tools, IDs, usage, and reasoning state. Codex sign-in and token renewal remain the host's responsibility. Ordinary Responses API completions retain non-streaming HTTP.

The offline catalog includes the antigravity provider with an empty model list. Model IDs come from the subscription: explicitly call AntigravityModelDiscovery(credentials, options).DiscoverModelsAsync(accountId) after Google OAuth login, then pass a returned descriptor as ProviderOptions.DiscoveredModel to the factory. Discovery does not modify the offline catalog or infer capabilities from model names.

Antigravity uses an unofficial Cloud Code interface. Supply GoogleOAuthOptions.ClientId and, if required by the OAuth client, ClientSecret; neither is embedded. The host can implement IOAuthTokenStore for persistence. Vertex project/location are configuration, not credentials.

Subscription authentication

ProviderAuthClient implements independent HTTP login, refresh where supported, and authenticated model discovery:

Options preset Provider ID Login
Grok() grok Browser PKCE or device code; distinct from the xai API-key service
OpenRouter() openrouter Browser PKCE or manual authorization code, yielding an API key
KimiCode(false) / KimiCode(true) kimi-code-plan-cn / kimi-code-plan-global Regional device-code OAuth
GitHubCopilot() github-copilot GitHub device OAuth and Copilot token exchange
Kilo() kilo Device authorization
ClinePass() cline-pass WorkOS device authorization and Cline registration

For example, a host can display the Kimi verification URI and user code, wait for approval, then select an authorized model:

let login () = task {
    use auth = new ProviderAuthClient(ProviderAuthOptions.KimiCode(false), InMemoryProviderAuthSessionStore())
    let ct = CancellationToken.None
    let! device = auth.BeginDeviceLoginAsync(ct)
    printfn "Open %O and enter %s" device.VerificationUri device.UserCode
    let! _ = auth.CompleteDeviceLoginAsync(device, "personal", ct)
    let! models = auth.DiscoverModelsAsync("personal", ct)
    if models.Count = 0 then invalidOp "No authorized models were returned."
    let selected = models[0] // Replace with the application's model selection.
    let factory = ProviderFactory(catalog, auth.CreateCredentialProvider())
    let model = factory.CreateClient("personal", selected)
    let! reply = model.Complete(ChatRequest(selected.ModelId, [| ChatMessage.User "Hello" |]), ct)
    printfn "%s" reply.Message.Text
}

Sessions default to memory. Implement IProviderAuthSessionStore to persist complete, rotated sessions by provider, authority, and account; keep ProviderAuthClient alive while using its credential provider. Kimi Code defaults to Messages for structured tools and thinking state. Browser flows expose BeginBrowserLoginAsync and CompleteBrowserLoginAsync so the host controls interaction.

NativeAOT

Wire JSON uses explicit Thoth.Json encoders and System.Text.Json DOM/writer APIs. Enable <PublishAot>true</PublishAot> in the host application. MEAI tool arguments and results support JSON elements, primitives, string-keyed dictionaries and arrays without reflection. For application DTOs, pass source-generated metadata with model.AsIChatClient(MyJsonContext.Default.Options), or convert the value to a JsonElement using its generated JsonTypeInfo. Register every DTO used in nested tool arguments/results. The existing parameterless adapter continues to use default JSON metadata for other types on JIT runtimes; NativeAOT requires explicit metadata for those types.

Verification

CI builds and tests on Linux and Windows, checks the catalog checksum and generated indexes, and installs the packed NuGet artifact into standalone F# and C# consumers. HTTP/SSE recordings cover provider request shapes, streaming and tool-result replay without contacting upstream services; real API tests require explicit opt-in.

Development rules, test commands, catalog maintenance, and tag-based trusted publishing are documented in AGENTS.md. Recording provenance and licensing are documented in the fixture notice.

License

MIT. Model metadata is sourced from models.dev; imported test recordings retain their upstream notices.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.3 151 11/5/2026
0.1.2 102 11/2/2026
0.1.1 116 10/17/2026
0.1.0 111 10/15/2026