From 55397db42e78b25cae9a3c4d41fd22a3115d3b81 Mon Sep 17 00:00:00 2001 From: PranavPurwar Date: Fri, 5 Jan 2024 19:58:08 +0530 Subject: [PATCH] Add Google Gemini and make chat feature public Tested-by: Pranav Purwar Signed-off-by: PranavPurwar --- app/build.gradle.kts | 6 ++ .../cosmicide/adapter/ConversationAdapter.kt | 46 +++++++++++- .../kotlin/org/cosmicide/chat/ChatProvider.kt | 73 ++++++++++++++++--- .../org/cosmicide/fragment/ChatFragment.kt | 49 ++----------- .../cosmicide/fragment/NewProjectFragment.kt | 2 +- .../cosmicide/fragment/PluginListFragment.kt | 2 - .../org/cosmicide/fragment/PluginsFragment.kt | 2 +- .../org/cosmicide/fragment/ProjectFragment.kt | 36 ++++++++- .../cosmicide/fragment/SettingsFragment.kt | 22 +++++- .../fragment/settings/AboutSettings.kt | 7 ++ .../fragment/settings/EditorSettings.kt | 4 - .../fragment/settings/GeminiSettings.kt | 67 +++++++++++++++++ .../startup/PreferencesInitializer.kt | 2 +- .../org/cosmicide/util/PreferenceKeys.kt | 6 ++ .../main/res/drawable/outline_forum_24.xml | 19 +++++ .../res/drawable/round_info_outline_24.xml | 19 +++++ app/src/main/res/menu/chat_menu.xml | 17 +---- app/src/main/res/values/strings.xml | 1 + .../rewrite/chat/ChatProviderTest.kt | 8 +- build.gradle.kts | 4 +- feature/appwrite/build.gradle.kts | 2 +- 21 files changed, 305 insertions(+), 89 deletions(-) create mode 100644 app/src/main/kotlin/org/cosmicide/fragment/settings/GeminiSettings.kt create mode 100644 app/src/main/res/drawable/outline_forum_24.xml create mode 100644 app/src/main/res/drawable/round_info_outline_24.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 039972710..9c00087be 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,12 +17,15 @@ android { defaultConfig { val commit = getGitCommit() + val GEMINI_API_KEY = "AIzaSyB-axwh7qrTGngrI2qNLgN5YAjCFJ-w0R8" + applicationId = "org.cosmicide" minSdk = 26 targetSdk = 34 versionCode = 24 versionName = "2.0.4" buildConfigField("String", "GIT_COMMIT", "\"$commit\"") + buildConfigField("String", "GEMINI_API_KEY", "\"$GEMINI_API_KEY\"") } signingConfigs { @@ -203,6 +206,9 @@ dependencies { implementation("org.lsposed.hiddenapibypass:hiddenapibypass:4.3") implementation("org.slf4j:slf4j-simple:2.1.0-alpha1") + implementation("com.google.ai.client.generativeai:generativeai:0.1.1") + + val shizukuVersion = "13.1.5" implementation("dev.rikka.shizuku:api:$shizukuVersion") diff --git a/app/src/main/kotlin/org/cosmicide/adapter/ConversationAdapter.kt b/app/src/main/kotlin/org/cosmicide/adapter/ConversationAdapter.kt index ff3dd7a92..8740f4943 100644 --- a/app/src/main/kotlin/org/cosmicide/adapter/ConversationAdapter.kt +++ b/app/src/main/kotlin/org/cosmicide/adapter/ConversationAdapter.kt @@ -9,6 +9,12 @@ package org.cosmicide.adapter import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView +import com.google.ai.client.generativeai.type.GenerateContentResponse +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.cosmicide.databinding.ConversationItemReceivedBinding import org.cosmicide.databinding.ConversationItemSentBinding import org.cosmicide.util.CommonUtils @@ -18,7 +24,23 @@ class ConversationAdapter : private val conversations = mutableListOf() - data class Conversation(val text: String, val author: String = "assistant") + data class Conversation( + var text: String = "", + val author: String = "assistant", + val flow: Flow? = null, + var finished: Boolean = false + ) { + init { + if (flow != null) { + CoroutineScope(Dispatchers.IO).launch { + flow.collect { + if (finished) return@collect + text = it.text!! + } + } + } + } + } companion object { const val VIEW_TYPE_SENT = 1 @@ -26,6 +48,7 @@ class ConversationAdapter : } fun add(conversation: Conversation) { + conversations.last().finished = true conversations += conversation notifyItemInserted(conversations.lastIndex) } @@ -94,8 +117,27 @@ class ConversationAdapter : BindableViewHolder(itemBinding) { override fun bind(data: Conversation) { + val scope = CoroutineScope(Dispatchers.IO) + + scope.launch { + if (data.text.isNotEmpty()) { + withContext(Dispatchers.Main) { + stream(data.text) + } + } + data.flow!!.collect { + if (data.finished) return@collect + + withContext(Dispatchers.Main) { + stream(it.text!!) + } + } + } + } + + fun stream(text: String) { binding.message.apply { - CommonUtils.getMarkwon().setMarkdown(this, data.text) + CommonUtils.getMarkwon().setMarkdown(this, binding.message.text.toString() + text) } } } diff --git a/app/src/main/kotlin/org/cosmicide/chat/ChatProvider.kt b/app/src/main/kotlin/org/cosmicide/chat/ChatProvider.kt index 4281ff87d..3a14d9811 100644 --- a/app/src/main/kotlin/org/cosmicide/chat/ChatProvider.kt +++ b/app/src/main/kotlin/org/cosmicide/chat/ChatProvider.kt @@ -8,23 +8,74 @@ package org.cosmicide.chat import android.util.Log -import com.google.gson.Gson -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.RequestBody.Companion.toRequestBody -import java.util.concurrent.TimeUnit +import com.google.ai.client.generativeai.GenerativeModel +import com.google.ai.client.generativeai.type.BlockThreshold +import com.google.ai.client.generativeai.type.GenerateContentResponse +import com.google.ai.client.generativeai.type.HarmCategory +import com.google.ai.client.generativeai.type.SafetySetting +import com.google.ai.client.generativeai.type.generationConfig +import kotlinx.coroutines.flow.Flow +import org.cosmicide.BuildConfig +import org.cosmicide.common.Prefs object ChatProvider { - private val client = OkHttpClient() + private val safetySettings = listOf( + SafetySetting(HarmCategory.SEXUALLY_EXPLICIT, BlockThreshold.NONE), // should we block this? + SafetySetting(HarmCategory.HATE_SPEECH, BlockThreshold.NONE), + SafetySetting(HarmCategory.DANGEROUS_CONTENT, BlockThreshold.NONE), + SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.NONE), + ) - private val gson = Gson() + private var generativeModel = GenerativeModel( + apiKey = BuildConfig.GEMINI_API_KEY, + modelName = "gemini-pro", + safetySettings = safetySettings, + generationConfig = generationConfig { + temperature = Prefs.temperature + topP = Prefs.topP + topK = Prefs.topK + maxOutputTokens = Prefs.maxTokens + } + ) + + private var chat = generativeModel.startChat() - data class Message(val role: String, val content: String) + @JvmStatic + fun regenerateModel( + temp: Float = Prefs.temperature, + top_p: Float = Prefs.topP, + top_k: Int = Prefs.topK, + maxTokens: Int = Prefs.maxTokens + ) { + Log.d( + "ChatProvider", + "regenerateModel: temperature ${Prefs.temperature}, topP ${Prefs.topP}, topK ${Prefs.topK}, maxTokens ${Prefs.maxTokens}" + ) + + GenerativeModel( + apiKey = BuildConfig.GEMINI_API_KEY, + modelName = "gemini-pro", + safetySettings = safetySettings, + generationConfig = generationConfig { + temperature = temp + topP = top_p + topK = top_k + maxOutputTokens = maxTokens + } + ).let { + generativeModel = it + chat = it.startChat() + } + } @JvmStatic - fun generate(model: String, conversation: List>): String { + fun generate(conversation: List>): Flow { + return chat.sendMessageStream(conversation.last()["text"]!!) + + + /* + // json format // { // "messages": [ @@ -56,5 +107,7 @@ object ChatProvider { e.printStackTrace() "Error: ${e.message}" } + + */ } } diff --git a/app/src/main/kotlin/org/cosmicide/fragment/ChatFragment.kt b/app/src/main/kotlin/org/cosmicide/fragment/ChatFragment.kt index 49db62c6d..470593f33 100644 --- a/app/src/main/kotlin/org/cosmicide/fragment/ChatFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/fragment/ChatFragment.kt @@ -32,7 +32,6 @@ import org.cosmicide.rewrite.common.BaseBindingFragment class ChatFragment : BaseBindingFragment() { private val conversationAdapter = ConversationAdapter() - private var model = Models.GPT_35_TURBO override fun getViewBinding() = FragmentChatBinding.inflate(layoutInflater) @@ -47,7 +46,7 @@ class ChatFragment : BaseBindingFragment() { private fun setupUI(context: Context) { initToolbar() initBackground(context) - binding.toolbar.title = model.name + binding.toolbar.title = "Gemini Pro" } private fun initToolbar() { @@ -61,26 +60,7 @@ class ChatFragment : BaseBindingFragment() { binding.recyclerview.invalidate() return@setOnMenuItemClickListener false } - val modelName = when (it.itemId) { - R.id.model_gpt35turbo -> { - model = Models.GPT_35_TURBO - "GPT-3.5 Turbo" - } - - R.id.model_gpt3516k -> { - model = Models.GPT_3516K - "GPT-3.5 16k" - } - - R.id.model_gpt35turbo0613 -> { - model = Models.GPT_35_TURBO_0613 - "GPT-3.5 Turbo 0613" - } - - else -> return@setOnMenuItemClickListener false - } - binding.toolbar.title = modelName true } } @@ -95,24 +75,11 @@ class ChatFragment : BaseBindingFragment() { conversationAdapter.add(conversation) binding.messageText.setText("") lifecycleScope.launch(Dispatchers.IO) { - val reply = when (model) { - Models.GPT_35_TURBO_0613 -> ChatProvider.generate( - "gpt-3.5-turbo-0613", - conversationAdapter.getConversations() - ) - - Models.GPT_35_TURBO -> ChatProvider.generate( - "gpt-3.5-turbo", - conversationAdapter.getConversations() - ) - - Models.GPT_3516K -> ChatProvider.generate( - "gpt-3.5-16k", - conversationAdapter.getConversations() - ) + val reply = ChatProvider.generate( + conversationAdapter.getConversations() + ) - } - val response = ConversationAdapter.Conversation(reply) + val response = ConversationAdapter.Conversation(flow = reply) withContext(Dispatchers.Main) { conversationAdapter.add(response) binding.recyclerview.scrollToPosition(conversationAdapter.itemCount - 1) @@ -160,11 +127,5 @@ class ChatFragment : BaseBindingFragment() { } } -enum class Models { - GPT_35_TURBO, - GPT_3516K, - GPT_35_TURBO_0613, -} - private val Int.dp: Int get() = (Resources.getSystem().displayMetrics.density * this + 0.5f).toInt() diff --git a/app/src/main/kotlin/org/cosmicide/fragment/NewProjectFragment.kt b/app/src/main/kotlin/org/cosmicide/fragment/NewProjectFragment.kt index 6ff8f59e6..03966e653 100644 --- a/app/src/main/kotlin/org/cosmicide/fragment/NewProjectFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/fragment/NewProjectFragment.kt @@ -111,4 +111,4 @@ class NewProjectFragment : BaseBindingFragment() { val content = language.classFileContent(name = "Main", packageName = packageName) writeText(content) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/org/cosmicide/fragment/PluginListFragment.kt b/app/src/main/kotlin/org/cosmicide/fragment/PluginListFragment.kt index b6a8213de..7671dfcf9 100644 --- a/app/src/main/kotlin/org/cosmicide/fragment/PluginListFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/fragment/PluginListFragment.kt @@ -65,7 +65,6 @@ class PluginListFragment : BaseBindingFragment() { .setTitle("Delete plugin") .setMessage("Are you sure you want to delete ${plugin.name}?") .setPositiveButton("Yes") { _, _ -> - Analytics.logEvent("plugin_delete", mapOf("plugin" to plugin.name)) lifecycleScope.launch { FileUtil.pluginDir.resolve(plugin.name).deleteRecursively() val plugins = getPlugins() @@ -77,7 +76,6 @@ class PluginListFragment : BaseBindingFragment() { } override fun onPluginInstall(plugin: Plugin) { - Analytics.logEvent("plugin_install", mapOf("plugin" to plugin.name)) binding.progressBar.visibility = View.VISIBLE Snackbar.make( binding.root, diff --git a/app/src/main/kotlin/org/cosmicide/fragment/PluginsFragment.kt b/app/src/main/kotlin/org/cosmicide/fragment/PluginsFragment.kt index 7c7e1fad2..678ad2d6f 100644 --- a/app/src/main/kotlin/org/cosmicide/fragment/PluginsFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/fragment/PluginsFragment.kt @@ -110,4 +110,4 @@ class PluginsFragment : BaseBindingFragment() { return plugins } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/org/cosmicide/fragment/ProjectFragment.kt b/app/src/main/kotlin/org/cosmicide/fragment/ProjectFragment.kt index 538360984..bba058470 100644 --- a/app/src/main/kotlin/org/cosmicide/fragment/ProjectFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/fragment/ProjectFragment.kt @@ -13,6 +13,7 @@ import android.os.Bundle import android.view.View import android.widget.EditText import android.widget.TextView +import android.widget.Toast import androidx.activity.result.ActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts.CreateDocument @@ -115,6 +116,7 @@ class ProjectFragment : BaseBindingFragment(), override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + askClientName() askForAnalyticsPermission() setOnClickListeners() @@ -331,6 +333,38 @@ class ProjectFragment : BaseBindingFragment(), }.show() } + private fun askClientName() { + val prefs = PreferenceManager.getDefaultSharedPreferences(requireContext()) + + val enteredName = prefs.getString("client_name", null) + if (enteredName != null) return + + val editText = EditText(requireContext()).apply { + hint = "Enter your name" + } + + MaterialAlertDialogBuilder(requireContext()).apply { + setView(editText) + setTitle("Enter your name") + setPositiveButton("Okay") { _, _ -> + val name = editText.text.toString() + + if (name.isEmpty()) { + Toast.makeText(requireContext(), "Name cannot be empty", Toast.LENGTH_SHORT) + .show() + askClientName() + return@setPositiveButton + } + + prefs.edit(commit = true) { + putString("client_name", name).apply() + } + } + show() + } + } + + private fun askForAnalyticsPermission() { val prefs = PreferenceManager.getDefaultSharedPreferences(requireContext()) if (prefs.getBoolean("analytics_preference_asked", false)) return @@ -376,4 +410,4 @@ class ProjectFragment : BaseBindingFragment(), setTransition(androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN) } } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/org/cosmicide/fragment/SettingsFragment.kt b/app/src/main/kotlin/org/cosmicide/fragment/SettingsFragment.kt index dd6e9ce59..32eb87059 100644 --- a/app/src/main/kotlin/org/cosmicide/fragment/SettingsFragment.kt +++ b/app/src/main/kotlin/org/cosmicide/fragment/SettingsFragment.kt @@ -13,16 +13,19 @@ import androidx.activity.OnBackPressedCallback import androidx.core.os.BundleCompat import com.google.android.material.dialog.MaterialAlertDialogBuilder import de.Maxr1998.modernpreferences.Preference +import de.Maxr1998.modernpreferences.PreferenceScreen import de.Maxr1998.modernpreferences.PreferencesAdapter import de.Maxr1998.modernpreferences.helpers.screen import de.Maxr1998.modernpreferences.helpers.subScreen import org.cosmicide.MainActivity +import org.cosmicide.chat.ChatProvider import org.cosmicide.databinding.FragmentSettingsBinding import org.cosmicide.fragment.settings.AboutSettings import org.cosmicide.fragment.settings.AppearanceSettings import org.cosmicide.fragment.settings.CompilerSettings import org.cosmicide.fragment.settings.EditorSettings import org.cosmicide.fragment.settings.FormatterSettings +import org.cosmicide.fragment.settings.GeminiSettings import org.cosmicide.fragment.settings.GitSettings import org.cosmicide.fragment.settings.PluginSettingsProvider import org.cosmicide.rewrite.common.BaseBindingFragment @@ -51,6 +54,9 @@ class SettingsFragment : BaseBindingFragment() { val pluginsSettings = PluginSettingsProvider(requireActivity()) val gitSettings = GitSettings() val aboutSettings = AboutSettings(requireActivity()) + val geminiSettings = GeminiSettings(requireActivity()) + + var geminiScreen: PreferenceScreen? = null val screen = screen(requireContext()) { subScreen { @@ -72,11 +78,13 @@ class SettingsFragment : BaseBindingFragment() { compilerSettings.provideSettings(this) } subScreen { + collapseIcon = true title = "Formatter" summary = "Adjust code formatting preferences" formatterSettings.provideSettings(this) } subScreen { + collapseIcon = true title = "Plugins" summary = "Explore and install plugins to extend the functionality of the IDE" pluginsSettings.provideSettings(this) @@ -87,6 +95,12 @@ class SettingsFragment : BaseBindingFragment() { summary = "Configure Git integration" gitSettings.provideSettings(this) } + geminiScreen = subScreen { + collapseIcon = true + title = "Gemini" + summary = "Configure Gemini integration" + geminiSettings.provideSettings(this) + } subScreen { collapseIcon = true title = "About" @@ -108,6 +122,9 @@ class SettingsFragment : BaseBindingFragment() { binding.preferencesView.adapter = preferencesAdapter binding.toolbar.setNavigationOnClickListener { + if (preferencesAdapter.currentScreen == geminiScreen) { + ChatProvider.regenerateModel() + } if (!preferencesAdapter.goBack()) { parentFragmentManager.popBackStack() } @@ -119,6 +136,9 @@ class SettingsFragment : BaseBindingFragment() { if (isResumed.not()) { return } + if (preferencesAdapter.currentScreen == geminiScreen) { + ChatProvider.regenerateModel() + } if (!preferencesAdapter.goBack()) { isEnabled = false parentFragmentManager.popBackStack() @@ -134,4 +154,4 @@ class SettingsFragment : BaseBindingFragment() { } outState.putParcelable("adapter", preferencesAdapter.getSavedState()) } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/org/cosmicide/fragment/settings/AboutSettings.kt b/app/src/main/kotlin/org/cosmicide/fragment/settings/AboutSettings.kt index 51d771240..db36be269 100644 --- a/app/src/main/kotlin/org/cosmicide/fragment/settings/AboutSettings.kt +++ b/app/src/main/kotlin/org/cosmicide/fragment/settings/AboutSettings.kt @@ -19,6 +19,7 @@ import android.util.Log import android.widget.EditText import android.widget.Toast import androidx.core.content.ContextCompat +import androidx.core.content.res.ResourcesCompat.* import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.commit @@ -52,6 +53,12 @@ class AboutSettings(private val activity: FragmentActivity) : SettingsProvider { @SuppressLint("PrivateResource") override fun provideSettings(builder: PreferenceScreen.Builder) { builder.apply { + icon = getDrawable( + activity.resources, + R.drawable.round_info_outline_24, + activity.theme + ) + expandText("about") { title = "About" summary = "A free and open-source IDE for Android." diff --git a/app/src/main/kotlin/org/cosmicide/fragment/settings/EditorSettings.kt b/app/src/main/kotlin/org/cosmicide/fragment/settings/EditorSettings.kt index ed4186dea..709142a92 100644 --- a/app/src/main/kotlin/org/cosmicide/fragment/settings/EditorSettings.kt +++ b/app/src/main/kotlin/org/cosmicide/fragment/settings/EditorSettings.kt @@ -78,10 +78,6 @@ class EditorSettings(private val activity: FragmentActivity) : SettingsProvider summary = "Enables sticky scroll in the editor" defaultValue = true - onCheckedChange { isChecked -> - Analytics.logEvent("sticky_scroll", isChecked) - true - } } switch(PreferenceKeys.EDITOR_USE_SPACES) { diff --git a/app/src/main/kotlin/org/cosmicide/fragment/settings/GeminiSettings.kt b/app/src/main/kotlin/org/cosmicide/fragment/settings/GeminiSettings.kt new file mode 100644 index 000000000..cc3c5209d --- /dev/null +++ b/app/src/main/kotlin/org/cosmicide/fragment/settings/GeminiSettings.kt @@ -0,0 +1,67 @@ +/* + * This file is part of Cosmic IDE. + * Cosmic IDE is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with Cosmic IDE. If not, see . + */ + +package org.cosmicide.fragment.settings + +import androidx.core.content.res.ResourcesCompat +import androidx.fragment.app.FragmentActivity +import de.Maxr1998.modernpreferences.PreferenceScreen +import de.Maxr1998.modernpreferences.helpers.seekBar +import de.Maxr1998.modernpreferences.helpers.singleChoice +import de.Maxr1998.modernpreferences.preferences.choice.SelectionItem +import org.cosmicide.R +import org.cosmicide.util.PreferenceKeys + +class GeminiSettings(private val activity: FragmentActivity) : SettingsProvider { + + private val temperature: List + get() = listOf( + 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, + 0.6f, 0.7f, 0.8f, 0.9f, 1.0f + ) + + private val keys = temperature.map { SelectionItem(it.toString(), it.toString(), null) } + + override fun provideSettings(builder: PreferenceScreen.Builder) { + builder.apply { + icon = ResourcesCompat.getDrawable( + activity.resources, + R.drawable.outline_forum_24, + activity.theme + ) + singleChoice(PreferenceKeys.TEMPERATURE, keys) { + title = "temperature" + summary = + "Controls the randomness of the output. A value closer to 1.0 will produce responses that are more varied and creative, while a value closer to 0.0 will typically result in more straightforward responses from the model." + initialSelection = "0.9" + } + + singleChoice(PreferenceKeys.TOP_P, keys) { + title = "top_p" + summary = + "The maximum cumulative probability of tokens to consider when sampling. Tokens are sorted based on their assigned probabilities so that only the most likely tokens are considered. Top-k sampling directly limits the maximum number of tokens to consider, while Nucleus sampling limits number of tokens based on the cumulative probability." + initialSelection = "1.0" + } + + seekBar(PreferenceKeys.TOP_K) { + title = "top_k" + summary = "top_k sets the maximum number of tokens to sample from on each step." + max = 60 + min = 1 + default = 1 + } + + seekBar(PreferenceKeys.MAX_TOKENS) { + title = "max_tokens" + summary = "max_tokens sets the maximum number of tokens to generate." + max = 2048 + min = 60 + default = 1024 + } + } + } +} diff --git a/app/src/main/kotlin/org/cosmicide/startup/PreferencesInitializer.kt b/app/src/main/kotlin/org/cosmicide/startup/PreferencesInitializer.kt index c5ce9b7a6..488a4ce54 100644 --- a/app/src/main/kotlin/org/cosmicide/startup/PreferencesInitializer.kt +++ b/app/src/main/kotlin/org/cosmicide/startup/PreferencesInitializer.kt @@ -20,4 +20,4 @@ class PreferencesInitializer : Initializer { } override fun dependencies(): List>> = emptyList() -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/org/cosmicide/util/PreferenceKeys.kt b/app/src/main/kotlin/org/cosmicide/util/PreferenceKeys.kt index 931568dd8..17efe6cad 100644 --- a/app/src/main/kotlin/org/cosmicide/util/PreferenceKeys.kt +++ b/app/src/main/kotlin/org/cosmicide/util/PreferenceKeys.kt @@ -56,4 +56,10 @@ object PreferenceKeys { const val PLUGIN_REPOSITORY = "plugin_repository" const val PLUGIN_SETTINGS = "plugin_settings" + // Gemini Pro + const val TEMPERATURE = "temperature" + const val TOP_P = "top_p" + const val TOP_K = "top_k" + const val CANDIDATE_COUNT = "candidate_count" + const val MAX_TOKENS = "max_tokens" } diff --git a/app/src/main/res/drawable/outline_forum_24.xml b/app/src/main/res/drawable/outline_forum_24.xml new file mode 100644 index 000000000..dc3c84f45 --- /dev/null +++ b/app/src/main/res/drawable/outline_forum_24.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/app/src/main/res/drawable/round_info_outline_24.xml b/app/src/main/res/drawable/round_info_outline_24.xml new file mode 100644 index 000000000..6ad309632 --- /dev/null +++ b/app/src/main/res/drawable/round_info_outline_24.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/app/src/main/res/menu/chat_menu.xml b/app/src/main/res/menu/chat_menu.xml index 5ebbef236..6e7f67d79 100644 --- a/app/src/main/res/menu/chat_menu.xml +++ b/app/src/main/res/menu/chat_menu.xml @@ -4,8 +4,10 @@ ~ Cosmic IDE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ~ You should have received a copy of the GNU General Public License along with Cosmic IDE. If not, see . --> - + - - - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 38c853b45..e759452a6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -102,4 +102,5 @@ Backup Program Arguments Advanced + Gemini Pro diff --git a/app/src/test/java/org/cosmicide/rewrite/chat/ChatProviderTest.kt b/app/src/test/java/org/cosmicide/rewrite/chat/ChatProviderTest.kt index 5fadfd619..733e5f119 100644 --- a/app/src/test/java/org/cosmicide/rewrite/chat/ChatProviderTest.kt +++ b/app/src/test/java/org/cosmicide/rewrite/chat/ChatProviderTest.kt @@ -8,7 +8,6 @@ package org.cosmicide.rewrite.chat import org.cosmicide.chat.ChatProvider -import org.cosmicide.fragment.Models import org.junit.Test class ChatProviderTest { @@ -18,10 +17,7 @@ class ChatProviderTest { mapOf("author" to "user", "text" to "hi"), mapOf("author" to "bot", "text" to "hello") ) - val models = Models.values().map { it.name } - for (model in models) { - val output = ChatProvider.generate(model, conversation) - println(output) - } + val output = ChatProvider.generate(conversation) + println(output) } } diff --git a/build.gradle.kts b/build.gradle.kts index 1426c27a0..639ba3848 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,8 +7,8 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.application") version "8.4.0-alpha01" apply false - id("com.android.library") version "8.4.0-alpha01" apply false + id("com.android.application") version "8.4.0-alpha02" apply false + id("com.android.library") version "8.4.0-alpha02" apply false id("org.jetbrains.kotlin.android") version "2.0.0-Beta2" apply false id("org.jetbrains.kotlin.jvm") version "2.0.0-Beta2" apply false id("dev.rikka.tools.materialthemebuilder") version "1.3.3" apply false diff --git a/feature/appwrite/build.gradle.kts b/feature/appwrite/build.gradle.kts index c2b2c125b..1325c705a 100644 --- a/feature/appwrite/build.gradle.kts +++ b/feature/appwrite/build.gradle.kts @@ -45,7 +45,7 @@ dependencies { implementation("com.google.code.gson:gson:2.10.1") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0-rc02") - implementation("androidx.appcompat:appcompat:${rootProject.extra["appcompatVersion"]}") + implementation("androidx.appcompat:appcompat:1.7.0-alpha03") implementation("androidx.fragment:fragment-ktx:1.7.0-alpha07") implementation("androidx.activity:activity-ktx:1.9.0-alpha01") implementation("androidx.browser:browser:1.7.0")