chataptor 0.1.0
chataptor: ^0.1.0 copied to clipboard
Headless Dart client for real-time, auto-translated customer support chat. Core SDK for Chataptor; pair with chataptor_flutter for drop-in Flutter widgets. Free early access.
chataptor #
Pure-Dart headless core client for Chataptor — real-time multilingual customer support chat.
Early Adopter Program: 6 months free, dedicated support, and a price-lock guarantee after the free period. Check available spots →
This package has no Flutter dependency. Use it when you need a custom UI or when you are integrating Chataptor into a pure-Dart server or CLI context. For drop-in Flutter widgets, use chataptor_flutter instead — it re-exports everything in this package.
Install #
dependencies:
chataptor: ^0.1.0
dart pub get
Usage #
1. Configure and connect #
import 'package:chataptor/chataptor.dart';
final client = ChataptorClient(
config: ChataptorConfig(
siteId: 'your-site-id', // Chataptor admin → Settings → API
widgetKey: 'pk_xxx', // public key, safe to embed in client code
),
);
await client.connect();
2. Listen to messages #
client.messages.listen((message) {
print('${message.body}');
});
3. Send a message #
sendMessage returns a sealed [SendResult] — handle both outcomes:
final result = await client.sendMessage('Hello, I need help with my order.');
switch (result) {
case SendSuccess():
print('Message sent');
case SendFailure(:final error):
print('Send failed: $error');
}
4. Observe connection state #
The connectionState stream emits sealed [ConnectionState] values:
client.connectionState.listen((state) {
switch (state) {
case Connected():
print('Connected — ready to send');
case Connecting():
print('Connecting…');
case Reconnecting(:final attemptNumber, :final nextAttemptIn):
print('Retry #$attemptNumber in $nextAttemptIn');
case Disconnected(:final reason):
print('Disconnected: $reason');
}
});
// Or read synchronously without subscribing:
final current = client.currentConnectionState;
5. Read site config and online-agent presence #
The backend pushes site configuration (welcome message, header title per language, offline mode) on the site channel join, and broadcasts agent availability events thereafter. Both signals are exposed as streams with a synchronous current-value accessor for one-shot reads:
// Per-language site config (welcomeMessage, headerTitle, offline mode).
final config = client.currentSiteConfig;
print(config?.activeHeaderTitle('pl'));
client.siteConfigStream.listen((cfg) {
// re-render header / offline UX
});
// Live roster of currently-online agents (id, name, avatar URL, initials).
for (final agent in client.currentOnlineAgents) {
print('${agent.name} (${agent.initials.short})');
}
client.onlineAgentsStream.listen((agents) {
// re-render avatar stack / Online-Offline status
});
6. Clear the session #
clearSession() drops the persisted guest identity and resets the
in-memory conversation. The next connect() registers as a fresh
customer with a new conversation thread. Useful for "log out" buttons
in customer apps and for local development.
await client.clearSession();
7. Disconnect and dispose #
await client.disconnect();
await client.dispose(); // releases all streams and transport resources
Configuration #
ChataptorConfig accepts ergonomic defaults — only siteId and widgetKey are required:
ChataptorConfig(
siteId: 'your-site-id',
widgetKey: 'pk_xxx',
// Intercept and modify outgoing messages (return null to cancel send)
hooks: ChataptorHooks(
beforeSend: (draft) async {
// sanitise, enrich, or cancel
return draft.copyWith(body: draft.body.trim());
},
onMessageReceived: (message) {
// fire analytics events here
},
onError: (error) {
// forward to your crash reporter
},
),
// Replace the built-in logger
logger: MyCustomLogger(),
// Replace the built-in storage (defaults to in-memory for pure Dart,
// SharedPreferences via chataptor_flutter)
storage: MyCustomStorage(),
)
Testing #
Import package:chataptor/testing.dart in your test files — never in production code.
import 'package:chataptor/chataptor.dart';
import 'package:chataptor/testing.dart';
import 'package:test/test.dart';
// Helper — Message requires explicit field values.
Message _agentMsg(String body) => Message(
id: 'test-$body',
conversationId: 'conv-1',
body: body,
author: MessageAuthor.agent,
timestamp: DateTime.utc(2026, 1, 1),
type: MessageType.text,
deliveryChannel: DeliveryChannel.websocket,
status: MessageStatus.delivered,
);
void main() {
test('receives incoming message from agent', () async {
final fake = FakeChataptorClient();
expect(fake.messages, emits(isA<Message>()));
fake.inject.message(_agentMsg('Hi, how can I help?'));
});
test('records outgoing messages', () async {
final fake = FakeChataptorClient(
initialConnectionState: const Connected(),
);
fake.inject.completeNextSend(
SendSuccess(MessageDraft(body: 'Hello!')),
);
await fake.sendMessage('Hello!');
expect(fake.recorded.sentMessages.first.body, 'Hello!');
});
}
FakeChataptorClient is the high-level fake for testing code that consumes the SDK.
For testing the SDK transport layer itself, use FakeChatTransport.
| Export | Purpose |
|---|---|
FakeChataptorClient |
Drop-in replacement for ChataptorClient in host-app tests |
FakeChatTransport |
Transport-level scripting for SDK unit tests |
InMemoryChataptorStorage |
Resets between test runs |
RecordingChataptorLogger |
Assert on log output |
Requirements #
| Minimum | |
|---|---|
| Dart | 3.9.0 |
License #
MIT © 2026 Chataptor