fixing provider switching
Some checks failed
CI/CD Pipeline / build (push) Failing after 4s

This commit is contained in:
2026-03-23 13:27:27 -06:00
parent d5cd472bf5
commit 10d6583a67
6 changed files with 150 additions and 25 deletions

View File

@@ -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
</.link>
<span class="flex-1">{@conversation_name}</span>
<.chat_provider_display provider={@provider} />
<.chat_provider_display provider={@provider} providers={@providers} />
</div>
<%= if @db_error do %>
<div class="mx-4 mt-2 px-3 py-2 rounded text-sm text-red-400 bg-red-950/40" role="alert">
@@ -122,6 +123,13 @@ defmodule ElixirAiWeb.ChatLive do
{:noreply, assign(socket, user_input: user_input)}
end
def handle_event("change_provider", %{"id" => provider_id}, socket) do
case ChatRunner.set_provider(socket.assigns.conversation_name, provider_id) do
{:ok, provider} -> {:noreply, assign(socket, provider: provider)}
_error -> {:noreply, socket}
end
end
def handle_event("submit", %{"user_input" => user_input}, socket) when user_input != "" do
ChatRunner.new_user_message(socket.assigns.conversation_name, user_input)
{:noreply, assign(socket, user_input: "")}

View File

@@ -1,31 +1,82 @@
defmodule ElixirAiWeb.ChatProviderDisplay do
use Phoenix.Component
alias Phoenix.LiveView.JS
attr :provider, :any, default: nil
def chat_provider_display(%{provider: nil} = assigns) do
~H"""
<div class="flex items-center gap-1.5 text-xs text-cyan-900 italic">
No provider set
</div>
"""
end
attr :providers, :list, default: []
def chat_provider_display(assigns) do
~H"""
<div class="flex items-center gap-2 text-xs min-w-0">
<div class="flex items-center gap-1.5 px-2 py-1 rounded bg-cyan-950/50 border border-cyan-900/40 min-w-0">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-3 h-3 shrink-0 text-cyan-600"
>
<path d="M10 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM6 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM1.49 15.326a.78.78 0 0 1-.358-.442 3 3 0 0 1 4.308-3.516 6.484 6.484 0 0 0-1.905 3.959c-.023.222-.014.442.025.654a4.97 4.97 0 0 1-2.07-.655ZM16.44 15.98a4.97 4.97 0 0 0 2.07-.654.78.78 0 0 0 .357-.442 3 3 0 0 0-4.308-3.516 6.484 6.484 0 0 1 1.907 3.96 2.32 2.32 0 0 1-.026.654ZM18 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM5.304 16.19a.844.844 0 0 1-.277-.71 5 5 0 0 1 9.947 0 .843.843 0 0 1-.277.71A6.975 6.975 0 0 1 10 18a6.974 6.974 0 0 1-4.696-1.81Z" />
</svg>
<span class="text-cyan-400 font-medium truncate">{@provider.name}</span>
<span class="text-cyan-800">·</span>
<span class="text-cyan-600 truncate">{@provider.model_name}</span>
<div class="relative" id="provider-display">
<button
type="button"
phx-click={JS.toggle(to: "#provider-dropdown")}
class="flex items-center gap-2 text-xs min-w-0 cursor-pointer hover:opacity-80 transition-opacity"
>
<div class="flex items-center gap-1.5 px-2 py-1 rounded bg-cyan-950/50 border border-cyan-900/40 min-w-0 select-none">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-3 h-3 shrink-0 text-cyan-600"
>
<path d="M10 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM6 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM1.49 15.326a.78.78 0 0 1-.358-.442 3 3 0 0 1 4.308-3.516 6.484 6.484 0 0 0-1.905 3.959c-.023.222-.014.442.025.654a4.97 4.97 0 0 1-2.07-.655ZM16.44 15.98a4.97 4.97 0 0 0 2.07-.654.78.78 0 0 0 .357-.442 3 3 0 0 0-4.308-3.516 6.484 6.484 0 0 1 1.907 3.96 2.32 2.32 0 0 1-.026.654ZM18 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM5.304 16.19a.844.844 0 0 1-.277-.71 5 5 0 0 1 9.947 0 .843.843 0 0 1-.277.71A6.975 6.975 0 0 1 10 18a6.974 6.974 0 0 1-4.696-1.81Z" />
</svg>
<%= if @provider do %>
<span class="text-cyan-400 font-medium truncate">{@provider.name}</span>
<span class="text-cyan-800">·</span>
<span class="text-cyan-600 truncate">{@provider.model_name}</span>
<% else %>
<span class="text-cyan-800 italic">No provider</span>
<% end %>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-2.5 h-2.5 text-cyan-700 ml-0.5 shrink-0"
>
<path
fill-rule="evenodd"
d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z"
clip-rule="evenodd"
/>
</svg>
</div>
</button>
<div
id="provider-dropdown"
class="hidden absolute right-0 top-full mt-1 z-50 min-w-max bg-gray-950 border border-cyan-900/40 rounded shadow-xl overflow-hidden"
phx-click-away={JS.hide(to: "#provider-dropdown")}
>
<%= if @providers == [] do %>
<div class="px-3 py-2 text-xs text-gray-500 italic">No providers configured</div>
<% else %>
<%= for p <- @providers do %>
<button
type="button"
phx-click={
JS.hide(to: "#provider-dropdown")
|> JS.push("change_provider", value: %{id: p.id})
}
class={[
"flex flex-col px-3 py-2 text-left w-full text-xs hover:bg-cyan-950/60 transition-colors",
if(@provider && @provider.name == p.name,
do: "text-cyan-400",
else: "text-gray-300"
)
]}
>
<span class="font-medium">{p.name}</span>
<span class={
if @provider && @provider.name == p.name,
do: "text-cyan-700",
else: "text-gray-500"
}>
{p.model_name}
</span>
</button>
<% end %>
<% end %>
</div>
</div>
"""