aaroh_chat 1.3.0+3 copy "aaroh_chat: ^1.3.0+3" to clipboard
aaroh_chat: ^1.3.0+3 copied to clipboard

Flutter chat SDK by Aaroh for AI-powered conversations, featuring built-in NLP, Claude API integration, and branding options.

example/lib/main.dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:aaroh_chat/aaroh_chat.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(const ExampleApp());
}

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Aaroh Chat SDK Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: Colors.deepPurple,
        useMaterial3: true,
      ),
      routes: {
        '/pricing': (_) => const _PricingPage(),
      },
      home: const HomePage(),
    );
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// MULTILINGUAL KnowledgeItem HELPER
//
// The SDK's built-in engine and Claude system-prompt both use the `answer`
// field. To make the bot actually reply in the user's chosen language you
// need to supply separate answers for each locale.
//
// Pattern: create a helper that returns the right KnowledgeItem based on
// the current LanguageTone. Pass `language` as an argument so the config
// is rebuilt whenever the user switches languages.
// ─────────────────────────────────────────────────────────────────────────────

/// Returns a bilingual answer for [topic] based on [lang].
String _answer(LanguageTone lang, {required String en, required String hi, required String hinglish}) {
  switch (lang) {
    case LanguageTone.hindi:
      return hi;
    case LanguageTone.hinglish:
      return hinglish;
    case LanguageTone.english:
    return en;
  }
}

/// Builds a knowledge base that responds in the correct language.
///
/// Call this every time [lang] changes and pass the result into a new
/// [AarohConfig]. The SDK picks up the new answers automatically.
List<Object> buildKnowledgeBase(LanguageTone lang) {
  return [
    // ── Plain strings: quick facts ──────────────────────────────────────────
    _answer(lang,
      en:       'ShopMart is an e-commerce platform selling electronics, clothing and home goods.',
      hi:       'ShopMart एक ई-कॉमर्स प्लेटफ़ॉर्म है जो इलेक्ट्रॉनिक्स, कपड़े और घर का सामान बेचता है।',
      hinglish: 'ShopMart ek e-commerce platform hai jo electronics, kapde aur ghar ka saman bechta hai.',
    ),

    // ── Structured KnowledgeItem entries ────────────────────────────────────
    KnowledgeItem(
      id: 'return-policy',
      question: _answer(lang,
        en:       'What is your return policy?',
        hi:       'आपकी वापसी नीति क्या है?',
        hinglish: 'Aapki return policy kya hai?',
      ),
      answer: _answer(lang,
        en:       '30-day hassle-free returns, no questions asked.',
        hi:       '30 दिनों के अंदर बिना किसी सवाल के वापसी करें।',
        hinglish: '30 din ke andar bina kisi sawaal ke return kar sakte hain.',
      ),
      category: 'Policies',
      keywords: ['refund', 'return', 'exchange', 'send back',
        'वापसी', 'रिफंड', 'vapas', 'wapsi'],
    ),

    KnowledgeItem(
      id: 'delivery',
      question: _answer(lang,
        en:       'Is delivery free?',
        hi:       'क्या डिलीवरी मुफ्त है?',
        hinglish: 'Kya delivery free hai?',
      ),
      answer: _answer(lang,
        en:       'Yes — free delivery on all orders above ₹499.',
        hi:       'हाँ — ₹499 से अधिक के सभी ऑर्डर पर मुफ्त डिलीवरी।',
        hinglish: 'Haan — ₹499 se upar ke sabhi orders par free delivery milti hai.',
      ),
      category: 'Shipping',
      keywords: ['shipping', 'delivery', 'courier', 'डिलीवरी', 'शिपिंग'],
    ),

    KnowledgeItem(
      id: 'emi',
      question: _answer(lang,
        en:       'Do you offer EMI?',
        hi:       'क्या EMI की सुविधा है?',
        hinglish: 'Kya EMI available hai?',
      ),
      answer: _answer(lang,
        en:       'Yes — EMI available on orders above ₹2000 via all major banks.',
        hi:       'हाँ — ₹2000 से अधिक के ऑर्डर पर सभी प्रमुख बैंकों के माध्यम से EMI उपलब्ध है।',
        hinglish: 'Haan — ₹2000 se upar ke orders par sabhi major banks ke through EMI available hai.',
      ),
      category: 'Payments',
      keywords: ['emi', 'installment', 'किश्त', 'credit card'],
    ),

    KnowledgeItem(
      id: 'working-hours',
      question: _answer(lang,
        en:       'What are your working hours?',
        hi:       'आपके काम के घंटे क्या हैं?',
        hinglish: 'Aapke working hours kya hain?',
      ),
      answer: _answer(lang,
        en:       'Our support team is available Monday to Saturday, 9 AM – 7 PM IST.',
        hi:       'हमारी सपोर्ट टीम सोमवार से शनिवार, सुबह 9 बजे से शाम 7 बजे IST तक उपलब्ध है।',
        hinglish: 'Hamari support team Monday se Saturday, 9 AM – 7 PM IST tak available hai.',
      ),
      category: 'Support',
      keywords: ['hours', 'timing', 'time', 'समय', 'घंटे', 'support'],
    ),
  ];
}

