Browse Source

ai actions pre-implementation

Milan Jurkulak 2 năm trước cách đây
mục cha
commit
0598968d17

+ 3 - 2
src/main/kotlin/eu/mjdev/desktop/components/controlcenter/pages/AIPage.kt

@@ -50,6 +50,7 @@ fun AIPage() = ControlCenterPage(
             api.ai.ask(what) { _, res ->
                 res.replace("* **", "")
                     .replace("**", "")
+                    .trim()
                     .let { resx ->
                         questionsList.removeIf { it.first == what }
                         questionsList.add(Pair(what, resx))
@@ -95,7 +96,7 @@ fun AIPage() = ControlCenterPage(
                                     .padding(8.dp)
                             ) {
                                 TextAny(
-                                    modifier = Modifier.fillMaxWidth().padding(end = 24.dp),
+                                    modifier = Modifier.fillMaxWidth().padding(end = 24.dp, top = 6.dp),
                                     text = "${idx + 1}. ${textData.first}",
                                     color = Color.White,
                                     textSelectionEnabled = true
@@ -122,7 +123,7 @@ fun AIPage() = ControlCenterPage(
                                     .padding(8.dp),
                             ) {
                                 TextAny(
-                                    modifier = Modifier.fillMaxWidth().padding(end = 24.dp),
+                                    modifier = Modifier.fillMaxWidth().padding(end = 24.dp, top = 6.dp),
                                     text = textData.second,
                                     color = Color.White.copy(alpha = 0.9f),
                                     textSelectionEnabled = true

+ 20 - 5
src/main/kotlin/eu/mjdev/desktop/managers/artificialintelligence/AIManager.kt

@@ -8,6 +8,8 @@
 
 package eu.mjdev.desktop.managers.artificialintelligence
 
+import eu.mjdev.desktop.managers.artificialintelligence.actions.ActionsProvider
+import eu.mjdev.desktop.managers.artificialintelligence.actions.base.ActionException.ActionNone
 import eu.mjdev.desktop.managers.artificialintelligence.base.AIPlugin
 import eu.mjdev.desktop.managers.artificialintelligence.plugins.AiPluginNull
 import eu.mjdev.desktop.managers.artificialintelligence.stt.STTPluginNull
@@ -24,7 +26,8 @@ class AIManager(
     val api: DesktopProvider,
     var pluginAI: AIPlugin,
     var pluginSTT: STTPlugin,
-    var pluginTTS: TTSPlugin
+    var pluginTTS: TTSPlugin,
+    var actions: ActionsProvider
 ) {
     val scope = api.scope
     val isAvailable: () -> Boolean = { pluginAI !is AiPluginNull }
@@ -33,8 +36,15 @@ class AIManager(
         question: String,
         block: AIManager.(question: String, result: String) -> Unit
     ) = scope.launch(Dispatchers.IO) {
-        pluginAI.ask(question).also { result ->
-            block.invoke(this@AIManager, question, result)
+        val actResult = actions.tryAction(question)
+        if (actResult is ActionNone) {
+            pluginAI.ask(question).also { result ->
+                block.invoke(this@AIManager, question, result)
+            }
+        } else {
+            actResult.message?.also { message ->
+                block.invoke(this@AIManager, question, message)
+            }
         }
     }
 
@@ -47,7 +57,12 @@ class AIManager(
             scope: CoroutineScope = api.scope,
             ai: AIPlugin = AiPluginNull(scope),
             stt: STTPlugin = STTPluginNull(scope),
-            tts: TTSPlugin = TTSPluginMain(scope)
-        ) = AIManager(api, ai, stt, tts)
+            tts: TTSPlugin = TTSPluginMain(scope),
+            actions: ActionsProvider = ActionsProvider(api) {
+                action("open calculator") {
+                    open("calculator")
+                }
+            }
+        ) = AIManager(api, ai, stt, tts, actions)
     }
 }

+ 71 - 0
src/main/kotlin/eu/mjdev/desktop/managers/artificialintelligence/actions/ActionsProvider.kt

@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.managers.artificialintelligence.actions
+
+import eu.mjdev.desktop.managers.artificialintelligence.actions.base.Action
+import eu.mjdev.desktop.managers.artificialintelligence.actions.base.ActionException
+import eu.mjdev.desktop.managers.artificialintelligence.actions.base.ActionException.ActionFail
+import eu.mjdev.desktop.managers.artificialintelligence.actions.base.ActionException.ActionSuccess
+import eu.mjdev.desktop.managers.artificialintelligence.actions.base.ActionProviderScope
+import eu.mjdev.desktop.provider.DesktopProvider
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+
+@Suppress("unused")
+class ActionsProvider(
+    val api: DesktopProvider,
+) : ArrayList<Action>() {
+    val scope: CoroutineScope = api.scope
+
+    constructor(
+        api: DesktopProvider,
+        block: ActionsProvider.() -> Unit = {}
+    ) : this(api) {
+        block.invoke(this)
+    }
+
+    constructor(
+        api: DesktopProvider,
+        vararg actions: Action
+    ) : this(api) {
+        addAll(actions)
+    }
+
+    fun action(
+        command: String,
+        action: suspend ActionProviderScope.() -> ActionException,
+    ) {
+        add(
+            Action(
+                name = command,
+                text = command,
+                action = action
+            )
+        )
+    }
+
+    // todo regexp & fuzzy
+    fun tryAction(
+        text: String
+    ): ActionException {
+        return text.trim().let { t ->
+            firstOrNull { a ->
+                a.text.contentEquals(t, true) || a.text.contains(t, true)
+            }?.let { a ->
+                a.lastSeen = System.currentTimeMillis()
+                runBlocking(Dispatchers.IO) {
+                    a.action.invoke(ActionProviderScope(api)).let { r ->
+                        if(r is ActionFail) r else ActionSuccess(a.responseSuccess, r)
+                    }
+                }
+            } ?: ActionException.ActionNone
+        }
+    }
+}

+ 21 - 0
src/main/kotlin/eu/mjdev/desktop/managers/artificialintelligence/actions/base/Action.kt

@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.managers.artificialintelligence.actions.base
+
+// todo history with command strings to analyze best result
+@Suppress("unused")
+class Action(
+    val name: String,
+    val text: String,
+    val regExp: String? = null,
+    val responseSuccess: String = "OK",
+    val action: suspend ActionProviderScope.() -> ActionException,
+    var lastSeen: Long = 0
+//    val history : ActionHistory
+)

+ 42 - 0
src/main/kotlin/eu/mjdev/desktop/managers/artificialintelligence/actions/base/ActionException.kt

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.managers.artificialintelligence.actions.base
+
+@Suppress("unused", "JavaIoSerializableObjectMustHaveReadResolve")
+open class ActionException(
+    message: String = "",
+    t: Throwable? = null,
+    val isError: Boolean = false
+) : Exception(message, t) {
+
+    object ActionNone : ActionException(
+        isError = false
+    )
+
+    class ActionSuccess(
+        message: String = "",
+        t: Throwable? = null
+    ) : ActionException(
+        message,
+        t,
+        isError = false
+    )
+
+    class ActionFail(
+        message: String = "",
+        t: Throwable? = null
+    ) : ActionException(message, t, true) {
+        constructor(
+            t: Throwable
+        ) : this(
+            t.message ?: "Error",
+            t
+        )
+    }
+}

+ 29 - 0
src/main/kotlin/eu/mjdev/desktop/managers/artificialintelligence/actions/base/ActionProviderScope.kt

@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.managers.artificialintelligence.actions.base
+
+import eu.mjdev.desktop.provider.DesktopProvider
+import eu.mjdev.desktop.managers.artificialintelligence.actions.base.ActionException.ActionFail
+import eu.mjdev.desktop.managers.artificialintelligence.actions.base.ActionException.ActionSuccess
+
+class ActionProviderScope(
+    private val api: DesktopProvider
+) {
+    // todo actions
+
+    fun open(
+        what: String
+    ): ActionException = try {
+        api.open(what)
+        ActionSuccess()
+    } catch (e: Exception) {
+        ActionFail(e)
+    }
+
+}

+ 5 - 0
src/main/kotlin/eu/mjdev/desktop/provider/DesktopProvider.kt

@@ -159,6 +159,11 @@ class DesktopProvider(
         moveToTrash(File(filePath))
     }
 
+    // todo, may be need another function
+    fun open(what: String) {
+        Shell.executeAndRead("xdg-open", what)
+    }
+
     fun openFileInAssociated(file: File) = runCatching {
         desktopUtils.open(file)
     }