FishyFlip 1.4.19

There is a newer version of this package available.
See the version list below for details.
dotnet add package FishyFlip --version 1.4.19
                    
NuGet\Install-Package FishyFlip -Version 1.4.19
                    
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="FishyFlip" Version="1.4.19" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FishyFlip" Version="1.4.19" />
                    
Directory.Packages.props
<PackageReference Include="FishyFlip" />
                    
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 FishyFlip --version 1.4.19
                    
#r "nuget: FishyFlip, 1.4.19"
                    
#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 FishyFlip@1.4.19
                    
#: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=FishyFlip&version=1.4.19
                    
Install as a Cake Addin
#tool nuget:?package=FishyFlip&version=1.4.19
                    
Install as a Cake Tool

FishyFlip - a .NET ATProtocol/Bluesky Library

NuGet Version License

FishyFlip Logo

1444070256569233

FishyFlip is an implementation of ATProtocol for .NET, forked from bluesky-net.

It is currently under construction.

For a Blazor WASM demo, check out https://drasticactions.github.io/FishyFlip

Third-Party Libraries

FishyFlip

bskycli

How To Use

  • Use ATProtocolBuilder to build a new instance of ATProtocol
// Include a ILogger if you want additional logging from the base library.
var debugLog = new DebugLoggerProvider();
var atProtocolBuilder = new ATProtocolBuilder()
    .EnableAutoRenewSession(true)
// Set the instance URL for the PDS you wish to connect to.
// Defaults to bsky.social.
    .WithInstanceUrl(new Uri("https://drasticactions.ninja"))
    .WithLogger(debugLog.CreateLogger("FishyFlipDebug"));
var atProtocol = atProtocolBuilder.Build();
  • Once created, you can now access unauthenticated APIs. For example, to get a list of posts from a user...
// Calls com.atproto.repo.listRecords for da-admin.drasticactions.ninja.
// ATHandle and ATDid are identifiers and can be used for most endpoints,
// such as for ListRecord points like below.
var listRecords = await atProtocol.Repo.ListPostAsync(ATHandle.Create("da-admin.drasticactions.ninja"));

// Each endpoint returns a Result<T>.
// This was originally taken from bluesky-net, which itself took it from OneOf.
// This is a pattern match object which can either be the "Success" object, 
// or an "Error" object. The "Error" object will always be the type of "Error" and always be from the Bluesky API.
// This would be where you would handle things like authentication errors and the like.
listRecords.Switch(
    success => { 
        foreach(var post in success!.Records)
        {
            // Prints the CID and ATURI of each post.
            Console.WriteLine($"CID: {post.Cid} Uri: {post.Uri}");
            // Value is `ATRecord`, a base type.
            // We can check if it's a Post and get its true value.
            if (post.Value is Post atPost)
            {
                Console.WriteLine(atPost.Text);
            }
        }
    },
    error =>
    {
        Console.WriteLine($"Error: {error.StatusCode} {error.Detail}");
    }
);
  • Instead of pattern matching, you can also use .HandleResult() to return the success object, and throw an exception upon an error.
var listRecords = (await atProtocol.Repo.ListPostAsync(ATHandle.Create("da-admin.drasticactions.ninja"))).HandleResult();
  • To log in, we need to create a session. This is applied to all ATProtocol calls once applied. If you need to create calls from a non-auth user session, create a new ATProtocol or destroy the existing session.
// While this accepts normal passwords, you should ask users
// to create an app password from their accounts to use it instead.
Result<Session> result = await atProtocol.Server.CreateSessionAsync(userName, password, CancellationToken.None);

result.Switch(
    success =>
    {
        // Contains the session information and tokens used internally.
        Console.WriteLine($"Session: {success.Did}");
    },
    error =>
    {
        Console.WriteLine($"Error: {error.StatusCode} {error.Detail}");
    }
);
// Creates a text post of "Hello, World!" to the signed in users account.
var postResult = await atProtocol.Repo.CreatePostAsync("Hello, World!");
postResult.Switch(
    success =>
    {
        // Contains the ATUri and CID.
        Console.WriteLine($"Post: {success.Uri} {success.Cid}");
    },
    error =>
    {
        Console.WriteLine($"Error: {error.StatusCode} {error.Detail}");
    }
);
  • To upload an image, you need to first upload it as a blob, and then attach it to a post. You can also embed links in text by setting a "Link" Facet.
var stream = File.OpenRead("path/to/image.png");
var content = new StreamContent(stream);
content.Headers.ContentLength = stream.Length;
// Bluesky uses the content type header for setting the blob type.
// As of this writing, it does not verify what kind of blob gets uploaded.
// But you should be careful about setting generic types or using the wrong one.
// If you do not set a type, it will return an error.
content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
var blobResult = await atProtocol.Repo.UploadBlobAsync(content);
await blobResult.SwitchAsync(
       async success =>
       {
           // Blob is uploaded.
           Console.WriteLine($"Blob: {success.Blob.Type}");
           // Converts the blob to an image.
           Image? image = success.Blob.ToImage();

           var prompt = "Hello, Image! Link Goes Here!";

           // To insert a link, we need to find the start and end of the link text.
           // This is done as a "ByteSlice."
           int promptStart = prompt.IndexOf("Link Goes Here!", StringComparison.InvariantCulture);
           int promptEnd = promptStart + Encoding.Default.GetBytes("Link Goes Here!").Length;
           var index = new FacetIndex(promptStart, promptEnd);
           var link = FacetFeature.CreateLink("https://drasticactions.dev");
           var facet = new Facet(index, link);

           // Create a post with the image and the link.
           var postResult = await atProtocol.Repo.CreatePostAsync(prompt, new[] { facet }, new ImagesEmbed(image, "Optional Alt Text, you should have your users set this when possible"));
       },
       async error =>
       {
            Console.WriteLine($"Error: {error.StatusCode} {error.Detail}");
       }
);

You should then see your image and link.

Post Sample

  • You can access the "Firehose" by using SubscribeRepos. This can be seen in the FishyFlip.Firehose sample. SubscribeRepos uses Websockets to connect to a given instead and get messages whenever a new one is posted. Messages need to be handled outside of the general WebSocket stream; if anything blocks the stream from returning messages, you may see errors from the protocol saying your connection is too slow.
var debugLog = new DebugLoggerProvider();
var atProtocolBuilder = new ATWebSocketProtocolBuilder()
// Defaults to bsky.network.
    .WithInstanceUrl(new Uri("https://drasticactions.ninja"))
    .WithLogger(debugLog.CreateLogger("FishyFlipDebug"));
var atProtocol = atProtocolBuilder.Build();

atProtocol.OnSubscribedRepoMessage += (sender, args) =>
{
    Task.Run(() => HandleMessageAsync(args.Message)).FireAndForgetSafeAsync();
};

await atProtocol.StartSubscribeReposAsync();

var key = Console.ReadKey();

await atProtocol.StopSubscriptionAsync();

async Task HandleMessageAsync(SubscribeRepoMessage message)
{
    if (message.Commit is null)
    {
        return;
    }

    var orgId = message.Commit.Repo;

    if (orgId is null)
    {
        return;
    }

    if (message.Record is not null)
    {
        Console.WriteLine($"Record: {message.Record.Type}");
    }
}
  • Sync endpoints generally encode their output as IPFS Car files. Here, we can process them as they are streaming so instead of needing to download a whole file to process it, we can do it as it is downloading. This is done by using the OnCarDecoded delegate.
var debugLog = new DebugLoggerProvider();
var atProtocolBuilder = new ATProtocolBuilder()
    .EnableAutoRenewSession(true)
    .WithInstanceUrl(new Uri("https://drasticactions.ninja"))
    .WithLogger(debugLog.CreateLogger("FishyFlipDebug"));
var atProtocol = atProtocolBuilder.Build();

var checkoutResult = await atProtocol.Sync.GetCheckoutAsync(ATDid.Create("did:plc:yhgc5rlqhoezrx6fbawajxlh"), HandleProgressStatus);

async void HandleProgressStatus(CarProgressStatusEvent e)
{
    var cid = e.Cid;
    var bytes = e.Bytes;
    var test = CBORObject.DecodeFromBytes(bytes);
    var record = ATRecord.FromCBORObject(test);
    // Prints the type of the record.
    Console.WriteLine(record?.Type);
}

