find_ai_chat 0.1.0
find_ai_chat: ^0.1.0 copied to clipboard
Flutter SDK for embedding the Find AI chat assistant in Flutter apps (mobile & web). Provides a drop-in widget with floating, drawer, and embedded modes, SSE streaming, and full programmatic control.
find_ai_chat #
Flutter SDK for embedding the Find AI chat assistant into Flutter apps
(mobile & web) — equivalent to widget.js for websites, talking to the same
public webchat API (/api/v1/channels/webchat/{connectionId}/...).
Features #
- Three display modes: embedded widget, floating bubble, or drawer panel
- Light/dark theme with system auto-detection
- Two visual styles: classic and GPT-style
- Programmatic control: open, close, toggle, send messages, clear conversation
- SSE streaming with automatic reconnection and
Last-Event-IDresume - Headless mode: use
FindChatClientdirectly for custom UIs or bots - Session persistence via
shared_preferences(visitor & conversation IDs)
Platform support #
| Platform | Supported |
|---|---|
| Android | ✅ |
| iOS | ✅ |
| Web | ✅ |
| macOS | ✅ |
| Windows | ✅ |
| Linux | ✅ |
Installation #
dependencies:
find_ai_chat: ^0.1.0
Quick start #
import 'package:find_ai_chat/find_ai_chat.dart';
FindChatWidget(
connectionId: 'your-connection-id',
baseUrl: 'https://api.example.com',
theme: FindChatTheme.light,
mode: FindChatMode.floating,
)
Global base URL #
Configure once in main() instead of repeating on every widget:
void main() {
FindChatEnvironment.configure(baseUrl: 'https://api.example.com');
runApp(const MyApp());
}
Programmatic control #
final controller = FindChatController(
connectionId: 'your-connection-id',
baseUrl: 'https://api.example.com',
);
controller.open();
controller.close();
controller.toggle();
controller.sendMessage('Hello');
controller.clearConversation();
// Reactive state (standard ChangeNotifier):
controller.state.status; // idle / loadingConfig / ready / sending / streaming / error
controller.state.pending; // true while waiting for LLM response
controller.state.messages; // List<FindChatMessage>
controller.isOpen; // relevant in floating/drawer modes
If you provide your own controller to FindChatWidget, the widget will not
initialize or dispose it — you are responsible for calling
controller.initialize() and controller.dispose().
Display modes #
| Mode | Behavior |
|---|---|
embedded |
Inline widget in the tree. Place it inside an Expanded, SizedBox, or Scaffold.body. |
floating |
Floating bubble (bottom-right corner) that opens a chat card overlay. |
drawer |
No bubble — opened only via code (controller.open()). Side panel on wide screens, bottom sheet on narrow screens (<600dp). |
When mode is not specified, the SDK uses the display_mode configured on the
connection (defaults to floating). embedded is a Flutter-only mode with no
backend equivalent.
Both floating and drawer render via Overlay — they float above the
entire app. Mount FindChatWidget once anywhere under
MaterialApp/WidgetsApp; no need to remount on every screen.
Theming #
FindChatTheme.light/.dark/.system— explicit override. Without an override, the SDK uses thecolor_schemefrom the connection config (defaults to light).FindChatVisualStyle.classic/.gptStyle— explicit override. Without an override, uses thevisual_stylefrom the connection config (defaults to classic).
Precedence: explicit widget parameter → remote connection config → factory default.
Architecture #
FindChatWidget — entry point; resolves theme/mode and delegates
├─ FindChatEmbeddedView
├─ FindChatFloatingBubble (via Overlay)
└─ FindChatDrawerView (via Overlay)
FindChatController — ChangeNotifier: init, sendMessage, open/close/toggle, clearConversation
FindChatClient — HTTP + SSE, stateless
FindChatSessionStore — visitor_id/conversation_id (shared_preferences)
FindChatClient can be used standalone (without the UI) for headless
integrations or fully custom UIs — it depends only on package:http.
Advanced topics #
Origin header in native apps #
The backend validates the Origin header against the connection's
allowed_origins. Since native HTTP clients can set this header freely, two
options exist:
- Set
allowed_origins: ["*"]on the connection (recommended for first-party apps). - Pass
originOverridetoFindChatWidget/FindChatController/FindChatClientwith a value in the allowlist.
SSE reconnection #
FindChatClient.streamTurn reconnects automatically using Last-Event-ID on
network cuts or server timeout (CHAT_STREAM_SSE_MAX_SECONDS, 300s default).
Reconnection never duplicates already-delivered text. Gives up after 3
consecutive failures with no events received
(FindChatTurnUnavailableException).
Limitations (v0.1) #
- No unread message badge in
floatingmode. - Cancellation sets a client-side flag but cannot abort the underlying TCP
connection (
package:httplimitation). - Mid-stream app kills cannot resume the specific turn on restart (conversation
history is still available via
/history).
Running tests #
flutter test
Covers SSE frame parsing (including split UTF-8 chunks), turn accumulator
(node retries, multi-node text, terminal events), and FindChatClient
(request building, error mapping, reconnection with Last-Event-ID).
License #
MIT — see LICENSE.