package com.blaze.agent import android.content.Context import android.util.Log import com.blaze.agent.ai.LLMRouter import com.blaze.agent.state.AppState import com.blaze.agent.state.AppStateManager import com.blaze.agent.task.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch class AgentOrchestrator( private val context: Context, private val llmRouter: LLMRouter, private val getScreenContent: () -> String, private val executeAction: suspend (String) -> Unit ) { companion object { private const val TAG = "BlazeOrchestrator" } private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private val classifier = TaskClassifier(llmRouter) private val taskManager = BackgroundTaskManager( context = context, llmRouter = llmRouter, getScreenContent = getScreenContent, executeAgentAction = executeAction ) fun handleCommand(userCommand: String) { scope.launch { try { AppStateManager.transitionTo(AppState.ACTIVE) Log.d(TAG, "Handling command: $userCommand") if (isStopCommand(userCommand)) { handleStopCommand(userCommand) return@launch } val classification = classifier.classify(userCommand) Log.d(TAG, "Classification: ${classification.taskType} — ${classification.reasoning}") when (classification.taskType) { TaskType.ONE_SHOT -> { executeAction(userCommand) AppStateManager.transitionTo(AppState.SLEEP) } TaskType.MONITORING -> { val task = MonitoringTask( description = userCommand, triggerCondition = classification.triggerCondition ?: "The condition described in the task", actionToExecute = classification.actionToExecute ?: userCommand, isRecurring = classification.isRecurring, checkIntervalMs = classification.checkIntervalMs ) taskManager.startTask(task) speakConfirmation(userCommand, classification) } } } catch (e: Exception) { Log.e(TAG, "Failed to handle command: $userCommand", e) AppStateManager.transitionTo(AppState.SLEEP) } } } private fun isStopCommand(command: String): Boolean { val lower = command.lowercase() return lower.contains("stop") || lower.contains("cancel") || lower.contains("stop monitoring") || lower.contains("stop watching") } private fun handleStopCommand(command: String) { val lower = command.lowercase() when { lower.contains("all") || lower.contains("everything") -> taskManager.stopAllTasks() else -> { val active = taskManager.getActiveTasks() val match = active.firstOrNull { task -> command.lowercase().split(" ").any { word -> word.length > 3 && task.description.lowercase().contains(word) } } if (match != null) taskManager.stopTask(match.id) else active.lastOrNull()?.let { taskManager.stopTask(it.id) } } } if (!taskManager.hasActiveTasks()) AppStateManager.transitionTo(AppState.SLEEP) } private fun speakConfirmation(command: String, classification: TaskClassification) { val interval = classification.checkIntervalMs / 1000 val type = if (classification.isRecurring) "continuously" else "until first match" Log.d(TAG, "Monitoring started: checking every ${interval}s, $type") } fun getActiveTasks(): List = taskManager.getActiveTasks() fun stopAllMonitoring() = taskManager.stopAllTasks() }