Vanira Flutter SDK — Scaffold

Status: Scaffold only. The protocol and session class are defined. Full implementation requires wiring flutter_webrtc into VaniraSession.


Architecture

The Flutter SDK mirrors the TypeScript SDK's core layer exactly. The signaling protocol, DataChannel event schema, and state machine are identical. Only the runtime (Dart vs JavaScript) and platform APIs differ.

flutter-sdk/
  lib/
    src/
      vanira_session.dart   ← Core session — mirrors TypeScript WebRTCClient
    vanira_sdk.dart         ← Public export
  pubspec.yaml
  README.md

TypeScript → Dart mapping

TypeScript (npm SDK) Dart (Flutter SDK)
new RTCPeerConnection(config) createPeerConnection(config) (flutter_webrtc)
navigator.mediaDevices.getUserMedia() navigator.mediaDevices.getUserMedia() (flutter_webrtc)
pc.createDataChannel('control', {}) pc.createDataChannel('control', RTCDataChannelInit())
pc.createOffer() await pc.createOffer({})
pc.setLocalDescription(offer) await pc.setLocalDescription(offer)
pc.setRemoteDescription(answer) await pc.setRemoteDescription(...)
pc.onConnectionState = handler pc.onConnectionState.listen(handler)
pc.onIceGatheringState listener pc.onIceGatheringState.listen(handler)
fetch(url, { method: 'POST', ... }) http.post(Uri.parse(url), body: jsonEncode(...))
JSON.stringify / JSON.parse jsonEncode / jsonDecode (dart:convert)
new Audio() + srcObject Not needed — flutter_webrtc routes audio automatically
setTimeout(fn, 5000) Future.delayed(const Duration(seconds: 5), fn)
Promise / async-await Future / async-await (same pattern)
onConnected callback VoidCallback / Function()
onTranscription callback Function(String text, bool isFinal)

DataChannel protocol

The event schema is identical to the browser/RN SDK. Dart's jsonDecode produces Map<String, dynamic> which maps directly to the TypeScript interface.

Server → client events

event payload fields action
clearAudio No-op (flutter_webrtc manages audio)
transcription text, isFinal Call onTranscription(text, isFinal)
mark name Log only
client_tool_call tool_call_id, name, arguments Send ack immediately, call onClientToolCall

Client → server events

method event name payload
sendToolResult(id, res) client_tool_result { call_id, result }
sendContextUpdate(ctx) client_context_update { data: { context } }
sendActionTrigger(name) client_action_trigger { data: { action_name, data } }
triggerActionInterrupt() action_interrupt

Implementation steps

1. Add dependencies to pubspec.yaml

dependencies:
  flutter_webrtc: ^0.9.0
  http: ^1.2.0
  permission_handler: ^11.0.0

2. Request microphone permission

import 'package:permission_handler/permission_handler.dart';
await Permission.microphone.request();

3. Register globals (Android / iOS)

// In main.dart before runApp()
import 'package:flutter_webrtc/flutter_webrtc.dart';
// No explicit registerGlobals() needed in flutter_webrtc >= 0.9
// flutter_webrtc auto-initializes on first API call

4. Wire VaniraSession.connect()

Uncomment and implement all TODO blocks in lib/src/vanira_session.dart. Each TODO maps to a numbered step in the TypeScript SDK's connect() method.

5. HTTP signaling (already portable)

The signaling endpoint and JSON body are identical to the TypeScript SDK:

final response = await http.post(
  Uri.parse('$serverUrl/webrtc?agent=${agentId}_$callId'),
  headers: {'Content-Type': 'application/json'},
  body: jsonEncode({
    'offer': offer.toMap(),
    'agentId': agentId,
    'callId': callId,
  }),
);
final answer = jsonDecode(response.body)['answer'];

6. Distribution

Publish to pub.flutter-io.cn as vanira_sdk:

name: vanira_sdk
version: 0.0.1
homepage: https://vanira.io
repository: https://github.com/vanira-ai/flutter-sdk

Known differences from browser/RN SDK

Topic Browser / RN Flutter
Audio output new Audio() / native stack Automatic via flutter_webrtc
playedStream event Sent when audio.onended fires Never sent — no onended equiv.
Screen share Browser: getDisplayMedia(); RN: N/A N/A — not supported
CDN distribution <script> tag via unpkg flutter pub add vanira_sdk
Widget <vanira-convai> custom element Flutter StatefulWidget
State management React hooks / Redux Riverpod / Provider / setState
Env vars import.meta.env.VITE_* flutter_dotenv or const String.fromEnvironment

Libraries

vanira_sdk
Vanira Voice AI — Flutter SDK (local vanira-sdk/flutter-sdk).