feat: the model's short name up to 9 characters, the chat 408px wide so nine of the widest letters fit

This commit is contained in:
redtea committed 2026-10-17 15:07:49 +03:00
1 parent 6a17f40042
commit 6c1da79b4a
5 files changed
+10 -10

No files matched your search

+3 -3
View File
@@ -44,7 +44,7 @@ const (
func aiUserKey(id int64) string { return "ai_user_" + strconv.FormatInt(id, 10) }
// aiConfig is one model the assistant can ask: its id and the names the chat
// shows (Short, up to 7 characters, on the button of the model in use), the
// shows (Short, up to 9 characters, on the button of the model in use), the
// kind of API, its address, model and key.
type aiConfig struct {
ID string `json:"id"`
@@ -77,8 +77,8 @@ func (c aiConfig) tidy() aiConfig {
c.Type = "gradio"
}
c.Name, c.Model, c.Key = strings.TrimSpace(c.Name), strings.TrimSpace(c.Model), strings.TrimSpace(c.Key)
if r := []rune(strings.TrimSpace(c.Short)); len(r) > 7 {
c.Short = strings.TrimSpace(string(r[:7]))
if r := []rune(strings.TrimSpace(c.Short)); len(r) > 9 {
c.Short = strings.TrimSpace(string(r[:9]))
} else {
c.Short = string(r)
}
+2 -2
View File
@@ -60,11 +60,11 @@ func TestAIModelsSaveAndList(t *testing.T) {
{"", "", "", "", "", "", ""}, // an empty card is dropped
})
ms := s.aiModels()
if len(ms) != 2 || ms[0].Name != "Qwen" || ms[1].Name != "Claude" || ms[1].Key != "secret-key" || ms[0].ID == "" || ms[0].ID == ms[1].ID || ms[1].Short != "Сонет 4" {
if len(ms) != 2 || ms[0].Name != "Qwen" || ms[1].Name != "Claude" || ms[1].Key != "secret-key" || ms[0].ID == "" || ms[0].ID == ms[1].ID || ms[1].Short != "Сонет 4.5" {
t.Fatalf("models: %+v", ms)
}
body := get(t, s, c, "/api/panel/ai").Body.String()
if strings.Contains(body, "secret-key") || !strings.Contains(body, `"name":"Claude"`) || !strings.Contains(body, `"short":"Сонет 4"`) || !strings.Contains(body, ms[1].ID) {
if strings.Contains(body, "secret-key") || !strings.Contains(body, `"name":"Claude"`) || !strings.Contains(body, `"short":"Сонет 4.5"`) || !strings.Contains(body, ms[1].ID) {
t.Fatalf("state: %s", body)
}
// Saved again with its id, a model keeps it.
+2 -2
View File
@@ -844,7 +844,7 @@ dialog.machinedlg { max-width:1000px; width:94vw; max-height:90vh; padding:0; ov
display:inline-flex; align-items:center; justify-content:center; box-shadow:0 8px 24px rgba(0,0,0,.45); }
.ai-fab[hidden] { display:none; }
body.touch.term-active .ai-fab { bottom:104px; }
.ai-box { position:fixed; right:28px; bottom:96px; z-index:41; width:384px; max-width:calc(100vw - 24px); height:min(500px, calc(100vh - 120px));
.ai-box { position:fixed; right:28px; bottom:96px; z-index:41; width:408px; max-width:calc(100vw - 24px); height:min(500px, calc(100vh - 120px));
display:flex; flex-direction:column; background:var(--panel); border:1px solid var(--border); border-radius:12px;
box-shadow:0 18px 44px rgba(0,0,0,.55); overflow:hidden; transform-origin:bottom right;
opacity:0; visibility:hidden; pointer-events:none; transform:translateY(14px) scale(.96);
@@ -963,7 +963,7 @@ dialog.uidlg { width:fit-content; min-width:min(300px, 92vw); max-width:min(560p
pointed at; the list opens upwards, as a small card. */
.ai-mpick { position:relative; margin-left:auto; min-width:0; }
.ai-mpick[hidden] { display:none; }
/* A short name (7 characters at most) is shown whole. */
/* A short name (9 characters at most) is shown whole. */
.ai-mpick.short { flex-shrink:0; }
.ai-mbtn { display:inline-flex; align-items:center; gap:3px; max-width:100%; height:28px; padding:0 5px 0 7px; border:0; border-radius:8px;
background:transparent; color:var(--muted); font-size:12.5px; font-weight:500; transition:background-color .15s, color .15s; }
+2 -2
View File
@@ -157,7 +157,7 @@
{{range .AIModels}} <fieldset class="ai-model">
<input type="hidden" name="m_id" value="{{.ID}}">
<div class="ai-model-head"><label class="ai-model-name">Название в чате<input type="text" name="m_name" value="{{.Name}}" placeholder="например, Claude"></label>
<label class="ai-model-short">Коротко<input type="text" name="m_short" value="{{.Short}}" maxlength="7" placeholder="до 7" title="Название на кнопке модели в чате, до 7 символов"></label>
<label class="ai-model-short">Коротко<input type="text" name="m_short" value="{{.Short}}" maxlength="9" placeholder="до 9" title="Название на кнопке модели в чате, до 9 символов"></label>
<button type="button" class="btn ghost small close ai-model-del" title="Удалить модель" aria-label="Удалить модель">Удалить</button></div>
<label>Тип API<select name="m_type">
<option value="gradio"{{if eq .Type "gradio"}} selected{{end}}>Gradio (Qwen Omni через прокси)</option>
@@ -174,7 +174,7 @@
<fieldset class="ai-model">
<input type="hidden" name="m_id" value="">
<div class="ai-model-head"><label class="ai-model-name">Название в чате<input type="text" name="m_name" value="" placeholder="например, Claude"></label>
<label class="ai-model-short">Коротко<input type="text" name="m_short" value="" maxlength="7" placeholder="до 7" title="Название на кнопке модели в чате, до 7 символов"></label>
<label class="ai-model-short">Коротко<input type="text" name="m_short" value="" maxlength="9" placeholder="до 9" title="Название на кнопке модели в чате, до 9 символов"></label>
<button type="button" class="btn ghost small close ai-model-del" title="Удалить модель" aria-label="Удалить модель">Удалить</button></div>
<label>Тип API<select name="m_type">
<option value="gradio">Gradio (Qwen Omni через прокси)</option>