ai_kit 0.1.0 copy "ai_kit: ^0.1.0" to clipboard
ai_kit: ^0.1.0 copied to clipboard

AI Integration Toolkit for Flutter. Multi-provider support (OpenAI, Gemini, Claude), streaming chat UI, smart widgets, and AI-powered components. Build AI features in minutes.

example/lib/main.dart

import 'package:ai_kit/ai_kit.dart';
import 'package:flutter/material.dart';

void main() {
  // Initialize AIKit with your provider(s)
  // Uncomment and add your API key:
  //
  // AIKit.init(
  //   providers: [
  //     OpenAIProvider(apiKey: 'sk-your-key-here'),
  //     // GeminiProvider(apiKey: 'AI-your-key-here'),
  //     // ClaudeProvider(apiKey: 'sk-ant-your-key-here'),
  //   ],
  // );

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'AI Kit Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: const Color(0xFF6C63FF),
        useMaterial3: true,
        brightness: Brightness.light,
      ),
      darkTheme: ThemeData(
        colorSchemeSeed: const Color(0xFF6C63FF),
        useMaterial3: true,
        brightness: Brightness.dark,
      ),
      home: const HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('AI Kit Examples')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _ExampleCard(
            title: 'Simple Chat',
            subtitle: 'Full-featured AI chat with streaming responses',
            icon: Icons.chat_bubble_outline,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => const SimpleChatExample()),
            ),
          ),
          const SizedBox(height: 12),
          _ExampleCard(
            title: 'Multi-Provider Chat',
            subtitle: 'Switch between OpenAI, Gemini, and Claude',
            icon: Icons.swap_horiz,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => const MultiProviderExample()),
            ),
          ),
          const SizedBox(height: 12),
          _ExampleCard(
            title: 'Quick Question',
            subtitle: 'Simple ask() API - one line AI call',
            icon: Icons.bolt,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => const QuickAskExample()),
            ),
          ),
          const SizedBox(height: 12),
          _ExampleCard(
            title: 'Custom Theme',
            subtitle: 'Fully themed chat interface',
            icon: Icons.palette,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => const ThemedChatExample()),
            ),
          ),
        ],
      ),
    );
  }
}

class _ExampleCard extends StatelessWidget {
  final String title;
  final String subtitle;
  final IconData icon;
  final VoidCallback onTap;

  const _ExampleCard({
    required this.title,
    required this.subtitle,
    required this.icon,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(
        leading: CircleAvatar(
          backgroundColor: Theme.of(context).colorScheme.primaryContainer,
          child: Icon(icon, color: Theme.of(context).colorScheme.primary),
        ),
        title: Text(title, style: const TextStyle(fontWeight: FontWeight.w600)),
        subtitle: Text(subtitle),
        trailing: const Icon(Icons.chevron_right),
        onTap: onTap,
      ),
    );
  }
}

// ─── Example 1: Simple Chat ─────────────────────────────────────────

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

  @override
  Widget build(BuildContext context) {
    final isInitialized = AIKit.isInitialized;

    return Scaffold(
      appBar: AppBar(title: const Text('Simple Chat')),
      body: isInitialized
          ? const AIChatView(
              systemPrompt:
                  'You are a friendly and helpful AI assistant. '
                  'Keep your responses concise and useful.',
              suggestions: [
                'Tell me a joke',
                'Explain quantum computing simply',
                'Write a haiku about Flutter',
              ],
              showUsage: true,
            )
          : const _NotInitializedView(),
    );
  }
}

// ─── Example 2: Multi-Provider ──────────────────────────────────────

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

  @override
  State<MultiProviderExample> createState() => _MultiProviderExampleState();
}

class _MultiProviderExampleState extends State<MultiProviderExample> {
  String? _selectedProvider;

  @override
  Widget build(BuildContext context) {
    if (!AIKit.isInitialized) {
      return Scaffold(
        appBar: AppBar(title: const Text('Multi-Provider Chat')),
        body: const _NotInitializedView(),
      );
    }

    final providers = AIKit.instance.providerNames;
    _selectedProvider ??= providers.isNotEmpty ? providers.first : null;

    return Scaffold(
      appBar: AppBar(
        title: const Text('Multi-Provider Chat'),
        actions: [
          if (providers.length > 1)
            PopupMenuButton<String>(
              icon: const Icon(Icons.swap_horiz),
              onSelected: (value) {
                setState(() => _selectedProvider = value);
              },
              itemBuilder: (context) => providers
                  .map(
                    (p) => PopupMenuItem(
                      value: p,
                      child: Row(
                        children: [
                          if (p == _selectedProvider)
                            const Icon(Icons.check, size: 18),
                          if (p != _selectedProvider) const SizedBox(width: 18),
                          const SizedBox(width: 8),
                          Text(p),
                        ],
                      ),
                    ),
                  )
                  .toList(),
            ),
        ],
      ),
      body: AIChatView(
        key: ValueKey(_selectedProvider),
        providerName: _selectedProvider,
        systemPrompt:
            'You are a helpful assistant. '
            'Mention that you are powered by $_selectedProvider.',
        showUsage: true,
        showCost: true,
      ),
    );
  }
}

// ─── Example 3: Quick Ask ───────────────────────────────────────────

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

  @override
  State<QuickAskExample> createState() => _QuickAskExampleState();
}