// ─────────────────────────────────────────────────────────────────────────────
// CUSTOM API INTEGRATION
//
// Pass your own backend URL via [AarohConfig.customApiUrl] (or implement the
// [onCustomApiCall] callback pattern shown below). The SDK will POST the user
// message + conversation history to your endpoint and display the reply.
//
// YOUR API CONTRACT (expected request / response shape):
//
//   POST https://your-api.com/chat
//   Content-Type: application/json
//   {
//     "message":  "User's latest message",
//     "language": "english" | "hindi" | "hinglish",
//     "history":  [ { "role": "user"|"bot", "content": "..." }, ... ]
//   }
//
//   200 OK
//   { "reply": "Bot's response text" }
//
// Swap the URL and request/response shapes to match your actual backend.
// ─────────────────────────────────────────────────────────────────────────────

/// Calls your own API and returns the bot reply string.
///
/// The SDK's [onCustomApiCall] hook receives the typed user message,
/// the current [LanguageTone], and the chat [history] so your backend
/// can maintain context.
Future<String> callMyApi({
  required String userMessage,
  required LanguageTone language,
  required List<Map<String, String>> history,
}) async {
  const url = 'https://your-api.example.com/chat'; // ← replace with your URL

  try {
    final response = await http.post(
      Uri.parse(url),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({
        'message':  userMessage,
        'language': language.name,          // 'english' | 'hindi' | 'hinglish'
        'history':  history,
      }),
    );

    if (response.statusCode == 200) {
      final data = jsonDecode(response.body) as Map<String, dynamic>;
      return data['reply'] as String? ?? 'Sorry, no reply received.';
    } else {
      return 'API error ${response.statusCode}: ${response.reasonPhrase}';
    }
  } catch (e) {
    return 'Could not reach the server. Please check your connection.';
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// HOME PAGE — language picker + demo buttons
// ─────────────────────────────────────────────────────────────────────────────

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  /// The currently selected language — drives ALL configs below.
  LanguageTone _selectedLang = LanguageTone.english;

  // ── Greeting per language ───────────────────────────────────────────────────
  String get _greeting => switch (_selectedLang) {
    LanguageTone.hindi    => 'नमस्ते! मैं ShopMart का सहायक हूँ। कैसे मदद करूँ?',
    LanguageTone.hinglish => 'Hello! Main ShopMart ka assistant hoon. Kaise help karun?',
    _                     => 'Hi! I am ShopMart\'s assistant. How can I help?',
  };

  // ── Config 1: Built-in engine with multilingual knowledge base ──────────────
  AarohConfig get _builtInConfig => AarohConfig(
    companyName:    'ShopMart',
    selectedLanguage: _selectedLang,           // ← tells the SDK which tone to use
    knowledgeBase:  buildKnowledgeBase(_selectedLang), // ← language-matched answers
    botGreeting:    _greeting,
    enableFeedback: true,
    enableAnalytics: true,
    fallbackReply: _answer(_selectedLang,
      en:       "I'm not sure about that. Try asking about delivery, EMI or returns.",
      hi:       'मुझे यह नहीं पता। डिलीवरी, EMI या वापसी के बारे में पूछें।',
      hinglish: 'Mujhe yeh nahi pata. Delivery, EMI ya returns ke baare mein poochhen.',
    ),
  );

  // ── Config 2: Claude API + language-aware knowledge base ───────────────────
  AarohConfig get _claudeConfig => AarohConfig(
    companyName:     'ShopMart',
    claudeApiKey:    'sk-ant-YOUR_KEY_HERE',   // ← add your key
    selectedLanguage: _selectedLang,
    knowledgeBase:   buildKnowledgeBase(_selectedLang),
    botGreeting:     _greeting,
    // Claude will be instructed to reply in the selected language
    // via the system prompt that the SDK builds automatically.
  );

  // ── Config 3: Your own custom API ──────────────────────────────────────────
  AarohConfig get _customApiConfig => AarohConfig(
    companyName:      'ShopMart',
    selectedLanguage: _selectedLang,
    knowledgeBase:    buildKnowledgeBase(_selectedLang),
    botGreeting:      _greeting,
    // Your API is wired in via the onCustomApiCall callback on pushAarohChat
    // (see the button handler below). The SDK skips its own engines and
    // streams your reply directly into the chat bubble.
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Aaroh Chat SDK Demo'),
        centerTitle: true,
      ),
      body: Center(
        child: SingleChildScrollView(
          padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [

              // ── Language picker ──────────────────────────────────────────
              const Text(
                'Select Language',
                style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500, color: Colors.grey),
              ),
              const SizedBox(height: 8),
              SegmentedButton<LanguageTone>(
                segments: const [
                  ButtonSegment(value: LanguageTone.english,  label: Text('English')),
                  ButtonSegment(value: LanguageTone.hindi,    label: Text('हिंदी')),
                  ButtonSegment(value: LanguageTone.hinglish, label: Text('Hinglish')),
                ],
                selected: {_selectedLang},
                onSelectionChanged: (sel) => setState(() => _selectedLang = sel.first),
              ),

              const SizedBox(height: 8),
              // Tip explaining what the picker does
              Text(
                'Choosing a language updates the knowledge base answers\n'
                    'and tells the bot which language to reply in.',
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 12, color: Colors.grey.shade600),
              ),

              const Divider(height: 48),

              // ── Demo 1: Built-in engine ──────────────────────────────────
              _DemoCard(
                icon: Icons.chat_bubble_outline,
                color: Colors.deepPurple,
                title: 'Built-in Engine',
                subtitle: 'No API key needed. Answers come from your knowledge base in the chosen language.',
                onTap: () => pushAarohChat(
                  context,
                  config: _builtInConfig,
                  onFeedback: (id, feedback, content, source) {
                    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                      content: Text('Feedback: ${feedback.name}'),
                    ));
                  },
                ),
              ),

              const SizedBox(height: 16),

              // ── Demo 2: Claude API ───────────────────────────────────────
              _DemoCard(
                icon: Icons.auto_awesome,
                color: Colors.indigo,
                title: 'Claude API',
                subtitle: 'Claude reads your multilingual knowledge base and replies in the chosen language.',
                onTap: () => pushAarohChat(
                  context,
                  config: _claudeConfig,
                ),
              ),

              const SizedBox(height: 16),

              // ── Demo 3: Custom API ───────────────────────────────────────
              _DemoCard(
                icon: Icons.cloud_outlined,
                color: Colors.teal,
                title: 'Custom API',
                subtitle: 'Your own backend endpoint handles all responses. Message, language & history are forwarded.',
                onTap: () => pushAarohChat(
                  context,
                  config: _customApiConfig,

                  // ← This callback fires for every user message.
                  //   The SDK awaits the returned string and displays it
                  //   as the bot reply. Returning null tells the SDK to
                  //   fall back to its own built-in engine.
                  onCustomApiCall: (userMessage, language, history) =>
                      callMyApi(
                        userMessage: userMessage,
                        language:    language,
                        history:     history,
                      ),
                ),
              ),

              const Divider(height: 48),

              // ── Embedded widget example ──────────────────────────────────
              OutlinedButton.icon(
                onPressed: () => Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (_) => AarohChatWidget(
                      config: _builtInConfig,
                    ),
                  ),
                ),
                icon: const Icon(Icons.open_in_new),
                label: const Text('Embedded Widget'),
              ),

            ],
          ),
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// Small reusable card widget for the demo buttons
// ─────────────────────────────────────────────────────────────────────────────

