プロバイダー、ストリーミング、DOCX エクスポート
AI Toolkit と組み合わせて使うサーバー側の機能で、すべて RichTextBox.AspNetCore NuGet パッケージ(1.0.0-preview.11 以降)に含まれています。1 行の DI で実際のプロバイダーに接続でき、エンドツーエンドの SSE ストリーミングと、HTML → DOCX のエンドポイントを備えています。
組み込みのプロバイダーリゾルバー
HttpClientFactory、キャンセル、ILogger<T> を使う、そのまま組み込める 3 つの IRichTextBoxAiResolver の実装があります。1 つを選んで Program.cs に登録します。
using RichTextBox.AiResolvers;
builder.Services.AddRichTextBox();
builder.Services.AddRichTextBoxOpenAiResolver(opts =>
{
opts.ApiKey = builder.Configuration["OpenAI:ApiKey"];
opts.Model = "gpt-6-luna";
});AddRichTextBoxOpenAiResolver は、AddRichTextBoxAnthropicResolver または AddRichTextBoxAzureOpenAiResolver に置き換えられます。3 つとも AiResolverOptions を共有しています。
public class AiResolverOptions
{
public string ApiKey { get; set; } // required
public string? Model { get; set; } // provider-specific default
public string? BaseUrl { get; set; } // for proxies / Ollama / Groq
public int MaxTokens { get; set; } = 1024;
public double Temperature { get; set; } = 0.4;
public string? SystemSuffix { get; set; } // appended to every mode's system prompt
public TimeSpan Timeout { get; set; } = 60s;
}Azure では、AzureOpenAiResolverOptions に 3 つの追加項目があります。Endpoint(https://my-resource.openai.azure.com)、DeploymentName(モデル名ではありません)、ApiVersion(省略可能)です。
OpenAiResolver は、OpenAI 互換のあらゆるエンドポイントで動作します。Groq、Together.ai、ローカルの Ollama を使う場合は BaseUrl を上書きしてください。
ストリーミングのレスポンス(Server-Sent Events)
MapRichTextBoxUploads() は、POST /richtextbox/ai/stream もマップします(RichTextBoxOptions.AiStreamEndpoint で変更できます)。OpenAI と Anthropic のリゾルバーは IStreamingRichTextBoxAiResolver を実装しています。ストリーミングに対応していないプロバイダーは、透過的に 1 つのデータフレームで返す動作になります。
通信形式
data: <json-encoded delta string>\n\n
data: <json-encoded delta string>\n\n
...
event: response
data: { ...RichTextBoxAiResponse payload... }\n\n
event: done
data: {}\n\nクライアント
var stream = editor.aiToolkit.streamRequest({
url: "/richtextbox/ai/stream",
body: { mode: "rewrite", selectionText: "..." },
onDelta: function (chunk, full) { /* render progressively */ },
onResponse: function (payload) { /* final structured result */ },
onDone: function (fullText) { },
onError: function (err) { }
});
// stream.abort() — cancel mid-response
// stream.promise — resolves with the concatenated full textヘルパーは fetch と ReadableStream を使います。ストリーミングに対応していないブラウザーでは、ストリーミングでないエンドポイントに対する XHR に自動的に切り替わります。
DOCX エクスポート
MapRichTextBoxUploads() は、POST /richtextbox/export/docx もマップします(DocxExportEndpoint で変更できます)。MIT ライセンスの DocumentFormat.OpenXml をベースにしており、外部サービスは使いません。
リクエスト
POST /richtextbox/export/docx
Content-Type: application/json
{
"html": "<h1>Memo</h1><p>Body.</p>",
"title": "Memo",
"fileName": "memo.docx"
}レスポンス
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document と Content-Disposition: attachment; filename=memo.docx を持つバイナリストリームです。
サポートしている HTML
- 段落、
h1–h6、blockquote、pre、hr - 入れ子の番号付きリストと箇条書きリスト
- 表(見出し行を含む)
- インライン:
b/strong,i/em,u,s/del,sub,sup,code,br - ハイパーリンク、インライン画像(data URI のみ。安全のため、外部の URL はスキップします)
- スタイル属性:
font-weight,font-style,text-decoration,color,background-color,text-align
クライアントのヘルパー
editor.aiToolkit.exportDocx({
url: "/richtextbox/export/docx",
fileName: "report.docx",
title: "Quarterly report"
});カスタムリゾルバー
Bedrock、Gemini、独自のモデルなど、それ以外のものを使う場合は、IRichTextBoxAiResolver(必要に応じて IStreamingRichTextBoxAiResolver も)を実装し、そのクラスを登録してください。AI Toolkit のそれ以外の部分は、プロバイダーに依存しません。
public sealed class MyBedrockResolver : IRichTextBoxAiResolver
{
public async ValueTask<RichTextBoxAiResponse> ResolveAsync(
RichTextBoxAiRequest request, CancellationToken cancellationToken = default)
{
// ...call Bedrock, map response to RichTextBoxAiResponseBuilder...
}
}
builder.Services.AddRichTextBox();
builder.Services.AddSingleton<IRichTextBoxAiResolver, MyBedrockResolver>();