Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 9af0c2e

Browse files
authored
UX: Improve seeded LLM edit page (#856)
1 parent 0aa2789 commit 9af0c2e

File tree

4 files changed

+85
-41
lines changed

4 files changed

+85
-41
lines changed

assets/javascripts/discourse/components/ai-llm-editor-form.gjs

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Component from "@glimmer/component";
22
import { tracked } from "@glimmer/tracking";
33
import { Input } from "@ember/component";
4-
import { concat, get } from "@ember/helper";
4+
import { concat, get, hash } from "@ember/helper";
55
import { on } from "@ember/modifier";
66
import { action, computed } from "@ember/object";
77
import { LinkTo } from "@ember/routing";
@@ -189,6 +189,7 @@ export default class AiLlmEditorForm extends Component {
189189
class="ai-llm-editor-input ai-llm-editor__display-name"
190190
@type="text"
191191
@value={{@model.display_name}}
192+
disabled={{this.seeded}}
192193
/>
193194
</div>
194195
<div class="control-group">
@@ -197,24 +198,26 @@ export default class AiLlmEditorForm extends Component {
197198
class="ai-llm-editor-input ai-llm-editor__name"
198199
@type="text"
199200
@value={{@model.name}}
201+
disabled={{this.seeded}}
200202
/>
201203
<DTooltip
202204
@icon="question-circle"
203-
@content={{I18n.t "discourse_ai.llms.hints.name"}}
205+
@content={{i18n "discourse_ai.llms.hints.name"}}
204206
/>
205207
</div>
206208
<div class="control-group">
207-
<label>{{I18n.t "discourse_ai.llms.provider"}}</label>
209+
<label>{{i18n "discourse_ai.llms.provider"}}</label>
208210
<ComboBox
209211
@value={{@model.provider}}
210212
@content={{this.selectedProviders}}
211213
@class="ai-llm-editor__provider"
214+
@options={{hash disabled=this.seeded}}
212215
/>
213216
</div>
214217
{{#unless this.seeded}}
215218
{{#if this.canEditURL}}
216219
<div class="control-group">
217-
<label>{{I18n.t "discourse_ai.llms.url"}}</label>
220+
<label>{{i18n "discourse_ai.llms.url"}}</label>
218221
<Input
219222
class="ai-llm-editor-input ai-llm-editor__url"
220223
@type="text"
@@ -224,7 +227,7 @@ export default class AiLlmEditorForm extends Component {
224227
</div>
225228
{{/if}}
226229
<div class="control-group">
227-
<label>{{I18n.t "discourse_ai.llms.api_key"}}</label>
230+
<label>{{i18n "discourse_ai.llms.api_key"}}</label>
228231
<div class="ai-llm-editor__secret-api-key-group">
229232
<Input
230233
@value={{@model.api_key}}
@@ -241,7 +244,7 @@ export default class AiLlmEditorForm extends Component {
241244
</div>
242245
{{#each-in this.metaProviderParams as |field type|}}
243246
<div class="control-group ai-llm-editor-provider-param__{{type}}">
244-
<label>{{I18n.t
247+
<label>{{i18n
245248
(concat "discourse_ai.llms.provider_fields." field)
246249
}}</label>
247250
{{#if (eq type "checkbox")}}
@@ -258,7 +261,7 @@ export default class AiLlmEditorForm extends Component {
258261
</div>
259262
{{/each-in}}
260263
<div class="control-group">
261-
<label>{{I18n.t "discourse_ai.llms.tokenizer"}}</label>
264+
<label>{{i18n "discourse_ai.llms.tokenizer"}}</label>
262265
<ComboBox
263266
@value={{@model.tokenizer}}
264267
@content={{@llms.resultSetMeta.tokenizers}}
@@ -278,63 +281,64 @@ export default class AiLlmEditorForm extends Component {
278281
/>
279282
<DTooltip
280283
@icon="question-circle"
281-
@content={{I18n.t "discourse_ai.llms.hints.max_prompt_tokens"}}
284+
@content={{i18n "discourse_ai.llms.hints.max_prompt_tokens"}}
282285
/>
283286
</div>
284287
<div class="control-group ai-llm-editor__vision-enabled">
285288
<Input @type="checkbox" @checked={{@model.vision_enabled}} />
286-
<label>{{I18n.t "discourse_ai.llms.vision_enabled"}}</label>
289+
<label>{{i18n "discourse_ai.llms.vision_enabled"}}</label>
287290
<DTooltip
288291
@icon="question-circle"
289-
@content={{I18n.t "discourse_ai.llms.hints.vision_enabled"}}
292+
@content={{i18n "discourse_ai.llms.hints.vision_enabled"}}
290293
/>
291294
</div>
292295
<div class="control-group ai-llm-editor__enabled-chat-bot">
293296
<Input @type="checkbox" @checked={{@model.enabled_chat_bot}} />
294-
<label>{{I18n.t "discourse_ai.llms.enabled_chat_bot"}}</label>
297+
<label>{{i18n "discourse_ai.llms.enabled_chat_bot"}}</label>
295298
<DTooltip
296299
@icon="question-circle"
297-
@content={{I18n.t "discourse_ai.llms.hints.enabled_chat_bot"}}
300+
@content={{i18n "discourse_ai.llms.hints.enabled_chat_bot"}}
298301
/>
299302
</div>
300-
{{#if @model.user}}
301-
<div class="control-group">
302-
<label>{{i18n "discourse_ai.llms.ai_bot_user"}}</label>
303-
<a
304-
class="avatar"
305-
href={{@model.user.path}}
306-
data-user-card={{@model.user.username}}
307-
>
308-
{{Avatar @model.user.avatar_template "small"}}
309-
</a>
310-
<LinkTo @route="adminUser" @model={{this.adminUser}}>
311-
{{@model.user.username}}
312-
</LinkTo>
313-
</div>
314-
{{/if}}
303+
{{/unless}}
304+
305+
{{#if @model.user}}
306+
<div class="control-group">
307+
<label>{{i18n "discourse_ai.llms.ai_bot_user"}}</label>
308+
<a
309+
class="avatar"
310+
href={{@model.user.path}}
311+
data-user-card={{@model.user.username}}
312+
>
313+
{{Avatar @model.user.avatar_template "small"}}
314+
</a>
315+
<LinkTo @route="adminUser" @model={{this.adminUser}}>
316+
{{@model.user.username}}
317+
</LinkTo>
318+
</div>
319+
{{/if}}
320+
321+
{{#unless this.seeded}}
315322
<div class="control-group ai-llm-editor__action_panel">
316323
<DButton
317324
class="ai-llm-editor__test"
318325
@action={{this.test}}
319326
@disabled={{this.testRunning}}
320-
>
321-
{{I18n.t "discourse_ai.llms.tests.title"}}
322-
</DButton>
327+
@label="discourse_ai.llms.tests.title"
328+
/>
323329

324330
<DButton
325331
class="btn-primary ai-llm-editor__save"
326332
@action={{this.save}}
327333
@disabled={{this.isSaving}}
328-
>
329-
{{I18n.t "discourse_ai.llms.save"}}
330-
</DButton>
334+
@label="discourse_ai.llms.save"
335+
/>
331336
{{#unless @model.isNew}}
332337
<DButton
333338
@action={{this.delete}}
334339
class="btn-danger ai-llm-editor__delete"
335-
>
336-
{{I18n.t "discourse_ai.llms.delete"}}
337-
</DButton>
340+
@label="discourse_ai.llms.delete"
341+
/>
338342
{{/unless}}
339343
</div>
340344
{{/unless}}
@@ -343,12 +347,12 @@ export default class AiLlmEditorForm extends Component {
343347
{{#if this.displayTestResult}}
344348
{{#if this.testRunning}}
345349
<div class="spinner small"></div>
346-
{{I18n.t "discourse_ai.llms.tests.running"}}
350+
{{i18n "discourse_ai.llms.tests.running"}}
347351
{{else}}
348352
{{#if this.testResult}}
349353
<div class="ai-llm-editor-tests__success">
350354
{{icon "check"}}
351-
{{I18n.t "discourse_ai.llms.tests.success"}}
355+
{{i18n "discourse_ai.llms.tests.success"}}
352356
</div>
353357
{{else}}
354358
<div class="ai-llm-editor-tests__failure">

assets/javascripts/discourse/components/ai-llms-list-editor.gjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export default class AiLlmsListEditor extends Component {
135135
</thead>
136136
<tbody>
137137
{{#each @llms as |llm|}}
138-
<tr data-persona-id={{llm.id}} class="ai-llm-list__row">
138+
<tr data-llm-id={{llm.name}} class="ai-llm-list__row">
139139
<td class="column-name">
140140
<h3>{{llm.display_name}}</h3>
141141
<p>
@@ -149,7 +149,7 @@ export default class AiLlmsListEditor extends Component {
149149
</ul>
150150
{{/if}}
151151
</td>
152-
<td>
152+
<td class="column-provider">
153153
{{i18n
154154
(concat "discourse_ai.llms.providers." llm.provider)
155155
}}

spec/fabricators/llm_model_fabricator.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,14 @@
8989
url "http://api.ollama.ai/api/chat"
9090
provider_params { { enable_native_tool: true } }
9191
end
92+
93+
Fabricator(:seeded_model, from: :llm_model) do
94+
id "-2"
95+
display_name "CDCK Hosted Model"
96+
name "cdck-hosted"
97+
provider "fake"
98+
api_key "DSC"
99+
tokenizer "DiscourseAi::Tokenizer::OpenAiTokenizer"
100+
url "https://cdck.test/"
101+
enabled_chat_bot true
102+
end

spec/system/llms/ai_llm_spec.rb

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# frozen_string_literal: true
22

3-
RSpec.describe "Managing LLM configurations", type: :system do
3+
RSpec.describe "Managing LLM configurations", type: :system, js: true do
44
fab!(:admin)
55

66
before do
@@ -69,4 +69,33 @@
6969
expect(llm.vision_enabled).to eq(true)
7070
expect(llm.user_id).not_to be_nil
7171
end
72+
73+
context "when seeded LLM is present" do
74+
fab!(:llm_model) { Fabricate(:seeded_model) }
75+
76+
it "shows the provider as CDCK in the UI" do
77+
visit "/admin/plugins/discourse-ai/ai-llms"
78+
expect(page).to have_css(
79+
"[data-llm-id='cdck-hosted'] .column-provider",
80+
text: I18n.t("js.discourse_ai.llms.providers.CDCK"),
81+
)
82+
end
83+
84+
it "shows an info alert to the user about the seeded LLM" do
85+
visit "/admin/plugins/discourse-ai/ai-llms"
86+
find("[data-llm-id='#{llm_model.name}'] .column-edit .btn").click()
87+
expect(page).to have_css(
88+
".alert.alert-info",
89+
text: I18n.t("js.discourse_ai.llms.seeded_warning"),
90+
)
91+
end
92+
93+
it "limits and shows disabled inputs for the seeded LLM" do
94+
visit "/admin/plugins/discourse-ai/ai-llms"
95+
find("[data-llm-id='cdck-hosted'] .column-edit .btn").click()
96+
expect(page).to have_css(".ai-llm-editor__display-name[disabled]")
97+
expect(page).to have_css(".ai-llm-editor__name[disabled]")
98+
expect(page).to have_css(".ai-llm-editor__provider.is-disabled")
99+
end
100+
end
72101
end

0 commit comments

Comments
 (0)