From 10d6583a6702c95bfa26046e096378e9ce1738e7 Mon Sep 17 00:00:00 2001 From: Alex Mickelson Date: Mon, 23 Mar 2026 13:27:27 -0600 Subject: [PATCH] fixing provider switching --- lib/elixir_ai/chat_runner/chat_runner.ex | 4 + lib/elixir_ai/chat_runner/tool_config.ex | 11 ++- lib/elixir_ai/data/ai_provider.ex | 28 ++++++ lib/elixir_ai/data/conversation.ex | 25 +++++ lib/elixir_ai_web/chat/chat_live.ex | 14 ++- .../chat/chat_provider_display.ex | 93 ++++++++++++++----- 6 files changed, 150 insertions(+), 25 deletions(-) diff --git a/lib/elixir_ai/chat_runner/chat_runner.ex b/lib/elixir_ai/chat_runner/chat_runner.ex index e54d9d9..9dd60d3 100644 --- a/lib/elixir_ai/chat_runner/chat_runner.ex +++ b/lib/elixir_ai/chat_runner/chat_runner.ex @@ -38,6 +38,10 @@ defmodule ElixirAi.ChatRunner do GenServer.call(via(name), {:tool_config, {:set_tool_choice, tool_choice}}) end + def set_provider(name, provider_id) when is_binary(provider_id) do + GenServer.call(via(name), {:tool_config, {:set_provider, provider_id}}) + end + def register_liveview_pid(name, liveview_pid) when is_pid(liveview_pid) do GenServer.call(via(name), {:session, {:register_liveview_pid, liveview_pid}}) end diff --git a/lib/elixir_ai/chat_runner/tool_config.ex b/lib/elixir_ai/chat_runner/tool_config.ex index 852a4bb..4c6c0bc 100644 --- a/lib/elixir_ai/chat_runner/tool_config.ex +++ b/lib/elixir_ai/chat_runner/tool_config.ex @@ -1,5 +1,5 @@ defmodule ElixirAi.ChatRunner.ToolConfig do - alias ElixirAi.{AiTools, Conversation} + alias ElixirAi.{AiProvider, AiTools, Conversation} def handle_call({:set_tool_choice, tool_choice}, _from, state) do Conversation.update_tool_choice(state.name, tool_choice) @@ -19,4 +19,13 @@ defmodule ElixirAi.ChatRunner.ToolConfig do liveview_tools: liveview_tools }} end + + def handle_call({:set_provider, provider_id}, _from, state) do + with :ok <- Conversation.update_provider(state.name, provider_id), + {:ok, provider} <- AiProvider.find_by_id(provider_id) do + {:reply, {:ok, provider}, %{state | provider: provider}} + else + error -> {:reply, error, state} + end + end end diff --git a/lib/elixir_ai/data/ai_provider.ex b/lib/elixir_ai/data/ai_provider.ex index dcdd1ef..e98793c 100644 --- a/lib/elixir_ai/data/ai_provider.ex +++ b/lib/elixir_ai/data/ai_provider.ex @@ -114,6 +114,34 @@ defmodule ElixirAi.AiProvider do end end + def find_by_id(id) do + case Ecto.UUID.dump(id) do + {:ok, binary_id} -> + sql = """ + SELECT id, name, model_name, api_token, completions_url + FROM ai_providers + WHERE id = $(id) + LIMIT 1 + """ + + params = %{"id" => binary_id} + + case DbHelpers.run_sql(sql, params, providers_topic(), AiProviderSchema.schema()) do + {:error, _} -> + {:error, :db_error} + + [] -> + {:error, :not_found} + + [row | _] -> + {:ok, row |> convert_uuid_to_string() |> then(&struct(AiProviderSchema, &1))} + end + + :error -> + {:error, :invalid_uuid} + end + end + def delete(id) do sql = "DELETE FROM ai_providers WHERE id = $(id)::uuid" params = %{"id" => id} diff --git a/lib/elixir_ai/data/conversation.ex b/lib/elixir_ai/data/conversation.ex index 61a629a..ed74609 100644 --- a/lib/elixir_ai/data/conversation.ex +++ b/lib/elixir_ai/data/conversation.ex @@ -173,6 +173,31 @@ defmodule ElixirAi.Conversation do end end + def update_provider(name, provider_id) when is_binary(provider_id) do + case Ecto.UUID.dump(provider_id) do + {:ok, binary_id} -> + sql = """ + UPDATE conversations + SET ai_provider_id = $(ai_provider_id), updated_at = $(updated_at) + WHERE name = $(name) + """ + + params = %{ + "name" => name, + "ai_provider_id" => binary_id, + "updated_at" => now() + } + + case DbHelpers.run_sql(sql, params, "conversations") do + {:error, :db_error} -> {:error, :db_error} + _ -> :ok + end + + :error -> + {:error, :invalid_uuid} + end + end + def find_id(name) do sql = "SELECT id FROM conversations WHERE name = $(name) LIMIT 1" params = %{"name" => name} diff --git a/lib/elixir_ai_web/chat/chat_live.ex b/lib/elixir_ai_web/chat/chat_live.ex index 65cd9bc..b82d3bd 100644 --- a/lib/elixir_ai_web/chat/chat_live.ex +++ b/lib/elixir_ai_web/chat/chat_live.ex @@ -4,8 +4,7 @@ defmodule ElixirAiWeb.ChatLive do import ElixirAiWeb.Spinner import ElixirAiWeb.ChatMessage import ElixirAiWeb.ChatProviderDisplay - alias ElixirAi.ChatRunner - alias ElixirAi.ConversationManager + alias ElixirAi.{AiProvider, ChatRunner, ConversationManager} import ElixirAi.PubsubTopics def mount(%{"name" => name}, _session, socket) do @@ -27,6 +26,7 @@ defmodule ElixirAiWeb.ChatLive do |> assign(streaming_response: conversation.streaming_response) |> assign(background_color: "bg-cyan-950/30") |> assign(provider: conversation.provider) + |> assign(providers: AiProvider.all()) |> assign(db_error: nil) |> assign(ai_error: nil)} @@ -44,6 +44,7 @@ defmodule ElixirAiWeb.ChatLive do |> assign(streaming_response: nil) |> assign(background_color: "bg-cyan-950/30") |> assign(provider: nil) + |> assign(providers: AiProvider.all()) |> assign(db_error: Exception.format(:error, reason)) |> assign(ai_error: nil)} end @@ -57,7 +58,7 @@ defmodule ElixirAiWeb.ChatLive do ← {@conversation_name} - <.chat_provider_display provider={@provider} /> + <.chat_provider_display provider={@provider} providers={@providers} /> <%= if @db_error do %>