fix: persist a2ui surfaces in the database for chats to re-hydrate on

opening an old chat, unless manually dismissed
This commit is contained in:
2026-05-27 20:13:33 +02:00
parent 141c2bfc89
commit f7a4a9512c
8 changed files with 241 additions and 5 deletions

View File

@@ -62,6 +62,42 @@ defmodule BDS.AI.Chat do
Repo.get(ChatConversation, conversation_id)
end
@spec get_surface_state(String.t()) :: map()
def get_surface_state(conversation_id) when is_binary(conversation_id) do
case Repo.get(ChatConversation, conversation_id) do
%ChatConversation{surface_state: state} when is_map(state) -> state
_other -> %{}
end
end
@spec put_surface_state(String.t(), map(), map(), MapSet.t()) ::
{:ok, map()} | {:error, term()}
def put_surface_state(conversation_id, surface_data, surface_tabs, dismissed_surfaces)
when is_binary(conversation_id) do
case Repo.get(ChatConversation, conversation_id) do
nil ->
{:error, :not_found}
%ChatConversation{} = conversation ->
state = %{
"surface_data" => surface_data,
"surface_tabs" => surface_tabs,
"dismissed_surfaces" => MapSet.to_list(dismissed_surfaces)
}
conversation
|> ChatConversation.changeset(%{
surface_state: state,
updated_at: Persistence.now_ms()
})
|> Repo.update()
|> case do
{:ok, _updated} -> {:ok, state}
error -> error
end
end
end
@spec delete_chat_conversation(String.t()) :: {:ok, :deleted} | {:error, :not_found | term()}
def delete_chat_conversation(conversation_id) when is_binary(conversation_id) do
case Repo.get(ChatConversation, conversation_id) do

View File

@@ -11,6 +11,7 @@ defmodule BDS.AI.ChatConversation do
title: String.t() | nil,
model: String.t() | nil,
copilot_session_id: String.t() | nil,
surface_state: map() | nil,
created_at: integer() | nil,
updated_at: integer() | nil
}
@@ -19,13 +20,14 @@ defmodule BDS.AI.ChatConversation do
field :title, :string
field :model, :string
field :copilot_session_id, :string
field :surface_state, :map
field :created_at, :integer
field :updated_at, :integer
end
def changeset(conversation, attrs) do
conversation
|> cast(attrs, [:id, :title, :model, :copilot_session_id, :created_at, :updated_at],
|> cast(attrs, [:id, :title, :model, :copilot_session_id, :surface_state, :created_at, :updated_at],
empty_values: [nil]
)
|> validate_required([:id, :title, :created_at, :updated_at])