Skip to content

Commit 0adc6ac

Browse files
committed
refactored
1 parent 5ce1ff1 commit 0adc6ac

4 files changed

Lines changed: 11 additions & 44 deletions

File tree

lib/mindwendel/services/chat_completions/chat_completions_service_impl.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ defmodule Mindwendel.Services.ChatCompletions.ChatCompletionsServiceImpl do
8282

8383
has_multiple_lanes = length(lanes) > 1
8484

85-
# System prompt - contains only instructions, no user-generated content
85+
# System prompt must contain only instructions, never user-generated content
8686
system_content =
8787
if has_multiple_lanes do
8888
~s|Generate ONLY valid JSON in the specified language. Format: [{"idea": "string", "lane_id": "uuid-or-null"}]. | <>
@@ -148,6 +148,7 @@ defmodule Mindwendel.Services.ChatCompletions.ChatCompletionsServiceImpl do
148148
ideas
149149
|> Enum.map(&normalize_idea_payload/1)
150150

151+
# System prompt must remain free of user-generated content to avoid prompt injection
151152
system_content =
152153
"You cluster brainstorming ideas into the existing labels provided. Respond ONLY with valid JSON. " <>
153154
~s|Format: [{"idea_id": "uuid", "label_ids": ["uuid"...], "new_labels": [{"id": "uuid", "name": "string or null", "color": "#rrggbb or null"}]}]. | <>

lib/mindwendel/services/idea_clustering_service.ex

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@ defmodule Mindwendel.Services.IdeaClusteringService do
88

99
require Logger
1010

11-
import Ecto.Query, only: [from: 2]
12-
1311
alias Mindwendel.Brainstormings.Brainstorming
1412
alias Mindwendel.Brainstormings.IdeaLabel
15-
alias Mindwendel.Brainstormings.Lane
1613
alias Mindwendel.IdeaLabels
1714
alias Mindwendel.Ideas
1815
alias Mindwendel.Repo
@@ -486,16 +483,5 @@ defmodule Mindwendel.Services.IdeaClusteringService do
486483

487484
defp normalize_label_name(_), do: nil
488485

489-
defp preload_brainstorming(brainstorming) do
490-
Repo.preload(brainstorming, [
491-
:labels,
492-
lanes:
493-
from(l in Lane,
494-
order_by: [
495-
asc: l.position_order,
496-
asc: l.inserted_at
497-
]
498-
)
499-
])
500-
end
486+
defp preload_brainstorming(brainstorming), do: Repo.preload(brainstorming, :labels)
501487
end

lib/mindwendel_web/live/brainstorming_live/show.ex

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -286,20 +286,8 @@ defmodule MindwendelWeb.BrainstormingLive.Show do
286286
)
287287
end
288288

289-
defp handle_ai_clustering_result({:ok, assignments} = result, id, socket)
290-
when is_list(assignments) do
291-
lanes = Lanes.get_lanes_for_brainstorming_with_labels_filtered(id)
292-
293-
socket =
294-
socket
295-
|> assign(:lanes, lanes)
296-
|> maybe_assign_updated_brainstorming(id)
297-
|> put_clustering_flash(result)
298-
299-
{:noreply, socket}
300-
end
301-
302-
defp handle_ai_clustering_result({:ok, :skipped} = result, id, socket) do
289+
defp handle_ai_clustering_result({:ok, outcome} = result, id, socket)
290+
when is_list(outcome) or outcome == :skipped do
303291
lanes = Lanes.get_lanes_for_brainstorming_with_labels_filtered(id)
304292

305293
socket =

test/support/chat_completions_case.ex

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,16 @@ defmodule Mindwendel.ChatCompletionsCase do
2626

2727
# Default stub: AI is disabled
2828
# Tests can override this with expect() for specific behavior
29-
def setup_ai_disabled_stub(_context) do
30-
Mindwendel.Services.ChatCompletions.ChatCompletionsServiceMock
31-
|> stub(:enabled?, fn -> false end)
32-
|> stub(:generate_ideas, fn _title, _lanes, _existing_ideas, _locale ->
33-
{:error, :ai_not_enabled}
34-
end)
35-
|> stub(:classify_labels, fn _title, _labels, _ideas, _locale ->
36-
{:error, :ai_not_enabled}
37-
end)
38-
39-
:ok
40-
end
29+
def setup_ai_disabled_stub(_context), do: disable_ai()
4130

4231
# Helper to explicitly stub AI as disabled (for clarity in tests)
4332
def disable_ai do
4433
# Already stubbed in setup, but this allows explicit calls
34+
stub_ai_disabled()
35+
:ok
36+
end
37+
38+
defp stub_ai_disabled do
4539
Mindwendel.Services.ChatCompletions.ChatCompletionsServiceMock
4640
|> stub(:enabled?, fn -> false end)
4741
|> stub(:generate_ideas, fn _title, _lanes, _existing_ideas, _locale ->
@@ -50,8 +44,6 @@ defmodule Mindwendel.ChatCompletionsCase do
5044
|> stub(:classify_labels, fn _title, _labels, _ideas, _locale ->
5145
{:error, :ai_not_enabled}
5246
end)
53-
54-
:ok
5547
end
5648

5749
# Helper to set up AI enabled with specific expectations

0 commit comments

Comments
 (0)