Incursa.OpenAI.ChatKit.AspNetCore
3.0.5
dotnet add package Incursa.OpenAI.ChatKit.AspNetCore --version 3.0.5
NuGet\Install-Package Incursa.OpenAI.ChatKit.AspNetCore -Version 3.0.5
<PackageReference Include="Incursa.OpenAI.ChatKit.AspNetCore" Version="3.0.5" />
<PackageVersion Include="Incursa.OpenAI.ChatKit.AspNetCore" Version="3.0.5" />
<PackageReference Include="Incursa.OpenAI.ChatKit.AspNetCore" />
paket add Incursa.OpenAI.ChatKit.AspNetCore --version 3.0.5
#r "nuget: Incursa.OpenAI.ChatKit.AspNetCore, 3.0.5"
#:package Incursa.OpenAI.ChatKit.AspNetCore@3.0.5
#addin nuget:?package=Incursa.OpenAI.ChatKit.AspNetCore&version=3.0.5
#tool nuget:?package=Incursa.OpenAI.ChatKit.AspNetCore&version=3.0.5
Incursa.OpenAI.ChatKit.AspNetCore
Incursa.OpenAI.ChatKit.AspNetCore is the ASP.NET Core integration package for Incursa.OpenAI.ChatKit.
It adds:
MapChatKit<TServer, TContext>(...)for HTTP and SSE endpoint handlingAddOpenAIChatKitApi(...)andAddOpenAIChatKitHosted(...)for explicit frontend hosting modes- Razor tag helpers for mounting the ChatKit frontend from MVC or Razor views
- packaged CSS and JavaScript assets under
_content/Incursa.OpenAI.ChatKit.AspNetCore/chatkit - a thin vanilla-JS bootstrap around the upstream
<openai-chatkit>web component - options for shared UI defaults across a site or application
Install
Use this package together with the core runtime package:
dotnet add package Incursa.OpenAI.ChatKit
dotnet add package Incursa.OpenAI.ChatKit.AspNetCore
What this package is for
- exposing a ChatKit-compatible endpoint from ASP.NET Core
- rendering the ChatKit frontend from Razor layouts, pages, or views
- shipping a repo-managed browser runtime without hand-written page bootstrapping
What this package is not for
- replacing the core
Incursa.OpenAI.ChatKitruntime - generating ChatKit UI assets during normal
dotnet build - forcing a specific MVC or Razor Pages structure on your app
Endpoint mapping
Register your server and map the ChatKit endpoint:
using Incursa.OpenAI.ChatKit;
using Incursa.OpenAI.ChatKit.AspNetCore;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<DemoChatKitServer>();
WebApplication app = builder.Build();
app.MapChatKit<DemoChatKitServer, Dictionary<string, object?>>(
"/chatkit",
_ => new Dictionary<string, object?>());
app.Run();
Razor UI wrapper
Register shared UI defaults for a custom ChatKit API endpoint:
builder.Services.AddOpenAIChatKitApi("/api/chatkit", "contoso-domain-key", configure: options =>
{
options.DefaultHeight = "760px";
options.StartScreen.Greeting = "How can I help today?";
options.Theme.ColorScheme = "dark";
options.Theme.Typography.BaseSize = 16;
options.Theme.Color.Accent.Primary = "#8B5CF6";
options.Header.LeftAction = new ChatKitHeaderActionOptions
{
Icon = "sidebar-left",
OnClickHandler = "window.chatkit.onHeaderAction",
};
options.Disclaimer.Text = "AI may make mistakes. Verify important details.";
options.Disclaimer.HighContrast = true;
options.EntityHandlers = "window.chatkitEntities";
options.Entities.ShowComposerMenu = true;
});
Then use the tag helpers from a layout or view:
@addTagHelper *, Incursa.OpenAI.ChatKit.AspNetCore
<incursa-chatkit-assets />
<incursa-chatkit-api
id="workspace-assistant"
class="chatkit-page"
api-url="/api/chatkit"
domain-key="contoso-domain-key"
theme-base-size="16"
theme-color-accent-primary="#8B5CF6"
header-left-action-icon="sidebar-left"
header-left-action-handler="window.chatkit.onHeaderAction"
disclaimer-text="AI may make mistakes. Verify important details."
disclaimer-high-contrast="true">
</incursa-chatkit-api>
Use <incursa-chatkit-api> when your application maps a custom ChatKit endpoint with MapChatKit(...). This is the explicit wrapper for self-hosted or custom API integrations.
For example, if your app maps a protected ChatKit endpoint at /api/chatkit, keep that route on the server side:
app.MapChatKit<MyChatKitServer, MyChatKitContext>(
"/api/chatkit",
MyChatKitContext.FromHttpContext)
.RequireAuthorization();
Then point the Razor host at that API endpoint:
<incursa-chatkit-api
api-url="/api/chatkit"
domain-key="contoso-domain-key" />
Direct API mode requires a domain key. Configure it either in AddOpenAIChatKitApi(...) or on the <incursa-chatkit-api> tag helper.
The wrapper also mirrors the richer upstream theme and header options:
theme-base-size,theme-font-family, andtheme-font-family-monotheme-color-grayscale-*,theme-color-accent-*, andtheme-color-surface-*header-left-action-*andheader-right-action-*for callback-backed header buttons
For start-screen prompts, the wrapper accepts either plain text or rich UserMessageContent[] values through the .NET options model.
Client tool handlers
To expose ChatKit onClientTool through the Razor wrapper, register a browser-side object whose keys match your server-side ClientToolCall.name values, then point the tag helper at that object:
<script>
window.chatkitClientTools = {
async get_selected_canvas_nodes({ name, params }) {
const nodes = myCanvas.getSelectedNodes(params.project);
return {
nodes: nodes.map((node) => ({ id: node.id, kind: node.type }))
};
}
};
</script>
<incursa-chatkit-assets />
<incursa-chatkit-api
api-url="/api/chatkit"
domain-key="contoso-domain-key"
client-tool-handlers="window.chatkitClientTools">
</incursa-chatkit-api>
client-tool-handlers accepts a dotted browser lookup path such as window.chatkitClientTools or app.chatkit.clientTools. Each resolved handler receives the upstream ChatKit tool-call object { name, params } and must return JSON-compatible data. If the lookup path or named tool handler is missing, the packaged runtime throws a clear browser error instead of silently ignoring the tool call.
Composer configuration
The wrapper can also project ChatKit composer attachments, tool pickers, model pickers, dictation, and custom upload strategies from AddOpenAIChatKitApi(...) or AddOpenAIChatKitHosted(...):
builder.Services.AddOpenAIChatKitApi("/api/chatkit", "contoso-domain-key", options =>
{
options.Composer.Attachments.Enabled = true;
options.Composer.Attachments.MaxCount = 10;
options.Composer.Attachments.MaxSize = 100 * 1024 * 1024;
options.Composer.Tools.Add(new ChatKitComposerTool
{
Id = "summarize",
Label = "Summarize",
Icon = "book-open",
});
options.Composer.Models.Add(new ChatKitComposerModel
{
Id = "gpt-4.1",
Label = "Quality",
Description = "Higher-quality responses",
Default = true,
});
options.Composer.Dictation.Enabled = true;
options.UploadStrategy.Type = "direct";
options.UploadStrategy.UploadUrl = "/files";
});
<incursa-chatkit-api
api-url="/api/chatkit"
domain-key="contoso-domain-key"
composer-attachments-enabled="true"
composer-attachments-max-count="10"
composer-dictation-enabled="true"
upload-strategy-type="direct"
upload-strategy-upload-url="/files">
</incursa-chatkit-api>
composer.attachments is omitted unless attachments are configured. When enabled, the runtime forwards the attachment limits and accepted file type map into useChatKit(...). composer.tools, composer.models, and composer.dictation are serialized from the .NET options model without any browser-side patching.
Entity handlers
To expose ChatKit entities through the Razor wrapper, register a browser-side object with the upstream callback names and point the tag helper at that registry:
<script>
window.chatkitEntities = {
async onTagSearch(query) {
return searchDocuments(query).map((document) => ({
id: document.id,
title: document.title,
group: "Documents",
icon: "document",
interactive: true,
data: {
source: "document"
}
}));
},
onClick(entity) {
openDocument(entity.id);
},
async onRequestPreview(entity) {
return {
preview: buildEntityPreview(entity)
};
}
};
</script>
<incursa-chatkit-assets />
<incursa-chatkit-api
api-url="/api/chatkit"
domain-key="contoso-domain-key"
entity-handlers="window.chatkitEntities"
entity-show-composer-menu="true">
</incursa-chatkit-api>
entity-handlers accepts a dotted browser lookup path such as window.chatkitEntities or app.chatkit.entityHandlers. The runtime looks for optional onTagSearch(query), onClick(entity), and onRequestPreview(entity) functions on that object and validates the returned entity list and preview payload shape before passing them to ChatKit.
When the user submits tagged content, the core server receives UserMessageTagContent entries alongside regular text content. That lets you convert upstream @ tags directly into your server-side domain model:
using System.Text.Json.Nodes;
using Incursa.OpenAI.ChatKit;
IReadOnlyList<UserMessageTagContent> tags = input.Content
.OfType<UserMessageTagContent>()
.ToList();
foreach (UserMessageTagContent tag in tags)
{
string? source = tag.Data.TryGetValue("source", out JsonNode? value)
? value?.GetValue<string>()
: null;
// Map the submitted entity tag into your own search, retrieval, or routing flow.
}
Header title
The header title area can be disabled independently from the header itself:
builder.Services.AddOpenAIChatKitHosted(options =>
{
options.Header.Enabled = true;
options.Header.TitleEnabled = false;
options.Header.TitleText = "Assistant";
});
<incursa-chatkit-hosted
session-endpoint="/api/chatkit/session"
action-endpoint="/api/chatkit/action"
header-title-enabled="false"
header-title="Assistant">
</incursa-chatkit-hosted>
Use header-title-enabled="false" when you want the header shell to remain visible but the title slot to be hidden.
OpenAI-hosted mode
If the frontend should use OpenAI-hosted ChatKit through local session and action endpoints, register hosted mode explicitly and use <incursa-chatkit-hosted>:
builder.Services.AddOpenAIChatKitHosted(options =>
{
options.SessionEndpoint = "/api/chatkit/session";
options.ActionEndpoint = "/api/chatkit/action";
});
<incursa-chatkit-assets />
<incursa-chatkit-hosted
session-endpoint="/api/chatkit/session"
action-endpoint="/api/chatkit/action">
</incursa-chatkit-hosted>
<incursa-chatkit-hosted> is the explicit wrapper for the hosted getClientSecret flow. Use it when your app issues the browser a ChatKit client secret instead of exposing a custom ChatKit API endpoint directly.
Widget actions
To expose upstream widgets.onAction through the Razor wrapper, register a browser-side function and point the tag helper at that lookup path:
<script>
window.chatkitOnWidgetAction = async (action, widgetItem) => {
if (action.type !== "save_profile") {
return;
}
await saveProfile(action.payload, widgetItem.id);
};
</script>
<incursa-chatkit-assets />
<incursa-chatkit-hosted
session-endpoint="/api/chatkit/session"
widget-action-handler="window.chatkitOnWidgetAction"
forward-widget-actions="false">
</incursa-chatkit-hosted>
widget-action-handler accepts a dotted browser lookup path such as window.chatkitOnWidgetAction or app.chatkit.widgets.onAction. The runtime resolves that function each time a widget action fires and passes the upstream (action, widgetItem) arguments unchanged.
Supported patterns:
- Server-only: omit
widget-action-handlerand keep widget forwarding enabled so actions post toaction-endpoint. - Client-only: set
widget-action-handlerand disable forwarding withforward-widget-actions="false". - Client-then-server: set both
widget-action-handlerandaction-endpoint. The runtime invokes the client callback first and forwards the same action to the endpoint only if the client callback succeeds.
In direct API mode (<incursa-chatkit-api>), widget-action-handler still works for client-handled widget actions. Local action-endpoint forwarding remains unavailable in that mode.
Updating packaged UI assets
Source vs generated files
The JavaScript pieces in this package fall into two buckets:
- Handwritten source:
ClientApp/chatkit-runtime/src/entry.jsClientApp/chatkit-runtime/src/runtimeHost.jsClientApp/chatkit-runtime/src/clientToolHandlers.jsClientApp/chatkit-runtime/src/entityHandlers.jsClientApp/chatkit-runtime/src/widgetActionHandlers.jsClientApp/chatkit-runtime/src/runtime.css
- Generated bundle:
wwwroot/chatkit/chatkit.jswwwroot/chatkit/chatkit.css
The browser startup flow is:
<incursa-chatkit-assets />renders the upstream CDN script and the local module bundle.- The CDN script defines the upstream
<openai-chatkit>custom element. - The local bundle finds each
data-incursa-chatkit-hostelement rendered by the Razor tag helper. - The local bundle parses
data-incursa-chatkit-config, creates<openai-chatkit>, and callssetOptions(...). - Optional browser callback registries such as
client-tool-handlers,entity-handlers, andwidget-action-handlerare resolved from dotted lookup paths likewindow.chatkit.clientTools.
This package intentionally carries both:
- editable frontend source in
ClientApp/chatkit-runtime - generated package assets in
wwwroot/chatkit
When the packaged ChatKit bootstrap or related npm dependencies need to move forward:
cd src/Incursa.OpenAI.ChatKit.AspNetCore/ClientApp/chatkit-runtime
npm install
npm run build
<incursa-chatkit-assets /> renders both the upstream ChatKit CDN script that defines <openai-chatkit> and the local package bootstrap that applies your serialized Razor config with setOptions(...).
Commit both the dependency file changes and the regenerated files under wwwroot/chatkit.
Related package
Incursa.OpenAI.ChatKit: core ChatKit models, routing, stores, and server runtime
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- Incursa.OpenAI.ChatKit (>= 3.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.