For more samples, check the apps, samples, and website directory.

Endpoints

As a general rule of thumb, com.atproto endpoints (such as com.atproto.sync) do not require authentication, where app.bsky ones do.

❌ - Not Implemented ⚠️ - Partial support, untested ✅ - Should be "working"

Sync

Endpoint Implemented
com.atproto.sync.getHead
com.atproto.sync.getBlob
com.atproto.sync.getRepo
com.atproto.sync.notifyOfUpdate
com.atproto.sync.requestCrawl
com.atproto.sync.listBlobs
com.atproto.sync.getLatestCommit
com.atproto.sync.subscribeRepos
com.atproto.sync.getRecord
com.atproto.sync.listRepos
com.atproto.sync.getBlocks
com.atproto.sync.getCheckout

Actor

Endpoint Implemented
app.bsky.actor.searchActorsTypeahead
app.bsky.actor.putPreferences
app.bsky.actor.getProfile
app.bsky.actor.getSuggestions
app.bsky.actor.searchActors
app.bsky.actor.getProfiles
app.bsky.actor.getPreferences

Feed

Endpoint Implemented
app.bsky.feed.getFeedGenerators
app.bsky.feed.getTimeline
app.bsky.feed.getFeedGenerator
app.bsky.feed.getAuthorFeed
app.bsky.feed.getLikes
app.bsky.feed.getPostThread
app.bsky.feed.getActorLikes
app.bsky.feed.getRepostedBy
app.bsky.feed.describeFeedGenerator
app.bsky.feed.searchPosts
app.bsky.feed.getPosts
app.bsky.feed.getFeed
app.bsky.feed.getFeedSkeleton
app.bsky.feed.getListFeed
app.bsky.feed.getSuggestedFeeds
app.bsky.feed.getActorFeeds

Graph

Endpoint Implemented
app.bsky.graph.getSuggestedFollowsByActor
app.bsky.graph.unmuteActorList
app.bsky.graph.getListBlocks
app.bsky.graph.muteActorList
app.bsky.graph.getLists
app.bsky.graph.getFollowers
app.bsky.graph.muteActor
app.bsky.graph.getMutes
app.bsky.graph.getListMutes
app.bsky.graph.getFollows
app.bsky.graph.getBlocks
app.bsky.graph.unmuteActor
app.bsky.graph.getList

Notification

Endpoint Implemented
app.bsky.notification.registerPush
app.bsky.notification.updateSeen
app.bsky.notification.listNotifications
app.bsky.notification.getUnreadCount

Server

Endpoint Implemented
com.atproto.server.requestEmailConfirmation
com.atproto.server.reserveSigningKey
com.atproto.server.getAccountInviteCodes
com.atproto.server.createSession
com.atproto.server.listAppPasswords
com.atproto.server.createInviteCodes
com.atproto.server.deleteSession
com.atproto.server.revokeAppPassword
com.atproto.server.createAppPassword
com.atproto.server.describeServer
com.atproto.server.confirmEmail
com.atproto.server.getSession
com.atproto.server.refreshSession
com.atproto.server.updateEmail
com.atproto.server.resetPassword
com.atproto.server.requestEmailUpdate
com.atproto.server.requestPasswordReset
com.atproto.server.requestAccountDelete
com.atproto.server.createAccount
com.atproto.server.deleteAccount
com.atproto.server.createInviteCode

Repo

Endpoint Implemented
com.atproto.repo.createRecord
com.atproto.repo.deleteRecord
com.atproto.repo.putRecord
com.atproto.repo.uploadBlob
com.atproto.repo.describeRepo
com.atproto.repo.getRecord
com.atproto.repo.applyWrites
com.atproto.repo.listRecords

Moderation

Endpoint Implemented
com.atproto.moderation.createReport

Labels

Endpoint Implemented
com.atproto.label.subscribeLabels ⚠️
com.atproto.label.queryLabels ⚠️

Identity

Endpoint Implemented
com.atproto.identity.updateHandle
com.atproto.identity.resolveHandle

Admin

