### Setup and Run iOS Slogan Example Source: https://github.com/liquid4all/leapsdk-examples/blob/main/README.md Commands to set up and open the LeapSloganExample on iOS. ```bash cd iOS/LeapSloganExample make setup && make open ``` -------------------------------- ### Run Development Server Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Web/LeapVoiceAssistantDemo/README.md Starts a local development server for the Compose-for-Web application. Ensure JDK 21 is installed and accessible via JAVA_HOME. ```bash JAVA_HOME="$(/usr/libexec/java_home -v 21)" ./gradlew wasmJsBrowserDevelopmentRun ``` -------------------------------- ### Setup and Run LeapAudioDemo Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Commands to set up and open the LeapAudioDemo project in Xcode. ```bash cd LeapAudioDemo make setup make open # Opens in Xcode ``` -------------------------------- ### Setup and Run LeapSloganExample Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Commands to set up and open the LeapSloganExample project in Xcode. ```bash cd LeapSloganExample make setup make open # Opens in Xcode ``` -------------------------------- ### Setup Project with Makefile Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Run this command to set up the project dependencies and configurations. ```bash make setup ``` -------------------------------- ### Setup and Run LeapChatExample Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Commands to set up and open the LeapChatExample project in Xcode. ```bash cd LeapChatExample make setup make open # Opens in Xcode ``` -------------------------------- ### Open Project in Xcode Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Use this command to open the project in Xcode after setup. ```bash make open ``` -------------------------------- ### Synchronous Cleanup for Resource Initialization Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Always perform synchronous cleanup of existing resources before creating new ones to prevent race conditions. This example shows the correct way to start streaming. ```kotlin // ✅ Good - synchronous cleanup fun startStreaming() { audioTrack?.stop() audioTrack?.release() audioTrack = null audioTrack = AudioTrack.Builder()...build() } // ❌ Bad - async cleanup causes race fun startStreaming() { scope.launch { reset() } // Returns immediately! audioTrack = AudioTrack.Builder()...build() // Can be nulled by reset() } ``` -------------------------------- ### Constrained Generation with @Generatable and @Guide Macros Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Demonstrates how to define a Codable struct with @Guide macros for structured output and configure generation options to use JSON schema constraints. This is useful for generating specific data formats like product recommendations. ```swift import LeapSDK import LeapSDKMacros @Generatable("Simple product recommendation") struct ProductRecommendation: Codable { @Guide("Product name") let name: String @Guide("Category") let category: String @Guide("Price in USD") let price: Double @Guide("Short recommendation reason") let reason: String @Guide("List of key features") let features: [String] } // Set up constrained generation options let options = GenerationOptions() options.jsonSchemaConstraint = ProductRecommendation.jsonSchema() // generateResponse(message:generationOptions:) returns a raw Kotlin flow; // bridge it to SkieSwiftFlow for async iteration let rawFlow = conversation.generateResponse(message: userMessage, generationOptions: options) let stream = rawFlow as! SkieSwiftFlow var jsonResponse = "" for try await response in stream { switch onEnum(of: response) { case .chunk(let chunk): jsonResponse.append(chunk.text) default: break } } // Decode the JSON response let result = try JSONDecoder().decode(ProductRecommendation.self, from: Data(jsonResponse.utf8)) ``` -------------------------------- ### Logging Strategy Examples Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Demonstrates logging entry/exit points and error handling with stack traces. ```kotlin Log.d(TAG, "Starting streaming playback job") Log.e(TAG, "Failed to request audio focus", exception) ``` -------------------------------- ### Clean and Setup Project Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Commands to clean build artifacts and re-setup the project, useful for troubleshooting build issues. ```bash make clean make setup ``` -------------------------------- ### Open Xcode Project Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Open the generated Xcode project file to start development or run the application. ```bash open macOS/LeapVoiceAssistantDemo/LeapVoiceAssistantDemo.xcodeproj ``` -------------------------------- ### Run Web Voice Assistant Example Source: https://github.com/liquid4all/leapsdk-examples/blob/main/README.md Commands to run the LeapVoiceAssistantDemo in development mode for Web (Kotlin/Wasm). ```bash cd Web/LeapVoiceAssistantDemo ./gradlew wasmJsBrowserDevelopmentRun # open http://localhost:8080 ``` -------------------------------- ### Install XcodeGen Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Command to install XcodeGen using Homebrew, required for project generation. ```bash brew install xcodegen ``` -------------------------------- ### Generate Project for RecipeGenerator Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Commands to generate the Xcode project for the RecipeGenerator example. ```bash cd RecipeGenerator xcodegen generate open RecipeGenerator.xcodeproj ``` -------------------------------- ### Install Android Debug App Source: https://github.com/liquid4all/leapsdk-examples/blob/main/README.md Command to install the debug version of the SloganApp on Android. ```bash cd Android/SloganApp ./gradlew installDebug ``` -------------------------------- ### Log and Handle Exceptions Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Example of properly logging and handling exceptions instead of silently swallowing them. ```kotlin // ✅ Log and handle try { operation() } catch (e: Exception) { Log.e(TAG, "Operation failed", e) _state.update { it.copy(error = e.message) } } ``` -------------------------------- ### Build and Run Android App Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Android/LeapAudioDemo/README.md Execute the Gradle wrapper command to build and install the debug version of the Android application. ```bash ./gradlew installDebug ``` -------------------------------- ### Generate Xcode Project Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/RecipeGenerator/README.md Use XcodeGen to create the Xcode project files for the LeapSDK example. ```bash xcodegen ``` -------------------------------- ### Conventional Commits Example Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Follow the Conventional Commits specification for commit messages, including type, scope, and description. Examples cover feature additions, bug fixes, and refactoring. ```git feat: add graceful streaming completion for audio playback fix: resolve race condition in audio streaming initialization refactor: extract string provider interface for testability ``` -------------------------------- ### Integration Test for Rapid Start/Stop Recording Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md An integration test to ensure that rapid start and stop recording events do not corrupt the audio state. ```kotlin @Test fun `rapid start stop recording should not cause state corruption`() = runTest { repeat(10) { viewModel.onEvent(AudioDemoEvent.StartRecording) viewModel.onEvent(AudioDemoEvent.StopRecording) } viewModel.state.value.recordingState shouldBe RecordingState.Idle } ``` -------------------------------- ### ViewModel Test Structure with Fakes Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Example of a unit test structure using a ViewModel and a fake audio playback implementation to test behavior. ```kotlin @Test fun `descriptive test name describing behavior`() = runTest { // Arrange val viewModel = AudioDemoViewModel( application = app, audioPlayback = fakeAudioPlayback, ) // Act viewModel.onEvent(AudioDemoEvent.PlayAudio(...)) // Assert fakeAudioPlayback.playCallCount shouldBe 1 viewModel.state.value.isPlaying shouldBe true } ``` -------------------------------- ### Request Microphone Permission Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Example of requesting microphone permission when the model state indicates loading, using LaunchedEffect. ```kotlin // Request permissions only when needed LaunchedEffect(state.modelState) { if (state.modelState is ModelState.Loading) { permissionLauncher.launch(arrayOf( Manifest.permission.RECORD_AUDIO )) } } ``` -------------------------------- ### Build Static Bundle Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Web/LeapVoiceAssistantDemo/README.md Compiles the Kotlin/Wasm project into a self-contained static bundle for deployment. Ensure JDK 21 is installed and accessible via JAVA_HOME. ```bash JAVA_HOME="$(/usr/libexec/java_home -v 21)" ./gradlew wasmJsBrowserDistribution ``` -------------------------------- ### Configure Code Signing in project.yml Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Example of how to configure automatic code signing and specify a development team within the `project.yml` file for running on a physical iOS device. ```yaml targets: YourTarget: settings: base: DEVELOPMENT_TEAM: YOUR_TEAM_ID CODE_SIGN_STYLE: Automatic ``` -------------------------------- ### Push Model to Android Device Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Android/LeapKoogAgent/README.md Use this command to copy the AI model bundle to the specified directory on your Android device. Ensure ADB is installed and the device is connected. ```bash adb push lfm2-1.2b-tool.bundle /tmp/models ``` -------------------------------- ### Common Makefile Tasks Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md A list of common tasks available in the Makefile for example projects, used for build automation. ```bash make setup # Generate Xcode project make build # Build the project make run # Build and run on simulator make clean # Clean generated files make open # Open project in Xcode ``` -------------------------------- ### Create Conversation Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Create a new multi-turn conversation instance, optionally providing a system prompt to guide the assistant's behavior. ```swift runner.createConversation(systemPrompt:) ``` -------------------------------- ### Channel for Hot Streams Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Utilize Channel for hot streams requiring backpressure, such as producer-consumer scenarios. This example shows a bounded channel. ```kotlin val channel = Channel(capacity = 100) // Bounded ``` -------------------------------- ### Swift Interoperability with Kotlin Enums Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapVoiceAssistantDemo/README.md Note on how Kotlin enum entries are lowercased when accessed in Swift due to ObjC interoperability. Examples include VoiceWidgetMode.IDLE becoming .idle. ```swift VoiceWidgetMode.IDLE → .idle VoiceWidgetMode.LISTENING → .listening ``` -------------------------------- ### Build and Run Project with Make Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapChatExample/README.md Builds the project and runs it on a simulator or device. This command may also include running tests. ```bash make build ``` -------------------------------- ### Open Xcode Project Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapVoiceAssistantDemo/README.md Command to open the generated Xcode project file in Xcode. ```bash open iOS/LeapVoiceAssistantDemo/LeapVoiceAssistantDemo.xcodeproj ``` -------------------------------- ### Use Bounded Collections for Streaming Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Shows how to use a bounded collection with a documented limit to prevent OutOfMemoryErrors when handling streaming audio samples. ```kotlin // ✅ Bounded with documented limits val audioSamples = ArrayList(720_000) // 30 sec max ``` -------------------------------- ### Fake Audio Playback Implementation for Testing Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Create a fake implementation of the AudioPlayback interface for testing purposes, tracking play call counts and simulating callbacks. ```kotlin class FakeAudioPlayback : AudioPlayback { var isPlaying = false private set var playCallCount = 0 private set var lastSamples: FloatArray? = null private set override fun play(samples: FloatArray, sampleRate: Int) { playCallCount++ lastSamples = samples isPlaying = true } // Simulate callbacks for testing fun simulatePlaybackCompleted() { isPlaying = false onPlaybackCompleted?.invoke() } } ``` -------------------------------- ### Calculating and Documenting Buffer Sizes Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Pre-allocate collections with calculated sizes based on requirements like sample rate and duration. Documenting these calculations aids in understanding memory usage. ```kotlin // Pre-allocate for ~30 seconds of audio at 24kHz sample rate // (24,000 samples/sec × 30 sec = 720,000 samples ≈ 2.88 MB) val audioBuffer = ArrayList(720_000) ``` -------------------------------- ### Load Model and Generate Response with LeapSDK Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Demonstrates loading a model using LeapSDK and generating a response with streaming. Ensure LeapSDK is imported. ```swift import LeapSDK // Load a model by name and quantization let modelRunner = try await Leap.shared.load( model: "LFM2-350M", quantization: "Q4_0", progress: { progress, speed in print("Download progress: \(Int(progress * 100))%") } ) // Create a conversation let conversation = Conversation(modelRunner: modelRunner, history: []) // Generate response with streaming let stream = conversation.generateResponse(message: ChatMessage(role: .user, content: ChatMessageContent.text("Hello, AI!")) ) for try await response in stream { switch onEnum(of: response) { case .chunk(let chunk): print(chunk.text) case .complete(let completion): print("Done: \(completion.fullMessage)") default: break } } ``` -------------------------------- ### Instantiate VoiceAssistantNSViewController Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Create an instance of VoiceAssistantNSViewController, which wraps the Compose UI for the voice assistant. ```swift VoiceAssistantNSViewControllerKt.VoiceAssistantNSViewController(…) ``` -------------------------------- ### Run All Unit Tests Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Android/LeapAudioDemo/app/src/test/kotlin/README.md Execute all unit tests for the project. This command is useful for a full test suite verification. ```bash ./gradlew test ``` -------------------------------- ### Show Explanation on Permission Denial Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Displays a message to the user if microphone permission is denied, explaining its necessity. ```kotlin // Show clear explanations on denial if (deniedPermissions.contains(Manifest.permission.RECORD_AUDIO)) { snackbar.show("Microphone permission required for audio recording") } ``` -------------------------------- ### Import LeapUi Framework Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Import the LeapUi framework to use its UI components and state management. ```swift import LeapUi ``` -------------------------------- ### Initialize VoiceAssistantState Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Create an immutable snapshot of the VoiceAssistant widget's state, including its mode and amplitude. ```swift VoiceAssistantState(mode:amplitude:) ``` -------------------------------- ### Run Unit Tests with Coverage Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Android/LeapAudioDemo/app/src/test/kotlin/README.md Execute all unit tests and generate a code coverage report. This helps in identifying untested parts of the codebase. ```bash ./gradlew testDebugUnitTestCoverage ``` -------------------------------- ### Generate Xcode Project with xcodegen Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapVoiceAssistantDemo/README.md Run this command in the iOS/LeapVoiceAssistantDemo directory to generate the Xcode project file from the project.yml specification. ```bash cd iOS/LeapVoiceAssistantDemo xcodegen generate ``` -------------------------------- ### Configure Audio Model Parameters Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Android/LeapAudioDemo/README.md Set the model name, quantization method, and multi-turn support in AudioDemoViewModel.kt. Note that the audio model does not support multi-turn conversations. ```kotlin private const val MODEL_NAME = "LFM2.5-Audio-1.5B" private const val QUANTIZATION = "Q4_0" private const val ENABLE_MULTI_TURN = false // Audio model doesn't support multi-turn ``` -------------------------------- ### Load Leap Model Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Download and load the specified Leap model with a given quantization level. Progress is reported via a closure. ```swift Leap.shared.load(model:quantization:progress:) ``` -------------------------------- ### AudioPlaybackManager Class Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Manages audio output. Use the `play` method to play audio from a given URL. ```swift @MainActor class AudioPlaybackManager: NSObject, ObservableObject { func play(url: URL) async { } } ``` -------------------------------- ### Setting Buffer Limits for Audio Streaming Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Use bounded channels or pre-allocate collections with a known capacity to manage memory and prevent OutOfMemoryErrors during audio streaming. ```kotlin // Bounded channel val audioQueue = Channel(capacity = 100) // Pre-allocated buffer val audioBuffer = ArrayList(720_000) // 30 sec @ 24kHz ``` -------------------------------- ### Project Configuration for Permissions Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Specifies required permissions for the app in the XcodeGen configuration file. Microphone access is needed for audio input, and background modes allow audio processing to continue. ```yaml INFOPLIST_KEY_NSMicrophoneUsageDescription: "Audio input is used to capture prompts." INFOPLIST_KEY_UIBackgroundModes: "audio" ``` -------------------------------- ### Import LeapSDK Framework Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Import the LeapSDK framework to access core functionalities like model loading and conversation management. ```swift import LeapSDK ``` -------------------------------- ### Compose Optimization with remember Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Shows how to use the `remember` function to cache derived values and prevent unnecessary recompositions in Jetpack Compose. ```kotlin val isEnabled = remember(state.modelState) { state.modelState is ModelState.Ready } ``` -------------------------------- ### Audio Player Completion Callbacks Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Implement callbacks to be invoked when the audio buffer is fully drained or when streaming is completed. ```kotlin class AudioPlayer( private val onPlaybackCompleted: (() -> Unit)? = null, private val onStreamingCompleted: (() -> Unit)? = null, ) { // Invoke callback when buffer is fully drained for (samples in queue) { track.write(samples, ...) } onStreamingCompleted?.invoke() } ``` -------------------------------- ### Generate Xcode Project with xcodegen Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Run this command in the project directory to generate the Xcode project file from the project.yml specification. ```bash cd macOS/LeapVoiceAssistantDemo xcodegen generate ``` -------------------------------- ### Use Monotonic Clock for Intervals Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Demonstrates the correct way to measure elapsed time using a monotonic clock, avoiding issues with system time changes. ```kotlin // ✅ Use monotonic clock val elapsed = SystemClock.elapsedRealtime() - startTime ``` -------------------------------- ### Load LeapSDK Audio Model Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Configures the LeapSDK to load a local audio AI model. Ensure the model file path is correct. ```swift let modelRunner = try await Leap.load( modelPath: Bundle.main.bundlePath + "/LFM2-Audio-1.5B-Q8_0.gguf" ) ``` -------------------------------- ### AudioRecorder Class Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Handles microphone input. Provides `startRecording` and `stopRecording` methods to manage audio capture. ```swift @MainActor class AudioRecorder: NSObject, ObservableObject { @Published var isRecording = false func startRecording() { } func stopRecording() { } } ``` -------------------------------- ### Fire-and-Forget for Main Thread Cleanup Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Demonstrates a fire-and-forget approach using CoroutineScope(Dispatchers.IO).launch for non-blocking cleanup operations in onCleared(). ```kotlin // ✅ Fire-and-forget for cleanup override fun onCleared() { CoroutineScope(Dispatchers.IO).launch { try { heavyOperation() } catch (e: Exception) { Log.e(TAG, "Cleanup failed", e) } } } ``` -------------------------------- ### Configure GitHub Packages Authentication Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Android/LeapAudioDemo/README.md Set environment variables for GitHub Packages authentication before building. This is required for downloading Leap SDK dependencies. ```bash export GITHUB_PACKAGES_USERNAME="your-github-username" export GITHUB_PACKAGES_TOKEN="your-github-personal-access-token" ``` -------------------------------- ### Configure Excluded Architectures for Intel Simulators Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapVoiceAssistantDemo/README.md Add this build setting to exclude x86_64 architectures, which is necessary for running on Intel Mac simulators as XCFrameworks are ARM64-only. ```swift EXCLUDED_ARCHS = x86_64 ``` -------------------------------- ### Requesting Audio Focus Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Properly request audio focus using `AudioFocusRequest.Builder` and handle focus changes, such as `AUDIOFOCUS_LOSS`, by stopping playback and abandoning focus. ```kotlin private fun requestAudioFocus(): Boolean { val request = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes( AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .build() ) .setOnAudioFocusChangeListener { focusChange -> when (focusChange) { AudioManager.AUDIOFOCUS_LOSS -> { stop() abandonAudioFocus() } } } .build() return audioManager.requestAudioFocus(request) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED } ``` -------------------------------- ### Flow for Cold Streams Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Use Flow for cold streams and reactive data sources. This snippet demonstrates creating a Flow that emits loaded data. ```kotlin val dataFlow: Flow = flow { emit(loadData()) } ``` -------------------------------- ### Build for iOS Simulator Excluding x86_64 Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Command to build the project for the iOS Simulator while excluding the x86_64 architecture, necessary due to LeapSDK xcframeworks only including arm64 slices for simulators. ```bash xcodebuild -scheme YourScheme \ -destination 'generic/platform=iOS Simulator' \ build EXCLUDED_ARCHS=x86_64 ``` -------------------------------- ### LeapSDK GitHub Repository Reference Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Shows how to reference the LeapSDK from GitHub in your `project.yml` file, specifying the repository URL and exact version. ```yaml packages: LeapSDK: url: https://github.com/Liquid4All/leap-sdk exactVersion: 0.10.0 ``` -------------------------------- ### Real-time Token Streaming Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapChatExample/README.md Demonstrates how to process AI responses token by token for a live, streaming effect in the chat interface. Updates the UI with each received token. ```swift for try await chunk in modelRunner.generateResponse(for: conversation) { if let delta = chunk.delta { // Update UI with each token lastMessage.content.appendText(delta) } } ``` -------------------------------- ### LeapSDK Package Configuration in project.yml Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Specifies how to reference the LeapSDK and LeapSDKMacros products in your project's `project.yml` file for Swift Package Manager integration. Includes necessary linker flags for the inference engine. ```yaml packages: LeapSDK: url: https://github.com/Liquid4All/leap-sdk exactVersion: 0.10.0 targets: YourApp: dependencies: - package: LeapSDK product: LeapModelDownloader # Includes LeapSDK; adds manifest downloading # Add LeapSDKMacros if using @Generatable/@Guide macros: - package: LeapSDK product: LeapSDKMacros settings: base: # Required to link the inference engine dynamic libraries OTHER_LDFLAGS: "$(inherited) -L$(BUILT_PRODUCTS_DIR)/LeapSDK.framework/Frameworks -linference_engine -linference_engine_llamacpp_backend" LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks @executable_path/Frameworks/LeapSDK.framework/Frameworks" ``` -------------------------------- ### Coroutine Dispatchers for Different Tasks Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Use Dispatchers.IO for I/O operations, Dispatchers.Default for CPU-intensive work, and Dispatchers.Main for UI updates. Prefer coroutines over manual thread management. ```kotlin viewModelScope.launch(Dispatchers.IO) { val result = loadData() } // ❌ Bad Thread { val result = loadData() }.start() ``` -------------------------------- ### Releasing Audio Resources Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Ensure all audio resources like `AudioTrack` are properly stopped and released to free up system resources and prevent issues. ```kotlin audioTrack?.apply { stop() release() } audioTrack = null ``` -------------------------------- ### AudioDemoView Struct Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Represents the SwiftUI interface for the audio demo. It uses `AudioDemoStore` to manage state and logic. ```swift struct AudioDemoView: View { @StateObject private var store = AudioDemoStore() // UI implementation } ``` -------------------------------- ### Convert Float Samples to Audio Content Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Convert raw float PCM audio samples and their sample rate into an Audio content format usable by the SDK. ```swift ChatMessageContent.fromFloatSamples(_:sampleRate:) ``` -------------------------------- ### Load Local AI Model Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapSloganExample/README.md This code snippet shows how to load a local AI model using LeapSDK. Ensure the model path is correct. ```swift let modelRunner = try await Leap.load( modelPath: Bundle.main.bundlePath + "/qwen3-1_7b_8da4w.bundle" ) ``` -------------------------------- ### Android Formatting with ktfmt Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Configure ktfmt with Google style for Kotlin code formatting in Android modules. Run `./gradlew ktfmtFormat` to format before committing. ```gradle com.ncorti.ktfmt.gradle plugin ktfmt { googleStyle() } ``` -------------------------------- ### Initialize VoiceAssistantStateHolder Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Initialize an observable bridge for VoiceAssistantState, used for Compose recomposition in SwiftUI. ```swift VoiceAssistantStateHolder(initial:) ``` -------------------------------- ### Run Specific Test Class Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Android/LeapAudioDemo/app/src/test/kotlin/README.md Execute tests only for a specified test class, such as AudioDemoViewModelTest. This is useful for focused testing during development. ```bash ./gradlew test --tests AudioDemoViewModelTest ``` -------------------------------- ### AudioDemoStore Class Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapAudioDemo/README.md Manages LeapSDK interaction and audio processing. Use the `processAudio` function to integrate LeapSDK with audio handling. ```swift @MainActor class AudioDemoStore: ObservableObject { @Published var isRecording = false @Published var isProcessing = false func processAudio(_ url: URL) async { // LeapSDK audio integration } } ``` -------------------------------- ### Audio State Data Class Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Define a data class to clearly track different audio states such as recording, playing, and streaming playback. ```kotlin data class AudioState( val isRecording: Boolean = false, val isPlaying: Boolean = false, val isStreamingPlayback: Boolean = false, // Buffer draining val playingMessageId: String? = null, ) ``` -------------------------------- ### Avoid Async Cleanup Race Condition Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Illustrates a race condition where async cleanup might interfere with new resource creation. Avoid this pattern. ```kotlin // ❌ Race condition - reset() returns immediately fun start() { reset() // Launches async job resource = createResource() // Can be nulled by reset() } ``` -------------------------------- ### MVI State Definition Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Define the UI state for MVI pattern using a data class. Initialize with default values for items, loading status, and error messages. ```kotlin data class MyState( val items: List = emptyList(), val isLoading: Boolean = false, val error: String? = null, ) ``` -------------------------------- ### SloganStore Class Definition Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapSloganExample/README.md This class manages LeapSDK interaction for slogan generation. It includes state for the generated slogan and generation status. ```swift @MainActor class SloganStore: ObservableObject { @Published var slogan = "" @Published var isGenerating = false func generateSlogan(for topic: String) async { // LeapSDK integration } } ``` -------------------------------- ### Graceful Audio Streaming Completion Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Close the audio queue to allow buffered audio to play out after generation completes, or to stop streaming immediately. ```kotlin // Allow buffered audio to play out after generation completes fun finishStreaming() { audioQueue?.close() // Close channel but don't cancel playback } // Immediate stop fun stopStreaming() { streamingJob?.cancel() audioQueue?.close() audioTrack?.stop() } ``` -------------------------------- ### MVI Composable Usage Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Implement the UI screen using Jetpack Compose. The composable receives the current state and an event handler function, not the ViewModel directly. ```kotlin @Composable fun MyScreen(state: MyState, onEvent: (MyEvent) -> Unit) { // UI receives state and event handler, not ViewModel Button(onClick = { onEvent(MyEvent.LoadData) }) { Text("Load") } } ``` -------------------------------- ### Enable Macro Trust via Defaults Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/README.md Command to bypass the macro trust prompt in Xcode for command-line builds by setting a user default. This is required when building LeapSloganExample. ```bash defaults write com.apple.dt.Xcode IDESkipMacroFingerprintValidation -bool YES ``` -------------------------------- ### ChatStore Class Definition Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapChatExample/README.md The core business logic and state management for the chat application. It manages messages and the generation state. ```swift @MainActor class ChatStore: ObservableObject { @Published var messages: [ChatMessage] = [] @Published var isGenerating = false func sendMessage(_ text: String) async { // Handle message sending and AI response } } ``` -------------------------------- ### Android String Resources Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Use string resources instead of hardcoded strings for all user-facing text in Android UI. Add new entries to res/values/strings.xml. ```kotlin Text(stringResource(R.string.recording_stopped)) ``` -------------------------------- ### Generate Response with Streaming Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Generate a response to a user message within a conversation. This method supports streaming inference. ```swift conversation.generateResponse(message:generationOptions:) ``` -------------------------------- ### Structured Concurrency with supervisorScope Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Employ structured concurrency using supervisorScope to manage child coroutines, ensuring proper cancellation and error handling within a scope. ```kotlin viewModelScope.launch { supervisorScope { launch { task1() } launch { task2() } } } ``` -------------------------------- ### MVI ViewModel Structure Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Implement the ViewModel for MVI pattern using Kotlin's StateFlow. Expose the state and provide an onEvent function to handle incoming events and update the state. ```kotlin class MyViewModel : ViewModel() { private val _state = MutableStateFlow(MyState()) val state: StateFlow = _state.asStateFlow() fun onEvent(event: MyEvent) { when (event) { is MyEvent.LoadData -> loadData() is MyEvent.UpdateItem -> updateItem(event.id) } } private fun loadData() { _state.update { it.copy(isLoading = true) } // ... implementation } } ``` -------------------------------- ### Abandoning Audio Focus Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Call `abandonAudioFocusRequest` when audio playback is complete or interrupted to release audio focus and allow other apps to play sound. ```kotlin audioManager.abandonAudioFocusRequest(focusRequest) ``` -------------------------------- ### Set Maximum Recording Duration Source: https://github.com/liquid4all/leapsdk-examples/blob/main/Android/LeapAudioDemo/README.md Define the maximum duration for audio recordings in seconds within AudioRecorder.kt. This helps prevent memory issues. ```kotlin private const val MAX_RECORDING_SECONDS = 60 // Maximum recording duration ``` -------------------------------- ### ContentView Structure Definition Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapChatExample/README.md The main chat interface of the application, composed of message list and input views. It uses ChatStore for state management. ```swift struct ContentView: View { @StateObject private var chatStore = ChatStore() var body: some View { VStack { MessagesListView(messages: chatStore.messages) ChatInputView(onSend: chatStore.sendMessage) } } } ``` -------------------------------- ### Adding a Message to Conversation Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapChatExample/README.md Shows how to add a new message, typically from the user, to the ongoing conversation history to maintain context. ```swift conversation.addMessage(ChatMessage( role: .user, content: .text(messageText) )) ``` -------------------------------- ### Inference Complete Notification Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Indicates that the inference generation is complete, often including statistics about the process. ```swift MessageResponseComplete ``` -------------------------------- ### ViewModel Resource Cleanup in onCleared() Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Implement resource cleanup in `onCleared()` to prevent memory leaks. This includes cancelling coroutine jobs and releasing resources, with special handling for long-running asynchronous operations like model unloading to avoid ANRs. ```kotlin override fun onCleared() { super.onCleared() // Cancel jobs first generationJob?.cancel() // Clean up resources with error handling audioRecorder.release() // Model cleanup - fire-and-forget is INTENTIONAL to avoid ANR // IMPORTANT: Async unload is the CORRECT approach here because: // 1. Model unloading can take 100-500ms+ (blocks native resources) // 2. onCleared() is called on the main thread // 3. Blocking the main thread risks ANR (Application Not Responding) // 4. viewModelScope is already cancelled at this point (can't use it) // 5. Process death will clean up native model resources anyway // 6. Fire-and-forget async cleanup is recommended for long-running shutdown operations // DO NOT change this to blocking or viewModelScope - it will cause ANRs! CoroutineScope(Dispatchers.IO).launch { try { modelRunner?.unload() } catch (e: Exception) { Log.e(TAG, "Error unloading model", e) } } } ``` -------------------------------- ### Buffer Side Effects for Reliability Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Configures MutableSharedFlow with buffering and overflow strategy to ensure side effects are not lost. ```kotlin // ✅ Buffer for reliability private val _sideEffect = MutableSharedFlow( replay = 0, extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST ) ``` -------------------------------- ### MVI Event Definition Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Define UI events using a sealed interface for type safety. This allows for exhaustive handling of different user interactions or system events. ```kotlin sealed interface MyEvent { data object LoadData : MyEvent data class UpdateItem(val id: String) : MyEvent } ``` -------------------------------- ### ContentView Struct Definition Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapSloganExample/README.md This struct defines the SwiftUI interface for the application. It uses an observable object to manage the state. ```swift struct ContentView: View { @StateObject private var store = SloganStore() @State private var topic = "" var body: some View { // UI implementation } } ``` -------------------------------- ### MessageBubble View Definition Source: https://github.com/liquid4all/leapsdk-examples/blob/main/iOS/LeapChatExample/README.md A custom UI component for displaying individual chat messages. It allows for distinct styling of user and assistant messages. ```swift struct MessageBubble: View { let message: ChatMessage var body: some View { // Custom bubble design with different styles for user/assistant } } ``` -------------------------------- ### Streaming Audio Chunk Source: https://github.com/liquid4all/leapsdk-examples/blob/main/macOS/LeapVoiceAssistantDemo/README.md Represents a chunk of audio data received during a streaming inference response. ```swift MessageResponseAudioSample ``` -------------------------------- ### User-Facing Error Side Effects Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Defines sealed interface for user-facing error side effects, including showing snackbars and dialogs. ```kotlin sealed interface SideEffect { data class ShowSnackbar(val message: String) : SideEffect data class ShowError(val title: String, val message: String) : SideEffect } ``` -------------------------------- ### Mutex for Shared Mutable State Source: https://github.com/liquid4all/leapsdk-examples/blob/main/AGENTS.md Protect shared mutable state from concurrent access issues by using a Mutex. The `withLock` function ensures exclusive access during state updates. ```kotlin private val mutex = Mutex() suspend fun updateSharedState() { mutex.withLock { sharedState = newValue } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.