class _QuickAskExampleState extends State<QuickAskExample> {
  final _controller = TextEditingController();
  String? _answer;
  bool _isLoading = false;
  String? _error;

  Future<void> _ask() async {
    if (_controller.text.trim().isEmpty) return;

    setState(() {
      _isLoading = true;
      _error = null;
      _answer = null;
    });

    try {
      final answer = await AIKit.instance.ask(_controller.text);
      setState(() => _answer = answer);
    } catch (e) {
      setState(() => _error = e.toString());
    } finally {
      setState(() => _isLoading = false);
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (!AIKit.isInitialized) {
      return Scaffold(
        appBar: AppBar(title: const Text('Quick Ask')),
        body: const _NotInitializedView(),
      );
    }

    return Scaffold(
      appBar: AppBar(title: const Text('Quick Ask')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              'One line of code:',
              style: Theme.of(context).textTheme.titleMedium,
            ),
            const SizedBox(height: 4),
            Container(
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(
                color: Theme.of(context).colorScheme.surfaceContainerHighest,
                borderRadius: BorderRadius.circular(8),
              ),
              child: const Text(
                "final answer = await AIKit.instance.ask('...');",
                style: TextStyle(fontFamily: 'monospace', fontSize: 13),
              ),
            ),
            const SizedBox(height: 24),
            TextField(
              controller: _controller,
              decoration: InputDecoration(
                labelText: 'Ask anything...',
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12),
                ),
                suffixIcon: IconButton(
                  icon: _isLoading
                      ? const SizedBox(
                          width: 20,
                          height: 20,
                          child: CircularProgressIndicator(strokeWidth: 2),
                        )
                      : const Icon(Icons.send),
                  onPressed: _isLoading ? null : _ask,
                ),
              ),
              onSubmitted: (_) => _ask(),
            ),
            const SizedBox(height: 16),
            if (_answer != null)
              Expanded(
                child: Card(
                  child: Padding(
                    padding: const EdgeInsets.all(16),
                    child: SingleChildScrollView(
                      child: SelectableText(_answer!),
                    ),
                  ),
                ),
              ),
            if (_error != null)
              Card(
                color: Theme.of(context).colorScheme.errorContainer,
                child: Padding(
                  padding: const EdgeInsets.all(16),
                  child: Text(
                    _error!,
                    style: TextStyle(
                      color: Theme.of(context).colorScheme.onErrorContainer,
                    ),
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }
}

// ─── Example 4: Themed Chat ─────────────────────────────────────────

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

  @override
  Widget build(BuildContext context) {
    if (!AIKit.isInitialized) {
      return Scaffold(
        appBar: AppBar(title: const Text('Custom Theme')),
        body: const _NotInitializedView(),
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: const Text('Themed Chat'),
        backgroundColor: const Color(0xFF1A1A2E),
        foregroundColor: Colors.white,
      ),
      body: AIChatView(
        systemPrompt: 'You are a creative writing assistant.',
        theme: const AIChatTheme(
          primaryColor: Color(0xFFE94560),
          backgroundColor: Color(0xFF1A1A2E),
          surfaceColor: Color(0xFF16213E),
          userBubbleColor: Color(0xFFE94560),
          aiBubbleColor: Color(0xFF16213E),
          userTextColor: Colors.white,
          aiTextColor: Color(0xFFEEEEEE),
          textColor: Colors.white,
          secondaryTextColor: Colors.white54,
          inputBackgroundColor: Color(0xFF0F3460),
          inputBorderColor: Color(0xFF533483),
          errorColor: Color(0xFFFF6B6B),
          showTimestamp: true,
        ),
        suggestions: [
          'Write a short story opening',
          'Create a character description',
          'Describe a fantasy world',
        ],
      ),
    );
  }
}

// ─── Helper: Not Initialized View ───────────────────────────────────

class _NotInitializedView extends StatelessWidget {
  const _NotInitializedView();

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(32),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(
              Icons.warning_amber_rounded,
              size: 64,
              color: Theme.of(context).colorScheme.error,
            ),
            const SizedBox(height: 16),
            Text(
              'AIKit Not Initialized',
              style: Theme.of(context).textTheme.headlineSmall,
            ),
            const SizedBox(height: 8),
            const Text(
              'Open main.dart and uncomment the AIKit.init() call '
              'with your API key to try this example.',
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 24),
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Theme.of(context).colorScheme.surfaceContainerHighest,
                borderRadius: BorderRadius.circular(12),
              ),
              child: const SelectableText(
                "AIKit.init(\n"
                "  providers: [\n"
                "    OpenAIProvider(apiKey: 'sk-...'),\n"
                "  ],\n"
                ");",
                style: TextStyle(fontFamily: 'monospace', fontSize: 13),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
1
likes
160
points
132
downloads
screenshot

Publisher

verified publisherthesanaullah.dev

Weekly Downloads

AI Integration Toolkit for Flutter. Multi-provider support (OpenAI, Gemini, Claude), streaming chat UI, smart widgets, and AI-powered components. Build AI features in minutes.

Repository (GitHub)
View/report issues

Topics

#ai #openai #gemini #chatbot #machine-learning

Documentation

API reference

License

MIT (license)

Dependencies

flutter, http, shared_preferences

More

Packages that depend on ai_kit