Skip to content

feat(dotnet): add Hashbrown.DotNet ASP.NET Core adapter#466

Open
boomerman wants to merge 1 commit intoliveloveapp:mainfrom
boomerman:feat/dotnet-package
Open

feat(dotnet): add Hashbrown.DotNet ASP.NET Core adapter#466
boomerman wants to merge 1 commit intoliveloveapp:mainfrom
boomerman:feat/dotnet-package

Conversation

@boomerman
Copy link

Introduces a new .NET package that exposes a streaming ASP.NET Core endpoint compatible with Hashbrown React and Angular clients.

  • Add MapHashbrownAgent() minimal API extension for one-line endpoint registration
  • Add AddHashbrown() DI extension that registers IHashbrownAgentService
  • Implement HashbrownAgentService with generate and load-thread operations
  • Implement FrameEncoder with big-endian length-prefix binary framing
  • Add CompletionCreateParams, Message, Frame, and related models
  • Support tool calling via AIFunctionFactory.CreateDeclaration
  • Support structured output via ChatResponseFormat.ForJsonSchema
  • Add HashbrownSample demonstrating Azure OpenAI integration
  • Add unit tests for FrameEncoder, models, DI extensions, and service
  • Add comprehensive README with integration guide

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

[ ] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] Other... Please describe:

What is the current behavior?

Closes #

What is the new behavior?

Does this PR introduce a breaking change?

[ ] Yes
[ ] No

Other information

Introduces a new .NET package that exposes a streaming ASP.NET Core
endpoint compatible with Hashbrown React and Angular clients.

- Add MapHashbrownAgent() minimal API extension for one-line endpoint registration
- Add AddHashbrown() DI extension that registers IHashbrownAgentService
- Implement HashbrownAgentService with generate and load-thread operations
- Implement FrameEncoder with big-endian length-prefix binary framing
- Add CompletionCreateParams, Message, Frame, and related models
- Support tool calling via AIFunctionFactory.CreateDeclaration
- Support structured output via ChatResponseFormat.ForJsonSchema
- Add HashbrownSample demonstrating Azure OpenAI integration
- Add unit tests for FrameEncoder, models, DI extensions, and service
- Add comprehensive README with integration guide
@nx-cloud
Copy link

nx-cloud bot commented Feb 20, 2026

View your CI Pipeline Execution ↗ for commit ddd5255

Command Status Duration Result
nx affected -t lint,test,build --parallel=3 ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-02-20 09:20:29 UTC

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ddd525537b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +49 to +50
var invokingContext = new InvokingContext(agent, null!, null!);
IEnumerable<ChatMessage> messages = await messageStore.InvokingAsync(invokingContext, cancellationToken);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Pass requested thread ID into thread loading

This path validates that request.ThreadId is present, but the actual load call never uses it and instead constructs InvokingContext with null! values. In any provider that stores multiple threads, load-thread cannot reliably fetch the caller’s thread and may return incorrect history (or fail if the provider expects non-null context metadata). Thread loading should be keyed by the requested thread id.

Useful? React with 👍 / 👎.

Comment on lines +83 to +87
List<ChatMessage> conversation = new();

// Build conversation from request messages
foreach (var msg in request.Messages)
{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Load persisted context before generate with threadId

Generation builds conversation only from request.Messages and never hydrates prior messages from messageStore when request.ThreadId is set. In Hashbrown’s threaded flow, follow-up generate calls typically send only message deltas (see generateMessage in packages/core/src/effects/generate-message.effects.ts), so skipping server-side load drops prior context and breaks conversation continuity.

Useful? React with 👍 / 👎.

Comment on lines +274 to +278
await WriteFrame(context, new Frame
{
Type = "thread-save-success",
ThreadId = threadId
}, cancellationToken);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Persist thread before sending thread-save-success

When messageStore is configured, this block emits thread-save-start and then immediately reports thread-save-success without calling any persistence API, so clients are told the thread was saved even though no data was written. Subsequent load-thread requests can return stale or empty history despite a success frame.

Useful? React with 👍 / 👎.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants