|
1 | 1 | defmodule Console.Chat.Utils do |
2 | 2 | alias Console.Chat.Reference |
3 | | - alias Console.Schema.{WorkbenchChatbot, ChatConnection, User} |
| 3 | + alias Console.Schema.{ |
| 4 | + WorkbenchChatbot, |
| 5 | + WorkbenchJob, |
| 6 | + ChatConnection, |
| 7 | + User, |
| 8 | + ChatbotMessage |
| 9 | + } |
4 | 10 | alias Console.Deployments.Workbenches |
5 | 11 | alias Console.Repo |
| 12 | + use Nebulex.Caching |
6 | 13 |
|
7 | 14 | require EEx |
8 | 15 |
|
| 16 | + @cache Console.conf(:cache_adapter) |
| 17 | + |
| 18 | + @decorate cacheable(cache: @cache, key: {:chatbot_msg, id}, opts: [ttl: :timer.hours(24)]) |
| 19 | + def chatbot_msg(id), do: Repo.get_by(ChatbotMessage, external_id: id) |
| 20 | + |
| 21 | + def cache_msg(%ChatbotMessage{} = msg), do: @cache.put({:chatbot_msg, cache_id(msg)}, msg, ttl: :timer.hours(24)) |
| 22 | + |
9 | 23 | def handle_mention(%Reference{} = msg, %Reference{} = chan_ref, %ChatConnection{} = conn), |
10 | 24 | do: handle_mention(msg, chan_ref, conn, %{}) |
11 | 25 |
|
12 | 26 | @doc """ |
13 | 27 | Looks up the workbench chatbot bound to the mentioned channel and, if found, spawns a workbench job for the |
14 | | - request. `extra` is merged into the persisted `ChatbotMessage`, letting providers stash reply coordinates |
15 | | - (e.g. teams `service_url`/`conversation_id`/`activity_id`) needed to respond out-of-band. |
| 28 | + request (or appends to the in-flight parent job when the mention is a threaded reply). `extra` is merged into |
| 29 | + the persisted `ChatbotMessage`, letting providers stash reply coordinates (e.g. teams |
| 30 | + `service_url`/`conversation_id`/`activity_id`) needed to respond out-of-band. |
16 | 31 | """ |
17 | | - def handle_mention(%Reference{} = msg, %Reference{text: channel} = chan_ref, %ChatConnection{id: id} = conn, %{} = extra) do |
18 | | - Workbenches.workbench_chatbot(id, channel) |
19 | | - |> Repo.preload([user: [:groups]]) |
| 32 | + def handle_mention(%Reference{id: external_id} = msg, %Reference{text: channel} = chan_ref, %ChatConnection{id: id} = conn, %{} = extra) do |
| 33 | + bot = Workbenches.workbench_chatbot(id, channel) |> Repo.preload([user: [:groups]]) |
| 34 | + with %WorkbenchChatbot{user: %User{} = user, prompt: prompt, message_behavior: behavior} = chatbot <- bot do |
| 35 | + prompt = prompt(chat: conn, msg: msg, channel: chan_ref, custom: prompt, behavior: behavior) |
| 36 | + case parent_job(msg) do |
| 37 | + %WorkbenchJob{} = job -> Workbenches.create_message(%{prompt: prompt}, job, user) |
| 38 | + _ -> |
| 39 | + chatbot_message = |
| 40 | + Map.merge(%{ |
| 41 | + message: msg.text, |
| 42 | + channel: channel, |
| 43 | + chat_connection_id: id, |
| 44 | + external_id: external_id, |
| 45 | + external_parent_id: msg.parent_id |
| 46 | + }, extra) |
| 47 | + |
| 48 | + Workbenches.create_workbench_job(%{ |
| 49 | + prompt: prompt, |
| 50 | + workbench_id: chatbot.workbench_id, |
| 51 | + modes: Console.mapify(chatbot.modes), |
| 52 | + chatbot_message: chatbot_message |
| 53 | + }, chatbot.workbench_id, user) |
| 54 | + end |
| 55 | + else |
| 56 | + _ -> :ok |
| 57 | + end |
| 58 | + end |
| 59 | + |
| 60 | + defp parent_job(%Reference{parent_id: id}) when is_binary(id) do |
| 61 | + chatbot_msg(id) |
| 62 | + |> Repo.preload(:workbench_job, force: true) |
20 | 63 | |> case do |
21 | | - %WorkbenchChatbot{user: %User{} = user, prompt: prompt, message_behavior: behavior} = chatbot -> |
22 | | - chatbot_message = |
23 | | - Map.merge(%{message: msg.text, channel: channel, chat_connection_id: id}, extra) |
24 | | - |
25 | | - Workbenches.create_workbench_job(%{ |
26 | | - prompt: prompt(chat: conn, msg: msg, channel: chan_ref, custom: prompt, behavior: behavior), |
27 | | - workbench_id: chatbot.workbench_id, |
28 | | - modes: Console.mapify(chatbot.modes), |
29 | | - chatbot_message: chatbot_message |
30 | | - }, chatbot.workbench_id, user) |
31 | | - nil -> :ok |
| 64 | + %ChatbotMessage{workbench_job: %WorkbenchJob{status: s} = job} when s not in ~w(running pending)a -> job |
| 65 | + _ -> nil |
32 | 66 | end |
33 | 67 | end |
| 68 | + defp parent_job(%Reference{parent_id: nil}), do: nil |
| 69 | + |
| 70 | + defp cache_id(%ChatbotMessage{external_id: id}) when is_binary(id), do: id |
| 71 | + defp cache_id(%ChatbotMessage{id: id}), do: id |
34 | 72 |
|
35 | 73 | EEx.function_from_file(:defp, :prompt, Console.priv_filename(["prompts", "workbench", "chat.md.eex"]), [:assigns]) |
36 | 74 | end |
0 commit comments