Endpoint Implemented
com.atproto.admin.getRepo
com.atproto.admin.updateAccountEmail
com.atproto.admin.getAccountInfo
com.atproto.admin.getSubjectStatus
com.atproto.admin.queryModerationStatuses
com.atproto.admin.updateAccountHandle
com.atproto.admin.getInviteCodes
com.atproto.admin.enableAccountInvites
com.atproto.admin.disableAccountInvites
com.atproto.admin.disableInviteCodes
com.atproto.admin.updateSubjectStatus
com.atproto.admin.emitModerationEvent
com.atproto.admin.getModerationEvent
com.atproto.admin.getRecord
com.atproto.admin.queryModerationEvents
com.atproto.admin.sendEmail
com.atproto.admin.searchRepos
com.atproto.admin.getAccountInfos
com.atproto.admin.deleteAccount

Unspecced

Endpoint Implemented
app.bsky.unspecced.searchActorsSkeleton
app.bsky.unspecced.searchPostsSkeleton
app.bsky.unspecced.getPopularFeedGenerators
app.bsky.unspecced.getTimelineSkeleton

Temp

Endpoint Implemented
com.atproto.temp.transferAccount
com.atproto.temp.pushBlob
com.atproto.temp.importRepo
com.atproto.temp.fetchLabels

Why "FishyFlip?"

"FishyFlip" is a reference to the Your Kickstarter Sucks episode of the same name.

Discord Image

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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 (7)

Showing the top 5 NuGet packages that depend on FishyFlip:

Package Downloads
FishyFlip.Xrpc

Implement ASP.NET XRPC endpoints for Bluesky and other ATProtocol apps.

WhiteWindLib

Access WhiteWind through .NET.

Resonance.SDK

SDK for integrating applications with the Resonance federation network. Now includes Discord OAuth authentication for seamless user management.

Presence.Posting.Lib

Presence is a set of .NET libraries and tools for social sharing. Presence.Posting.Lib submits posts and threads to social networks.

FishyFlip.AspNetCore

ASP.NET Core integration for FishyFlip - ATProtocol/Bluesky library

GitHub repositories (4)

Showing the top 4 popular GitHub repositories that depend on FishyFlip:

Repository Stars
FireCubeStudios/DarkSky
BlueSky client for Windows 10/11
alnkesq/AppViewLite
A Bluesky appview focused on low resource consumption
Doofus-Mc-Goofus/LonghornBluesky
Third-party Bluesky client designed with a Windows Longhorn-like aesthetic.
FritzAndFriends/TagzApp
An application that discovers content on social media for hashtags
Version Downloads Last Updated
4.1.0-alpha.7 113 9/12/2025
4.1.0-alpha.5 134 9/9/2025
4.1.0-alpha.4 167 8/29/2025
4.1.0-alpha.2 94 8/22/2025
4.1.0-alpha.1 113 8/21/2025
3.11.0 332 8/21/2025
3.11.0-alpha.16 108 8/21/2025
3.11.0-alpha.15 124 8/12/2025
3.11.0-alpha.13 128 8/4/2025
3.11.0-alpha.12 96 7/27/2025
3.11.0-alpha.11 342 7/25/2025
3.11.0-alpha.9 514 7/23/2025
3.11.0-alpha.8 499 7/22/2025
3.11.0-alpha.7 113 7/16/2025
3.11.0-alpha.6 115 7/14/2025
3.11.0-alpha.5 100 7/11/2025
3.11.0-alpha.4 119 7/4/2025
3.11.0-alpha.3 77 6/27/2025
3.11.0-alpha.2 87 6/21/2025
3.11.0-alpha.1 122 6/16/2025
3.10.0 541 6/13/2025
3.10.0-alpha.21 262 6/13/2025
3.10.0-alpha.20 183 6/8/2025
3.10.0-alpha.19 130 6/5/2025
3.10.0-alpha.18 121 6/4/2025
3.10.0-alpha.17 127 6/3/2025
3.10.0-alpha.16 104 5/30/2025
3.10.0-alpha.15 132 5/28/2025
3.10.0-alpha.14 109 5/23/2025
3.10.0-alpha.13 126 5/22/2025
3.10.0-alpha.12 130 5/21/2025
3.10.0-alpha.11 132 5/18/2025
3.10.0-alpha.10 209 5/12/2025
3.10.0-alpha.9 122 5/11/2025
3.10.0-alpha.8 74 5/9/2025
3.10.0-alpha.7 132 5/9/2025
3.10.0-alpha.6 127 5/8/2025
3.10.0-alpha.5 228 5/7/2025
3.10.0-alpha.4 125 5/6/2025
3.10.0-alpha.3 434 5/4/2025
3.10.0-alpha.2 146 5/1/2025
3.10.0-alpha.1 121 4/25/2025
3.9.0 397 4/22/2025
3.9.0-alpha.5 148 4/22/2025
3.9.0-alpha.4 161 4/21/2025
3.9.0-alpha.3 174 4/18/2025
3.9.0-alpha.2 170 4/17/2025
3.9.0-alpha.1 185 4/16/2025
3.8.0 350 4/11/2025
3.8.0-alpha.2 135 4/11/2025
3.7.0 301 4/9/2025
3.7.0-alpha.3 158 4/9/2025
3.7.0-alpha.2 160 4/7/2025
3.7.0-alpha.1 148 4/3/2025
3.6.0 324 3/30/2025
3.6.0-alpha.8 142 3/19/2025
3.6.0-alpha.7 127 3/14/2025
3.6.0-alpha.6 150 3/12/2025
3.6.0-alpha.5 119 3/9/2025
3.6.0-alpha.4 206 3/6/2025
3.6.0-alpha.3 196 3/5/2025
3.6.0-alpha.2 210 3/5/2025
3.6.0-alpha.1 200 3/5/2025
3.5.4 194 3/29/2025
3.5.3 451 3/20/2025
3.5.2 481 3/5/2025
3.5.1 368 3/5/2025
3.5.0-alpha.19 196 3/4/2025
3.5.0-alpha.18 96 3/2/2025
3.5.0-alpha.17 108 2/27/2025
3.5.0-alpha.16 91 2/26/2025
3.5.0-alpha.15 99 2/25/2025
3.5.0-alpha.14 99 2/24/2025
3.5.0-alpha.13 111 2/23/2025
3.5.0-alpha.12 98 2/23/2025
3.5.0-alpha.11 94 2/22/2025
3.5.0-alpha.10 96 2/22/2025
3.5.0-alpha.9 91 2/22/2025
3.5.0-alpha.8 94 2/21/2025
3.5.0-alpha.7 100 2/21/2025
3.5.0-alpha.6 84 2/20/2025
3.5.0-alpha.5 100 2/19/2025
3.5.0-alpha.4 95 2/17/2025
3.5.0-alpha.3 398 2/9/2025
3.5.0-alpha.2 94 2/8/2025
3.5.0-alpha.1 104 2/8/2025
3.4.1 761 2/10/2025
3.4.0 204 2/6/2025
3.4.0-alpha.21 90 2/6/2025
3.4.0-alpha.20 102 2/2/2025
3.4.0-alpha.19 111 2/2/2025
3.4.0-alpha.18 101 1/31/2025
3.4.0-alpha.17 95 1/30/2025
3.4.0-alpha.16 83 1/29/2025
3.4.0-alpha.15 92 1/29/2025
3.4.0-alpha.14 107 1/28/2025
3.4.0-alpha.13 93 1/28/2025
3.4.0-alpha.12 89 1/27/2025
3.4.0-alpha.11 106 1/25/2025
3.4.0-alpha.10 82 1/24/2025
3.4.0-alpha.9 278 1/22/2025
3.4.0-alpha.8 85 1/22/2025
3.4.0-alpha.7 91 1/20/2025
3.4.0-alpha.6 80 1/19/2025
3.4.0-alpha.5 88 1/18/2025
3.4.0-alpha.4 73 1/18/2025
3.4.0-alpha.3 83 1/18/2025
3.4.0-alpha.2 89 1/18/2025
3.4.0-alpha.1 94 1/16/2025
3.4.0-alpha.0 74 1/15/2025
3.3.2 434 1/20/2025
3.3.1 251 1/17/2025
3.3.0-alpha.4 98 1/13/2025
3.3.0-alpha.3 81 1/13/2025
3.3.0-alpha.2 95 1/13/2025
3.3.0-alpha.1 113 1/11/2025
3.2.2 281 1/13/2025
3.2.1 191 1/10/2025
3.2.0-alpha.11 77 1/10/2025
3.2.0-alpha.9 87 1/9/2025
3.2.0-alpha.8 113 1/6/2025
3.2.0-alpha.7 93 1/6/2025
3.2.0-alpha.6 585 1/5/2025
3.2.0-alpha.5 118 1/4/2025
3.2.0-alpha.4 226 1/3/2025
3.2.0-alpha.3 115 1/3/2025
3.2.0-alpha.2 99 12/30/2024
3.2.0-alpha.1 94 12/27/2024
3.1.2 554 12/27/2024
3.1.0-alpha.28 251 12/26/2024
3.1.0-alpha.27 152 12/24/2024
3.1.0-alpha.26 123 12/24/2024
3.1.0-alpha.25 107 12/24/2024
3.1.0-alpha.24 114 12/23/2024
3.1.0-alpha.23 158 12/21/2024
3.1.0-alpha.22 104 12/21/2024
3.1.0-alpha.21 105 12/19/2024
3.1.0-alpha.20 115 12/17/2024
3.1.0-alpha.19 98 12/17/2024
3.1.0-alpha.18 91 12/17/2024
3.1.0-alpha.17 208 12/16/2024
3.1.0-alpha.16 119 12/15/2024
3.1.0-alpha.15 148 12/14/2024
3.1.0-alpha.14 173 12/13/2024
3.1.0-alpha.13 407 12/12/2024
3.1.0-alpha.12 185 12/9/2024
3.1.0-alpha.11 106 12/8/2024
3.1.0-alpha.10 90 12/7/2024
3.1.0-alpha.9 187 12/6/2024
3.1.0-alpha.8 108 12/5/2024
3.1.0-alpha.7 244 12/2/2024
3.1.0-alpha.6 127 11/28/2024
3.1.0-alpha.5 81 11/27/2024
3.1.0-alpha.4 94 11/25/2024
3.1.0-alpha.3 139 11/24/2024
3.1.0-alpha.2 110 11/24/2024
3.1.0-alpha.1 82 11/23/2024
3.1.0-alpha.0 143 11/22/2024
2.2.0-alpha.71 94 11/22/2024
2.2.0-alpha.67 72 11/22/2024
2.2.0-alpha.64 113 11/21/2024
2.2.0-alpha.57 72 11/21/2024
2.2.0-alpha.55 68 11/20/2024
2.2.0-alpha.50 77 11/19/2024
2.2.0-alpha.38 112 11/17/2024
2.2.0-alpha.37 80 11/17/2024
2.2.0-alpha.11 81 11/17/2024
2.2.0-alpha.9 74 11/17/2024
2.2.0-alpha.6 93 11/13/2024
2.2.0-alpha.4 106 11/11/2024
2.2.0-alpha.2 120 11/5/2024
2.1.1 1,180 11/5/2024
2.1.0 148 11/4/2024
2.1.0-alpha.23 107 11/1/2024
2.1.0-alpha.22 84 10/31/2024
2.1.0-alpha.21 89 10/31/2024
2.1.0-alpha.20 87 10/29/2024
2.1.0-alpha.19 107 10/28/2024
2.0.0 464 10/19/2024
2.0.0-alpha.53 146 10/13/2024
2.0.0-alpha.45 98 9/27/2024
1.9.0-alpha.38 95 9/13/2024
1.8.80 315 9/12/2024
1.8.78 160 9/8/2024
1.8.39-alpha 122 6/2/2024
1.7.56 696 3/18/2024
1.7.43-alpha 242 2/24/2024
1.7.31-alpha 254 2/14/2024
1.7.12-alpha 270 2/8/2024
1.6.16 1,096 2/7/2024
1.5.25 342 1/17/2024
1.4.19 339 1/15/2024
1.4.16 304 1/15/2024
1.3.11 319 1/9/2024
1.2.1 732 11/22/2023
1.1.62-alpha 358 11/6/2023
1.1.59-alpha 366 11/6/2023
1.1.54-alpha 381 10/16/2023
1.1.52-alpha 392 10/13/2023
1.1.49-alpha 543 9/22/2023
1.1.45-alpha 487 8/9/2023
1.1.35-alpha 592 7/28/2023
1.1.33-alpha 419 7/26/2023
1.1.18-alpha 393 7/15/2023