fix: provide target language for AI suggestions
This commit is contained in:
@@ -660,6 +660,44 @@ defmodule BDS.AITest do
|
||||
assert message =~ "# Draft body"
|
||||
end
|
||||
|
||||
test "analyze_post respects the language option and instructs the model to respond in that language" do
|
||||
assert {:ok, _endpoint} =
|
||||
BDS.AI.put_endpoint(
|
||||
:online,
|
||||
%{
|
||||
url: "https://api.example.test/v1",
|
||||
api_key: "online-secret",
|
||||
model: "gpt-4o-mini"
|
||||
},
|
||||
secret_backend: FakeSecretBackend
|
||||
)
|
||||
|
||||
assert :ok = BDS.AI.set_airplane_mode(false)
|
||||
assert :ok = BDS.AI.put_model_preference(:title, "gpt-4.1-mini")
|
||||
|
||||
assert {:ok, result} =
|
||||
BDS.AI.analyze_post(
|
||||
%{
|
||||
title: "Draft Post",
|
||||
excerpt: "Short summary",
|
||||
content: "# Draft body"
|
||||
},
|
||||
language: "de",
|
||||
runtime: FakeRuntime,
|
||||
test_pid: self(),
|
||||
secret_backend: FakeSecretBackend
|
||||
)
|
||||
|
||||
assert result.title =~ "Draft Post"
|
||||
|
||||
assert_received {:runtime_request, _endpoint, request}
|
||||
assert request.operation == :analyze_post
|
||||
system_message = get_in(request.messages, [Access.at(0), "content"]) || ""
|
||||
user_message = get_in(request.messages, [Access.at(1), "content"]) || ""
|
||||
assert system_message =~ "German"
|
||||
assert user_message =~ "German"
|
||||
end
|
||||
|
||||
test "analyze_import_taxonomy uses the selected model override and returns only valid existing-term mappings" do
|
||||
assert {:ok, _endpoint} =
|
||||
BDS.AI.put_endpoint(
|
||||
@@ -867,6 +905,54 @@ defmodule BDS.AITest do
|
||||
assert image_content["image_url"]["url"] =~ ~r/^data:image\/png;base64,/
|
||||
end
|
||||
|
||||
test "analyze_image respects the language option and instructs the model to respond in that language" do
|
||||
assert {:ok, _endpoint} =
|
||||
BDS.AI.put_endpoint(
|
||||
:airplane,
|
||||
%{
|
||||
url: "http://localhost:11434/v1",
|
||||
api_key: nil,
|
||||
model: "llama-default"
|
||||
},
|
||||
secret_backend: FakeSecretBackend
|
||||
)
|
||||
|
||||
assert :ok = BDS.AI.set_airplane_mode(true)
|
||||
assert :ok = BDS.AI.put_model_preference(:airplane_image_analysis, "llama3.2")
|
||||
|
||||
assert :ok =
|
||||
BDS.AI.put_model_capabilities("llama3.2", %{
|
||||
supports_attachment: true,
|
||||
supports_tool_calls: false,
|
||||
disables_reasoning: false
|
||||
})
|
||||
|
||||
assert {:ok, analysis} =
|
||||
BDS.AI.analyze_image(
|
||||
%{
|
||||
mime_type: "image/png",
|
||||
title: "Source",
|
||||
alt: nil,
|
||||
caption: nil,
|
||||
image_url: "https://example.com/test.png"
|
||||
},
|
||||
language: "de",
|
||||
runtime: FakeRuntime,
|
||||
test_pid: self(),
|
||||
secret_backend: FakeSecretBackend
|
||||
)
|
||||
|
||||
assert analysis.title == "Sunset"
|
||||
|
||||
assert_received {:runtime_request, _endpoint, request}
|
||||
assert request.operation == :analyze_image
|
||||
system_message = get_in(request.messages, [Access.at(0), "content"]) || ""
|
||||
user_message = Enum.at(request.messages, 1)
|
||||
text_content = Enum.at(user_message["content"], 0)
|
||||
assert system_message =~ "German"
|
||||
assert text_content["text"] =~ "German"
|
||||
end
|
||||
|
||||
test "chat persists user, tool, and assistant messages with usage and blog stats prompt augmentation" do
|
||||
{:ok, project} = create_project_fixture("AI Chat")
|
||||
_fixtures = seed_project_content(project.id)
|
||||
|
||||
@@ -2415,6 +2415,68 @@ defmodule BDS.Desktop.ShellLiveTest do
|
||||
refute html =~ "Loading"
|
||||
end
|
||||
|
||||
test "ai suggestions overlay sends project main language for posts", %{project: project} do
|
||||
Application.put_env(:bds, :test_pid, self())
|
||||
|
||||
server =
|
||||
start_supervised!({Bandit, plug: AiSuggestionsServer, port: 0, startup_log: false})
|
||||
|
||||
{:ok, {_address, port}} = ThousandIsland.listener_info(server)
|
||||
|
||||
assert :ok = AI.set_airplane_mode(false)
|
||||
|
||||
assert {:ok, _endpoint} =
|
||||
AI.put_endpoint(:online, %{
|
||||
url: "http://127.0.0.1:#{port}/v1",
|
||||
api_key: "test-secret",
|
||||
model: "gpt-test"
|
||||
})
|
||||
|
||||
assert :ok = AI.put_model_preference(:title, "gpt-test")
|
||||
|
||||
assert {:ok, _metadata} = Metadata.update_project_metadata(project.id, %{main_language: "de"})
|
||||
|
||||
{:ok, post} =
|
||||
Posts.create_post(%{
|
||||
project_id: project.id,
|
||||
title: "German Post",
|
||||
content: "Some content for AI analysis"
|
||||
})
|
||||
|
||||
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
|
||||
|
||||
html =
|
||||
render_click(view, "pin_sidebar_item", %{
|
||||
"route" => "post",
|
||||
"id" => post.id,
|
||||
"title" => post.title,
|
||||
"subtitle" => "draft"
|
||||
})
|
||||
|
||||
assert html =~ ~s(data-testid="post-editor")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("[data-testid='post-editor'] .quick-actions-btn")
|
||||
|> render_click()
|
||||
|
||||
assert html =~ "quick-actions-menu"
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("[phx-click='open_overlay'][phx-value-kind='ai_suggestions']")
|
||||
|> render_click()
|
||||
|
||||
assert html =~ "ai-suggestions-modal"
|
||||
|
||||
assert_receive {:ai_suggestions_request, request}, 2_000
|
||||
|
||||
system_message = get_in(request, ["messages", Access.at(0), "content"]) || ""
|
||||
user_message = get_in(request, ["messages", Access.at(1), "content"]) || ""
|
||||
assert system_message =~ "German"
|
||||
assert user_message =~ "German"
|
||||
end
|
||||
|
||||
test "ai suggestions overlay is gated by offline mode for media", %{project: project} do
|
||||
assert :ok = AI.set_airplane_mode(true)
|
||||
|
||||
@@ -2532,6 +2594,77 @@ defmodule BDS.Desktop.ShellLiveTest do
|
||||
refute html =~ "Loading"
|
||||
end
|
||||
|
||||
test "ai suggestions overlay sends project main language for media", %{project: project} do
|
||||
Application.put_env(:bds, :test_pid, self())
|
||||
|
||||
server =
|
||||
start_supervised!({Bandit, plug: AiSuggestionsServer, port: 0, startup_log: false})
|
||||
|
||||
{:ok, {_address, port}} = ThousandIsland.listener_info(server)
|
||||
|
||||
assert :ok = AI.set_airplane_mode(false)
|
||||
|
||||
assert {:ok, _endpoint} =
|
||||
AI.put_endpoint(:online, %{
|
||||
url: "http://127.0.0.1:#{port}/v1",
|
||||
api_key: "test-secret",
|
||||
model: "gpt-test"
|
||||
})
|
||||
|
||||
assert :ok = AI.put_model_preference(:image_analysis, "gpt-test")
|
||||
assert :ok = AI.put_model_capabilities("gpt-test", %{supports_attachment: true})
|
||||
|
||||
assert {:ok, _metadata} = Metadata.update_project_metadata(project.id, %{main_language: "de"})
|
||||
|
||||
temp_dir =
|
||||
Path.join(System.tmp_dir!(), "bds-shell-live-#{System.unique_integer([:positive])}")
|
||||
|
||||
File.mkdir_p!(temp_dir)
|
||||
media_source_path = Path.join(temp_dir, "german-media.jpg")
|
||||
File.write!(media_source_path, "fake image body")
|
||||
|
||||
{:ok, media} =
|
||||
Media.import_media(%{
|
||||
project_id: project.id,
|
||||
source_path: media_source_path,
|
||||
title: "German Media"
|
||||
})
|
||||
|
||||
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
|
||||
|
||||
html =
|
||||
render_click(view, "pin_sidebar_item", %{
|
||||
"route" => "media",
|
||||
"id" => media.id,
|
||||
"title" => media.title,
|
||||
"subtitle" => "draft"
|
||||
})
|
||||
|
||||
assert html =~ ~s(data-testid="media-editor")
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("[data-testid='media-editor'] .quick-actions-btn")
|
||||
|> render_click()
|
||||
|
||||
assert html =~ "quick-actions-menu"
|
||||
|
||||
html =
|
||||
view
|
||||
|> element("[phx-click='open_overlay'][phx-value-kind='ai_suggestions']")
|
||||
|> render_click()
|
||||
|
||||
assert html =~ "ai-suggestions-modal"
|
||||
|
||||
assert_receive {:ai_suggestions_request, request}, 2_000
|
||||
|
||||
system_message = get_in(request, ["messages", Access.at(0), "content"]) || ""
|
||||
user_message = Enum.at(request["messages"], 1)
|
||||
text_content = Enum.at(user_message["content"], 0)
|
||||
assert system_message =~ "German"
|
||||
assert text_content["text"] =~ "German"
|
||||
end
|
||||
|
||||
test "ai suggestions async error closes overlay and shows toast", %{project: project} do
|
||||
Application.put_env(:bds, :test_pid, self())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user