class _DemoCard extends StatelessWidget {
  const _DemoCard({
    required this.icon,
    required this.color,
    required this.title,
    required this.subtitle,
    required this.onTap,
  });

  final IconData icon;
  final Color color;
  final String title;
  final String subtitle;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 0,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12),
        side: BorderSide(color: color.withOpacity(0.3)),
      ),
      child: InkWell(
        borderRadius: BorderRadius.circular(12),
        onTap: onTap,
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Row(
            children: [
              CircleAvatar(
                backgroundColor: color.withOpacity(0.1),
                child: Icon(icon, color: color),
              ),
              const SizedBox(width: 16),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(title, style: const TextStyle(fontWeight: FontWeight.w600)),
                    const SizedBox(height: 4),
                    Text(subtitle,
                        style: TextStyle(fontSize: 12, color: Colors.grey.shade600)),
                  ],
                ),
              ),
              Icon(Icons.chevron_right, color: Colors.grey.shade400),
            ],
          ),
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// Dummy pricing page (for deep-link demo)
// ─────────────────────────────────────────────────────────────────────────────

class _PricingPage extends StatelessWidget {
  const _PricingPage();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Pricing')),
      body: const Center(child: Text('Pro plan — ₹999/month')),
    );
  }
}
5
likes
140
points
177
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter chat SDK by Aaroh for AI-powered conversations, featuring built-in NLP, Claude API integration, and branding options.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

fl_chart, flutter, google_fonts, http, intl, provider, shared_preferences, speech_to_text, url_launcher, uuid

More

Packages that depend on aaroh_chat