diff --git a/CHANGELOG.md b/CHANGELOG.md index 2749cfb..47fb37c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +# [0.1.4] - 2024-08-24 + +Changed: + +- configuration moved from $HOME/.config/r0b0t.json to $HOME/.config/r0b0t/conf.json +- internal design based on events, moving event handlers to GtkGui module and simplifying @lanayx style dependency injection, eliminating it for the Core module. Navigation was simplified by relying on fixed configuration groups rather than a tree. + +Fixed: + +- Display of existing API keys in command palette + # [0.1.3] - 2024-08-09 Added: diff --git a/R0b0t.Lib/Configuration.fs b/R0b0t.Lib/Configuration.fs index f2cd3d7..3a1071b 100644 --- a/R0b0t.Lib/Configuration.fs +++ b/R0b0t.Lib/Configuration.fs @@ -1,6 +1,7 @@ module Configuration open System +open System.IO type Key = Key of string @@ -52,11 +53,13 @@ let providersModels = HuggingFace, huggingFaceModels ImaginePro, imagineProAiModels ] -let confPath = - (LamgEnv.getEnv "HOME" |> Option.defaultValue "~") - :: [ ".config"; "r0b0t.json" ] - |> List.toArray - |> System.IO.Path.Join +let confDir = + (LamgEnv.getEnv "HOME" |> Option.defaultValue "~") :: [ ".config"; "r0b0t" ] + +let confPath = confDir @ [ "conf.json" ] |> List.toArray |> Path.Join + +let ensureConfDirExists () = + confDir |> List.toArray |> Path.Join |> Directory.CreateDirectory |> ignore type ConfigurationManager() = let mutable conf = @@ -128,13 +131,16 @@ type ConfigurationManager() = |> List.map (fun (p, Key k) -> p.ToString(), k) |> Map.ofList - { provider = provider - model = model - provider_keys = keys } - |> (fun v -> - let opts = Text.Json.JsonSerializerOptions(WriteIndented = true) - Text.Json.JsonSerializer.Serialize(v, opts)) - |> fun json -> IO.File.WriteAllText(confPath, json) + let serializable = + { provider = provider + model = model + provider_keys = keys } + + let opts = Text.Json.JsonSerializerOptions(WriteIndented = true) + let json = Text.Json.JsonSerializer.Serialize(serializable, opts) + + ensureConfDirExists () + File.WriteAllText(confPath, json) with e -> eprintfn $"failed to store configuration: {e.Message}" diff --git a/R0b0t.Lib/GtkGui.fs b/R0b0t.Lib/GtkGui.fs index b3846d4..85fdfa4 100644 --- a/R0b0t.Lib/GtkGui.fs +++ b/R0b0t.Lib/GtkGui.fs @@ -101,7 +101,7 @@ let populateListBox (l: ListBox) (xs: Row array) = let appendRow { label = label; control = control } = match control with | Checkbox v -> boolSetting label v - | Entry _ -> stringSetting label "" + | Entry text -> stringSetting label text | SettingGroup descr -> settingGroup (label, descr) |> l.Append diff --git a/R0b0t.Lib/Navigation.fs b/R0b0t.Lib/Navigation.fs index f1abddb..83c234a 100644 --- a/R0b0t.Lib/Navigation.fs +++ b/R0b0t.Lib/Navigation.fs @@ -27,15 +27,15 @@ type Setting = { row: Row; request: Request } let settingGroups = [| { row = { label = "Set provider" - control = SettingGroup "SetProvider" } + control = SettingGroup "AI platform giving access to LLMs through an API" } request = Skip } { row = { label = "Set model" - control = SettingGroup "Set model" } + control = SettingGroup "Large Language Models available for the selected provider" } request = Skip } { row = { label = "Set API key" - control = SettingGroup "Set API key" } + control = SettingGroup "API key for the selected provider for authorizing the requests" } request = Skip } |] let providers = [| OpenAI; Anthropic; HuggingFace; GitHub; ImaginePro |] @@ -69,13 +69,14 @@ let setModelsGroup = (p, settings)) |> Map.ofList -let newSetApiKeyGroup (providerKeys: Map) = - providerKeys - |> Map.map (fun p key -> - [| { row = - { label = "API key" - control = Entry(let (Key k) = key in k) } - request = SetApiKey(p, key) } |]) +let apiKeySetting provider (Key key) = + [| { row = + { label = "API key" + control = Entry key } + request = SetApiKey(provider, (Key key)) } |] + + +let newSetApiKeyGroup (providerKeys: Map) = providerKeys |> Map.map apiKeySetting type NavigationHandler(conf: Configuration, requester: Event) = @@ -100,12 +101,17 @@ type NavigationHandler(conf: Configuration, requester: Event) = 2, Entry "" |] let getGroupSettings group = - let activeProvider = fst groupActiveItem[0] + let activeProvider = providers[fst groupActiveItem[0]] match group with | 0 -> setProviderGroup - | 1 -> setModelsGroup[providers[activeProvider]] - | 2 -> setApiKeysGroup[providers[activeProvider]] + | 1 -> setModelsGroup[activeProvider] + | 2 -> + if setApiKeysGroup.ContainsKey activeProvider then + setApiKeysGroup[activeProvider] + else + apiKeySetting activeProvider (Key "") + | _ -> failwith $"mismatch between UI and NavigationHandler, setting group {group} out of range" // index: optional index of the item the user wants to activate diff --git a/r0b0t/r0b0t.fsproj b/r0b0t/r0b0t.fsproj index ac8755f..3ecef97 100644 --- a/r0b0t/r0b0t.fsproj +++ b/r0b0t/r0b0t.fsproj @@ -8,7 +8,7 @@ ./nupkg true - 0.1.3 + 0.1.4 Luis Ángel Méndez Gort AGPL-3.0-or-later r0b0t