ai_tracker 0.1.2 copy "ai_tracker: ^0.1.2" to clipboard
ai_tracker: ^0.1.2 copied to clipboard

On-device observability (cost, latency, tokens, errors) for AI/LLM calls in Flutter. Local-first & zero-config, with optional opt-in sync to your backend.

example/lib/main.dart

import 'dart:math';

import 'package:ai_tracker/ai_tracker.dart';
import 'package:flutter/foundation.dart'
    show kIsWeb, defaultTargetPlatform, TargetPlatform;
import 'package:flutter/material.dart';

/// Picks the right host to reach the reference backend from each target.
// ignore: unused_element
String _syncEndpoint() {
  const path = '/api/ai-events';
  if (kIsWeb) return 'http://localhost:8000$path';
  if (defaultTargetPlatform == TargetPlatform.android) {
    return 'http://10.0.2.2:8000$path'; // Android emulator -> host machine
  }
  return 'http://localhost:8000$path'; // iOS simulator, desktop
}

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Local, zero-config. To try sync against the reference backend, swap for:
  // await AiTracker.init(
  //   syncEnabled: true,
  //   syncEndpoint: _syncEndpoint(),
  // );
  await AiTracker.init();

  runApp(const DemoApp());
}

class DemoApp extends StatelessWidget {
  const DemoApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ai_tracker demo',
      theme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        useMaterial3: true,
        brightness: Brightness.dark,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});
  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final _rnd = Random();
  int _sent = 0;

  static const _providers = [
    ('openai', 'gpt-4o'),
    ('anthropic', 'claude-sonnet-4'),
    ('gemini-nano', 'nano-2'), // on-device -> cost 0, no network
  ];

  /// Fakes an LLM round-trip so the demo runs with no API keys.
  Future<String> _fakeLlmCall() async {
    await Future<void>.delayed(
        Duration(milliseconds: 200 + _rnd.nextInt(1200)));
    if (_rnd.nextInt(10) == 0) throw Exception('simulated timeout');
    return 'response';
  }

  Future<void> _makeCall() async {
    final (provider, model) = _providers[_rnd.nextInt(_providers.length)];
    try {
      await AiTracker.track(
        provider: provider,
        model: model,
        operation: _fakeLlmCall,
        extractUsage: (_) => AiUsage(
          inputTokens: 50 + _rnd.nextInt(400),
          outputTokens: 50 + _rnd.nextInt(800),
        ),
      );
    } catch (_) {
      // error is tracked automatically; swallow for the demo
    }
    if (mounted) setState(() => _sent++);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('ai_tracker demo')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('Simulated calls made: $_sent',
                style: Theme.of(context).textTheme.titleMedium),
            const SizedBox(height: 20),
            FilledButton.icon(
              onPressed: _makeCall,
              icon: const Icon(Icons.bolt),
              label: const Text('Make a tracked AI call'),
            ),
            const SizedBox(height: 12),
            OutlinedButton.icon(
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (_) => Scaffold(
                    appBar: AppBar(title: const Text('AI Tracker')),
                    body: const AiTrackerDashboard(),
                  ),
                ),
              ),
              icon: const Icon(Icons.insights),
              label: const Text('Open dashboard'),
            ),
          ],
        ),
      ),
    );
  }
}
4
likes
160
points
61
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

On-device observability (cost, latency, tokens, errors) for AI/LLM calls in Flutter. Local-first & zero-config, with optional opt-in sync to your backend.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

drift, drift_flutter, flutter, http, sqlite3, sqlite3_flutter_libs, uuid, workmanager

More

Packages that depend on ai_tracker