Flutter Agent Pupau
A Flutter plugin that integrates Pupau AI agents in your application.
Features
- AI-Powered Chat Interface - Full-featured chat UI with streaming responses
- Multiple Widget Modes - Full screen, sized container, or floating overlay
- Flexible Authentication - API key or bearer token authentication
- Event Streaming - Real-time events for conversation lifecycle
- Multi-language Support - Built-in support for 14 languages
- Programmatic Control - Open, reset, and load conversations via code
Documentation
For full documentation on Pupau and more information on this plugin, visit Pupau AI Docs
Installation
Add the package name and version in your package's pubspec.yaml file:
dependencies:
flutter_agent_pupau: ^1.0.1
Then run:
flutter pub get
Usage
1. Import the plugin
import 'package:flutter_agent_pupau/flutter_agent_pupau.dart';
2. Configure PupauConfig
Create a PupauConfig using one of two authentication methods:
Option A: API Key Authentication
final config = PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
// Optional parameters
conversationId: 'existing-conversation-id', // Load specific conversation
isAnonymous: false, // Anonymous chat mode
language: PupauLanguage.en, // UI language (defaults to English)
apiUrl: 'https://api.pupau.ai', // Override base API URL
isMarketplace: false, // Set true for marketplace agents
googleMapsApiKey: 'your-maps-key', // For location features
hideInputBox: false, // Hide the input field
widgetMode: WidgetMode.full, // Display mode
showNerdStats: false, // Show token/credit stats
hideAudioRecordingButton: false, // Hide audio recording button
resetChatOnOpen: true, // Reset chat state when opening
conversationStarters: [ // Predefined starter messages
'Tell me about your features',
'How can you help me?',
],
initialWelcomeMessage: 'Hi! How can I help you today?', // Fallback welcome while actual message is loading
customProperties: { // Custom metadata
'userId': '123',
'source': 'mobile_app',
},
appBarConfig: AppBarConfig( // App bar configuration
showAppBar: true,
actions: [], // Custom action buttons
closeStyle: CloseStyle.arrow, // arrow, cross, or none
closeButtonPosition: CloseButtonPosition.left, // left or right
),
drawerConfig: DrawerConfig( // Drawer configuration
drawer: MyDrawer(), // Left drawer widget
endDrawer: MyEndDrawer(), // Right drawer widget
scaffoldKey: myScaffoldKey, // Optional: GlobalKey<ScaffoldState> for programmatic control
onDrawerChanged: (isOpen) { // Called when drawer opens/closes
print('Drawer is ${isOpen ? "open" : "closed"}');
},
onEndDrawerChanged: (isOpen) { // Called when end drawer opens/closes
print('End drawer is ${isOpen ? "open" : "closed"}');
},
),
);
Option B: Bearer Token Authentication
Requires explicit assistant ID.
final config = PupauConfig.createWithToken(
bearerToken: 'your-bearer-token',
assistantId: 'your-assistant-id',
// ... same optional parameters as above
);
Widget Avatar
The PupauAgentAvatar widget is the main UI component that displays an avatar and handles chat interactions. It supports three display modes:
Full Screen Mode (Default)
On tap it navigates to a full page that displays the chat.
PupauAgentAvatar(
config: PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
widgetMode: WidgetMode.full,
),
)
Sized Mode
The avatar expands in-place to a specified width and height.
PupauAgentAvatar(
config: PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
widgetMode: WidgetMode.sized,
sizedConfig: SizedConfig(
width: 400,
height: 600,
initiallyExpanded: false, // Start collapsed
),
),
)
Initially Expanded Chat
If you want the chat to be already expanded when the widget first loads, use the sized mode with initiallyExpanded: true. You can also hide the close button using AppBarConfig so that the chat will always stay open.
PupauAgentAvatar(
config: PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
widgetMode: WidgetMode.sized,
sizedConfig: SizedConfig(
width: 400,
height: 600,
initiallyExpanded: true, //Chat starts expanded!
),
appBarConfig: AppBarConfig(
closeStyle: CloseStyle.none, //Hide close button so that expanded chat cannot be closed
),
),
)
Floating Overlay Mode
The chat appears as a floating overlay anchored to the avatar.
PupauAgentAvatar(
config: PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
widgetMode: WidgetMode.floating,
floatingConfig: FloatingConfig(
width: 400,
height: 600,
anchor: FloatingAnchor.bottomRight, // bottomRight, bottomLeft, topRight, topLeft
),
),
)
Headless Assistant Preloading with PupauAgentPreloader
If you need to warm the plugin state and load assistant data without showing the chat UI, use PupauAgentPreloader.
- Ensures chat bindings/controllers are registered for the given
PupauConfig - Preloads the
Assistantmodel for the configuredassistantId - Lets you render any custom UI via a builder, without imposing layout
import 'package:flutter_agent_pupau/flutter_agent_pupau.dart';
// Example: preload assistant data, then open chat programmatically on tap.
final config = PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
);
PupauAgentPreloader(
config: config,
builder: (context, assistant, isLoading) {
return InkWell(
onTap: () => PupauChatUtils.openChat(context, config),
child: ListTile(
leading: isLoading
? const SizedBox(
width: 40,
height: 40,
child: Center(child: CircularProgressIndicator(strokeWidth: 2)),
)
: null,
title: Text(assistant?.name ?? 'Loading...'),
subtitle: Text(assistant?.description ?? ''),
),
);
},
)
Programmatic Control with PupauChatUtils
Control the chat programmatically from anywhere in your app:
Open Chat from Code
// Open chat with a button press
ElevatedButton(
onPressed: () {
PupauChatUtils.openChat(
context,
PupauConfig.createWithApiKey(apiKey: 'your-api-key'),
);
},
child: Text('Open Chat'),
)
Reset Current Chat
// Clear the current conversation and start fresh
await PupauChatUtils.resetChat();
Load Specific PupauConversation
// Load a conversation by ID
await PupauChatUtils.loadConversation('conversation-id');
Preload Assistants List and Avatars
Use PupauChatUtils.preloadAssistantsList to warm the assistants list and cache avatar images before you show a picker, list, or drawer of agents.
- Resolves auth from either an explicit
PupauConfig, abearerToken, or the current chat controller config - Precaches avatar images
// Example 1: preload with bearer token (no config yet)
final assistants = await PupauChatUtils.preloadAssistantsList(
context,
bearerToken: 'your-bearer-token',
);
// Example 2: preload with an existing config
final config = PupauConfig.createWithToken(
bearerToken: 'your-bearer-token',
assistantId: 'your-assistant-id',
);
final assistantsWithConfig = await PupauChatUtils.preloadAssistantsList(
context,
config: config,
);
// Use `assistants` / `assistantsWithConfig` to build a fast-loading list or drawer.
Other PupauChatUtils methods
-
Anonymous mode
PupauChatUtils.startAnonymousChat(): switch current chat to anonymous mode (resets conversation).PupauChatUtils.toggleAnonymousMode(): toggle anonymous mode on/off (resets conversation).PupauChatUtils.exitAnonymousAndStartNewConversation(): exit anonymous mode (if enabled) and start fresh.PupauChatUtils.startNewConversation(isCurrentlyAnonymous: ...): helper for “New conversation” UI flows.
-
UI toggles
PupauChatUtils.setNerdStats(true/false): show/hide token + credit stats.PupauChatUtils.setHideInputBox(true/false): hide/show the input box.
-
Assistant refresh
PupauChatUtils.reloadCurrentAssistant(): reload the current assistant model and update UI.
-
Auth refresh flow (bearer token)
PupauChatUtils.updateAuthToken(newBearerToken): set the refreshed token and unblock all suspended 401 requests.
Event Streaming with PupauEventService
Listen to real-time events from the chat interface:
Basic Event Listening
import 'package:flutter_agent_pupau/flutter_agent_pupau.dart';
// Listen to all chat events
PupauEventService.pupauStream.listen((event) {
print('Event Type: ${event.type}');
print('Event Payload: ${event.payload}');
switch (event.type) {
case UpdateConversationType.newConversation:
print('New conversation created: ${event.payload}');
break;
case UpdateConversationType.messageSent:
print('Message sent: ${event.payload}');
break;
case UpdateConversationType.messageReceived:
print('Message received: ${event.payload}');
break;
case UpdateConversationType.conversationChanged:
print('PupauConversation changed to: ${event.payload}');
break;
case UpdateConversationType.error:
print('Error occurred: ${event.payload}');
break;
// ... handle other events
}
});
Audio Recording Feature
To use the audio recording feature, follow these steps
Android Audio Setup
In your AndroidManifest.xml file add:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
iOS Audio Setup
In your ios/Runner/Info.plist file add:
<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to your microphone to record voice messages.</string>
Then in your ios/Podfile, in the post_install section, add the microphone permission configuration:
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_MICROPHONE=1',
]
end
end
end
Note: After modifying the Podfile, run flutter clean and rebuild your app, as these changes require recompilation.
App Bar Configuration
The AppBarConfig allows you to customize the app bar appearance and behavior:
Show/Hide App Bar
PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
appBarConfig: AppBarConfig(
showAppBar: false, // Hide the app bar completely
),
)
Custom Actions
Add custom action buttons to the app bar:
PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
appBarConfig: AppBarConfig(
actions: [
IconButton(
icon: Icon(Icons.menu),
tooltip: 'Open drawer',
onPressed: () {
Scaffold.of(context).openDrawer();
},
),
IconButton(
icon: Icon(Icons.info),
onPressed: () {
// Handle info
},
),
],
),
)
### Close Button Style and Position
Control the close button appearance and position:
```dart
PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
appBarConfig: AppBarConfig(
closeStyle: CloseStyle.arrow, // arrow, cross, or none
closeButtonPosition: CloseButtonPosition.left, // left or right
),
)
Default Behavior:
- Full Mode: Arrow icon on the left
- Sized/Floating Modes: Cross icon on the right
Available Options:
CloseStyle.arrow- Arrow back icon (<)CloseStyle.cross- Close/X icon (×)CloseStyle.none- Hide the close button completelyCloseButtonPosition.left- Show in the leading positionCloseButtonPosition.right- Show in the actions position, at the most right position
Drawer Configuration
The DrawerConfig allows you to add drawers to the chat interface:
Left Drawer
PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
drawerConfig: DrawerConfig(
drawer: Drawer(
child: ListView(
children: [
ListTile(
title: Text('Menu Item 1'),
onTap: () {
// Handle tap
},
),
ListTile(
title: Text('Menu Item 2'),
onTap: () {
// Handle tap
},
),
],
),
),
onDrawerChanged: (isOpen) {
print('Drawer is ${isOpen ? "open" : "closed"}');
},
),
)
Right Drawer (End Drawer)
PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
drawerConfig: DrawerConfig(
endDrawer: Drawer(
child: ListView(
children: [
ListTile(
title: Text('Settings'),
onTap: () {
// Handle settings
},
),
],
),
),
onEndDrawerChanged: (isOpen) {
print('End drawer is ${isOpen ? "open" : "closed"}');
},
),
)
Both Drawers
You can configure both drawers simultaneously:
PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
drawerConfig: DrawerConfig(
drawer: MyLeftDrawer(),
endDrawer: MyRightDrawer(),
onDrawerChanged: (isOpen) {
// Handle left drawer state changes
},
onEndDrawerChanged: (isOpen) {
// Handle right drawer state changes
},
),
)
Controlling Drawers Programmatically
You can control the drawers programmatically by providing a scaffoldKey:
final scaffoldKey = GlobalKey<ScaffoldState>();
PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
drawerConfig: DrawerConfig(
drawer: MyDrawer(),
scaffoldKey: scaffoldKey,
),
)
// Later, open/close the drawer programmatically:
scaffoldKey.currentState?.openDrawer();
scaffoldKey.currentState?.openEndDrawer();
scaffoldKey.currentState?.closeDrawer();
Note: The scaffoldKey allows you to control the drawer from anywhere in your app using the ScaffoldState methods like openDrawer(), openEndDrawer(), and closeDrawer().
Event Types
| Event Type | Payload | Description |
|---|---|---|
componentBootStatus |
BootState |
Plugin initialization status (off, pending, ok, error) |
newConversation |
PupauConversation (conversation) |
New conversation created |
resetConversation |
null |
PupauConversation was reset |
conversationChanged |
PupauConversation (conversation) |
Active conversation changed |
conversationTitleGenerated |
String (title) |
PupauConversation title generated |
firstMessageComplete |
null |
First message in conversation completed |
messageSent |
Message |
User sent a message |
messageReceived |
Message |
AI response received |
stopMessage |
null |
Message streaming stopped |
deleteConversation |
String (conversationId) |
PupauConversation deleted |
windowClose |
null |
Chat window closed |
historyToggle |
bool |
PupauConversation history toggled |
noCredit |
null |
No credits available |
error |
String (error message) |
General error occurred |
authError |
Map (url, statusCode, message) |
Authentication error (typically HTTP 401) |
tokensPerSecond |
double |
Streaming performance metric |
timeToComplete |
int (milliseconds) |
Time to complete response |
timeToFirstToken |
int (milliseconds) |
Time to first token received |
inputFieldFocusChanged |
bool (isFocused) |
Message input field focus gained or lost |
Supported Languages
The plugin supports the following languages via the PupauLanguage enum:
PupauLanguage.en- English (default)PupauLanguage.de- GermanPupauLanguage.es- SpanishPupauLanguage.fr- FrenchPupauLanguage.hi- HindiPupauLanguage.it- ItalianPupauLanguage.ko- KoreanPupauLanguage.nl- DutchPupauLanguage.pl- PolishPupauLanguage.pt- PortuguesePupauLanguage.sq- AlbanianPupauLanguage.sv- SwedishPupauLanguage.tr- TurkishPupauLanguage.zh- Chinese
Example:
PupauConfig.createWithApiKey(
apiKey: 'your-api-key',
language: PupauLanguage.es, // Spanish
)
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Libraries
- chat_page/bindings/chat_bindings
- chat_page/components/attachments_elements/attachment_card
- chat_page/components/attachments_elements/attachment_note_modal
- chat_page/components/attachments_elements/attachment_switch_skeleton
- chat_page/components/attachments_elements/attachments_box
- chat_page/components/attachments_elements/attachments_list
- chat_page/components/attachments_elements/attachments_modal
- chat_page/components/attachments_elements/attachments_search_bar
- chat_page/components/attachments_elements/attachments_tokens_info
- chat_page/components/attachments_elements/toggle_attachments_switch
- chat_page/components/chat_elements/assistant_avatar
- chat_page/components/chat_elements/assistant_capabilities
- chat_page/components/chat_elements/assistant_chip
- chat_page/components/chat_elements/assistant_info_modal
- chat_page/components/chat_elements/chat_app_bar
- chat_page/components/chat_elements/chat_image_full
- chat_page/components/chat_elements/chat_image_zoomable
- chat_page/components/chat_elements/chat_input_field
- chat_page/components/chat_elements/chat_loading_message
- chat_page/components/chat_elements/chat_skeleton
- chat_page/components/chat_elements/chat_tools_fab
- chat_page/components/chat_elements/conversation_starter_chip
- chat_page/components/chat_elements/conversation_starters_list
- chat_page/components/chat_elements/conversation_title
- chat_page/components/chat_elements/custom_action_card
- chat_page/components/chat_elements/custom_actions_modal
- chat_page/components/chat_elements/initial_message
- chat_page/components/chat_elements/messages_list
- chat_page/components/chat_elements/my_mention_tag_text_editing_controller
- chat_page/components/chat_elements/my_mention_tag_text_field
- chat_page/components/chat_elements/pupau_agent_preloader
- chat_page/components/chat_elements/recording_bar
- chat_page/components/chat_elements/taggable_assistants_list
- chat_page/components/chat_elements/tagged_assistants_list
- chat_page/components/markdown_builders_elements/code_builder
- chat_page/components/markdown_builders_elements/code_container
- chat_page/components/markdown_builders_elements/download_builder
- chat_page/components/markdown_builders_elements/download_container
- chat_page/components/markdown_builders_elements/download_syntax
- chat_page/components/markdown_builders_elements/google_map_builder
- chat_page/components/markdown_builders_elements/google_map_container
- chat_page/components/markdown_builders_elements/google_map_syntax
- chat_page/components/markdown_builders_elements/link_builder
- chat_page/components/markdown_builders_elements/mermaid_builder
- chat_page/components/markdown_builders_elements/mermaid_container
- chat_page/components/markdown_builders_elements/mermaid_syntax
- chat_page/components/markdown_builders_elements/thinking_builder
- chat_page/components/markdown_builders_elements/thinking_syntax_builder
- chat_page/components/markdown_builders_elements/thinking_tag_container
- chat_page/components/markdown_builders_elements/tool_use_info
- chat_page/components/markdown_builders_elements/tool_use_info_list
- chat_page/components/message_elements/attachment_trimming_container
- chat_page/components/message_elements/attachment_trimming_dialog
- chat_page/components/message_elements/attachments_box
- chat_page/components/message_elements/audio_converting_info
- chat_page/components/message_elements/chat_audio_label
- chat_page/components/message_elements/chat_date_container
- chat_page/components/message_elements/context_info_container
- chat_page/components/message_elements/context_info_item
- chat_page/components/message_elements/fork_conversation_icon
- chat_page/components/message_elements/fork_conversation_modal
- chat_page/components/message_elements/kb_references_modal
- chat_page/components/message_elements/knowledge_base_info
- chat_page/components/message_elements/loading_dots
- chat_page/components/message_elements/loading_tag
- chat_page/components/message_elements/loading_text
- chat_page/components/message_elements/loading_tool_preview_content
- chat_page/components/message_elements/loading_tool_use
- chat_page/components/message_elements/loading_web_search
- chat_page/components/message_elements/message_action_bar
- chat_page/components/message_elements/message_body
- chat_page/components/message_elements/message_bottom_elements
- chat_page/components/message_elements/message_bubble
- chat_page/components/message_elements/message_content
- chat_page/components/message_elements/message_copy_icon
- chat_page/components/message_elements/message_elements
- chat_page/components/message_elements/message_load_error_info
- chat_page/components/message_elements/message_notifier
- chat_page/components/message_elements/message_sender_info
- chat_page/components/message_elements/message_stream_builder
- chat_page/components/message_elements/message_time_info
- chat_page/components/message_elements/prompt_options_list
- chat_page/components/message_elements/reaction_icon
- chat_page/components/message_elements/reference_text
- chat_page/components/message_elements/reflection_tag_container
- chat_page/components/message_elements/text_to_speach_icon
- chat_page/components/message_elements/urls_list
- chat_page/components/message_elements/warning_action_bar_icon
- chat_page/components/message_elements/web_search_type_indicator
- chat_page/components/shared/api_error_widget
- chat_page/components/shared/basic_app_bar
- chat_page/components/shared/close_icon
- chat_page/components/shared/custom_basic_dialog
- chat_page/components/shared/custom_checkbox
- chat_page/components/shared/custom_delete_confirm_dialog
- chat_page/components/shared/custom_info_box
- chat_page/components/shared/custom_input_field
- chat_page/components/shared/custom_search_bar
- chat_page/components/shared/custom_selectable_text
- chat_page/components/shared/custom_switch
- chat_page/components/shared/error_snackbar
- chat_page/components/shared/feedback_snackbar
- chat_page/components/shared/image_not_available_widget
- chat_page/components/shared/info_row
- chat_page/components/shared/marketplace_icon
- chat_page/components/shared/modal_option
- chat_page/components/shared/no_data_found_info
- chat_page/components/shared/selection_transformer
- chat_page/components/shared/setting_denied_dialog
- chat_page/components/tool_use_elements/ask_user_option
- chat_page/components/tool_use_elements/basic_tool_use_modal
- chat_page/components/tool_use_elements/browser_inspector_modal
- chat_page/components/tool_use_elements/browser_use_bottom_info
- chat_page/components/tool_use_elements/browser_use_datalayer_content
- chat_page/components/tool_use_elements/browser_use_datalayer_item
- chat_page/components/tool_use_elements/browser_use_loading_message
- chat_page/components/tool_use_elements/browser_use_network_content
- chat_page/components/tool_use_elements/browser_use_network_item
- chat_page/components/tool_use_elements/document_tool_card
- chat_page/components/tool_use_elements/document_tool_download
- chat_page/components/tool_use_elements/image_generation_tool_modal
- chat_page/components/tool_use_elements/message_ask_user
- chat_page/components/tool_use_elements/message_browser_use
- chat_page/components/tool_use_elements/message_browser_use_loading_placeholder
- chat_page/components/tool_use_elements/message_browser_use_screenshot
- chat_page/components/tool_use_elements/message_document
- chat_page/components/tool_use_elements/message_knowledge_base
- chat_page/components/tool_use_elements/message_task_tool
- chat_page/components/tool_use_elements/message_thinking
- chat_page/components/tool_use_elements/message_to_do_list
- chat_page/components/tool_use_elements/smtp_info_modal
- chat_page/components/tool_use_elements/task_capability_pill
- chat_page/components/tool_use_elements/task_create_content
- chat_page/components/tool_use_elements/task_info_chip
- chat_page/components/tool_use_elements/todo_item
- chat_page/components/tool_use_elements/tool_use_avatar
- chat_page/components/tool_use_elements/tool_use_bubble
- chat_page/components/tool_use_elements/tool_use_info
- chat_page/components/tool_use_elements/tool_use_info_list
- chat_page/components/tool_use_elements/tool_use_message_content
- chat_page/components/ui_tool_elements/message_request_credentials
- chat_page/components/ui_tool_elements/ui_tool_bubble
- chat_page/components/web_elements/chat_images_list
- chat_page/components/web_elements/graph_info_container
- chat_page/components/web_elements/news_container
- chat_page/components/web_elements/organic_info_container
- chat_page/components/web_elements/organic_info_modal
- chat_page/components/web_elements/source_info
- chat_page/components/web_elements/web_search_elements
- chat_page/components/web_elements/web_search_images_modal
- chat_page/components/web_elements/web_search_news_list
- chat_page/components/web_elements/web_search_news_modal
- chat_page/controllers/assistants_controller
- chat_page/controllers/attachments_controller
- chat_page/controllers/browser_inspector_controller
- chat_page/controllers/chat_controller
- chat_page/controllers/tool_ask_user_controller
- chat_page/pupau_agent_avatar
- chat_page/pupau_agent_chat
- chat_page/utils/modal_utils
- config/pupau_config
- flutter_agent_pupau
- Main library file for flutter_agent_pupau package
- models/ai_model
- models/assistant_api_key_model
- models/assistant_model
- models/attachment_model
- models/chat_image_model
- models/conversation_model
- models/custom_action_model
- models/loading_message_model
- models/prompt_option_model
- models/prompt_reflection_model
- models/pupau_message_model
- models/setting_model
- models/tool_use_message_model
- models/tool_use_models/tool_use_args_delta_data
- models/tool_use_models/tool_use_ask_user_data
- models/tool_use_models/tool_use_browser_use_data
- models/tool_use_models/tool_use_document_data
- models/tool_use_models/tool_use_heartbeat_data
- models/tool_use_models/tool_use_image_generation_data
- models/tool_use_models/tool_use_knowledge_base_data
- models/tool_use_models/tool_use_partial_result_data
- models/tool_use_models/tool_use_pending_data
- models/tool_use_models/tool_use_pipeline_data
- models/tool_use_models/tool_use_s_m_t_p_data
- models/tool_use_models/tool_use_task_data
- models/tool_use_models/tool_use_thinking_data
- models/tool_use_models/tool_use_to_do_list_data
- models/tool_use_models/tool_use_web_reader_data
- models/tool_use_models/tool_use_web_search_data
- models/ui_tool_message_model
- pupau_agent
- Public API for flutter_agent_pupau package
- services/api_exceptions
- services/api_service
- services/assistant_service
- services/attachment_service
- services/audio_recording_service
- services/conversation_service
- services/device_service
- services/file_service
- services/file_service_stub
- services/file_service_web
- services/google_drive_service
- services/google_maps_service
- services/json_parse_service
- services/language_service
- services/message_service
- services/pupau_event_service
- services/settings_service
- services/sse_service
- services/string_service
- services/style_service
- services/tag_service
- services/tool_args_delta_service
- services/tool_ask_user_service
- services/tool_use_service
- services/tts_service
- services/ui_tool_service
- utils/api_urls
- utils/constants
- utils/pupau_chat_utils
- utils/settings
- utils/translations/languages/de_de_translation
- utils/translations/languages/en_us_translation
- utils/translations/languages/es_es_translation
- utils/translations/languages/fr_fr_translation
- utils/translations/languages/hi_in_translation
- utils/translations/languages/it_it_translation
- utils/translations/languages/ko_kr_translation
- utils/translations/languages/nl_nl_translation
- utils/translations/languages/pl_pl_translation
- utils/translations/languages/pt_pt_translation
- utils/translations/languages/sq_al_translation
- utils/translations/languages/sv_se_translation
- utils/translations/languages/tr_tr_translation
- utils/translations/languages/zh_cn_translation
- utils/translations/localization_service
- utils/translations/strings_enum
- utils/translations/theme/anonymous_theme_colors
- utils/translations/theme/dark_theme_colors
- utils/translations/theme/light_theme_colors
- utils/translations/theme/my_fonts
- utils/translations/theme/my_styles
- utils/translations/theme/my_theme
- utils/translations/theme/theme_extensions/pupau_theme_data
- utils/translations/theme/theme_extensions/skeleton_theme_data