osvi_chat 0.1.1
osvi_chat: ^0.1.1 copied to clipboard
Embed an Osvi AI chat agent in a Flutter app: a headless chat client and drop-in chat widgets.
osvi_chat #
Embed an Osvi AI chat agent in a Flutter app. You get a ready-made chat screen and launcher button, plus a headless client if you want to build your own UI.
It talks to the same agent, dashboard settings and conversations as the web SDK (@osvi-ai/chat). It runs on iOS, Android, web and desktop, with no native code.
Install #
flutter pub add osvi_chat
Quick start #
import 'package:osvi_chat/osvi_chat.dart';
final client = await OsviChatClient.create(agentId: 'AGENT_ID');
// A floating button that opens the chat full screen, with an unread badge:
Scaffold(floatingActionButton: OsviChatLauncher(client: client));
// Or the chat panel anywhere in your layout:
OsviChatView(client: client);
OsviChatClient.create stores the visitor id and current session with shared_preferences, so a returning visitor sees their conversation. It also reconnects when the app returns to the foreground.
Dispose the client when you no longer need it: client.dispose().
Signed-in users (server mode) #
Without auth, each device is an anonymous visitor. For signed-in users, your backend creates the session with your Osvi API token and hands the app a short-lived stream token:
final client = await OsviChatClient.create(
agentId: 'AGENT_ID',
auth: ChatAuth.server(getToken: ({bool newSession = false}) async {
final res = await myApi.get('/osvi-token', query: {'new': '$newSession'});
return ServerToken.fromJson(res); // {sessionId, token, wsUrl, expiresAt}
}),
);
Your backend calls:
GET /v1/chat/session/active?customer_id=…&agent_uuid=…, orPOST /v1/chat/sessionwith{agent_uuid, customer_id}- then
POST /v1/chat/session/:id/ws_tokenwith{"stream": "user"}
Send the API-Token header on these calls. Never put the API token in the app.
Customising #
OsviChatView(
client: client,
title: 'Help',
subtitle: 'We reply in minutes',
theme: const OsviChatTheme(
colors: OsviChatColorOverrides(primary: Color(0xFF0B6A87)),
mode: OsviThemeMode.auto, // light, dark or auto (follows the device)
radius: 16,
buttons: OsviButtonsVariant.list,
carousel: OsviCarouselVariant.slider,
),
strings: const OsviChatStrings(placeholder: 'Ask us anything…'),
newChatKeepsHistory: true,
onPrechat: (info) => print('pre-chat saved: ${info.toJson()}'),
);
What the dashboard controls: the colour, light/dark mode, title, pre-chat form and WhatsApp hand-off configured there apply automatically. Values you set in the app win over them.
Strings: every visible string is overridable. The keys match the web SDK, plus a few extra (for example team, select and confirmDate) for text the web panel hard-codes.
Features #
- Messages: markdown replies, links in visitor messages, reactions, and typing indicators for both the AI and a team member.
- Interactive cards: buttons (chips or list, including an "other" free-text answer), carousels (slider or list), and a date picker (single date or range).
- Human takeover: a "team member joined" notice, with card answers paused while a person is connected.
- Resilient connection: pings, token rotation, reconnect with backoff, resending unconfirmed messages, and recovery of history after a reconnect.
- Limits: handling for rate limits, daily caps and the per-conversation cap, with countdowns.
- Pre-chat and hand-off: the pre-chat form (name and phone) and Continue on WhatsApp.
- Accessibility: status changes and new replies are announced, focus moves to new cards, and animations respect reduced-motion settings.
Headless use #
Build your own UI on the client:
ValueListenableBuilder<ChatState>(
valueListenable: client,
builder: (context, state, _) => Text('${state.items.length} messages'),
);
await client.start();
await client.send('Hello');
await client.respond(interactionId, const InteractionResponse.selection('billing'));
await client.newSession();
Relationship to the web SDK #
The core is a one-to-one port of @osvi-ai/chat's TypeScript core. Its test suite is ported test for test, and it replays the same recorded server fixtures. See PARITY.md for how the two are kept in step.