AiChatAdapter class
Provider-agnostic AI chat adapter.
Quick setup — use a built-in factory for zero-config streaming:
AiChatAdapter.anthropic(apiKey: myKey)
AiChatAdapter.openAi(apiKey: myKey)
AiChatAdapter.google(apiKey: myKey)
Custom backend — implement sendMessage directly:
AiChatAdapter(
sendMessage: (request) async* {
final stream = openai.chat.completions.createStream(
model: 'gpt-4o',
messages: [
{'role': 'system', 'content': request.systemPrompt},
...request.history.map((m) =>
{'role': m.role.name, 'content': m.text}),
],
);
await for (final chunk in stream) {
yield chunk.choices.first.delta.content ?? '';
}
},
)
Errors — a failed reply shows a short reason in the chat ("API key
rejected", "Rate limited", "Provider error", "Offline", "Can't reach
the provider", else "Reply failed"); the full error text, with API
keys and tokens masked, is offered through Copy error. A custom
backend can throw, or add to its stream, an AiProviderException
carrying the HTTP statusCode so the reason is exact; otherwise the
status is read from the error text where it can be ("returned 401",
"status code of 429", "statusCode: 503").
Timeouts — a reply fails when no text arrives within
firstTokenTimeout, or when the text stops for longer than
stallTimeout. A slow model (a local model loading, a reasoning
model thinking before it writes) needs longer values, or none. An
empty chunk on the stream restarts the current timeout without adding
text, so an adapter can keep a slow reply alive by yielding ''.
Constructors
-
AiChatAdapter({required Stream<
String> sendMessage(AiChatRequest request), List<String> ? networkExcludePatterns, Duration? firstTokenTimeout = defaultFirstTokenTimeout, Duration? stallTimeout = defaultStallTimeout}) -
const
- AiChatAdapter.anthropic({required String apiKey, String model = 'claude-sonnet-4-20250514', int maxTokens = 4096, Duration? firstTokenTimeout = defaultFirstTokenTimeout, Duration? stallTimeout = defaultStallTimeout})
-
Creates an adapter for the Anthropic Messages API.
factory
- AiChatAdapter.google({required String apiKey, String model = 'gemini-2.0-flash', Duration? firstTokenTimeout = defaultFirstTokenTimeout, Duration? stallTimeout = defaultStallTimeout})
-
Creates an adapter for the Google Gemini API.
factory
- AiChatAdapter.openAi({required String apiKey, String model = 'gpt-4o', int maxTokens = 4096, String baseUrl = 'https://api.openai.com', Duration? firstTokenTimeout = defaultFirstTokenTimeout, Duration? stallTimeout = defaultStallTimeout})
-
Creates an adapter for the OpenAI Chat Completions API.
factory
Properties
- firstTokenTimeout → Duration?
-
Longest wait from sending a message to the first text of the reply;
the reply then fails with "No reply in …" and offers Retry.
final
- hashCode → int
-
The hash code for this object.
no setterinherited
-
networkExcludePatterns
→ List<
String> ? -
URL patterns the adapter's provider uses, auto-merged with
SleuthConfig.networkExcludePatterns so the network monitor
ignores AI API traffic.
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
-
sendMessage
→ Stream<
String> Function(AiChatRequest request) -
Sends a chat request and returns a stream of text tokens.
final
- stallTimeout → Duration?
-
Longest gap between two pieces of text once a reply is streaming;
the reply then fails with "Reply stalled", the text so far kept on
screen.
final
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Constants
- defaultFirstTokenTimeout → const Duration
- Default firstTokenTimeout.
- defaultStallTimeout → const Duration
- Default stallTimeout.