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:
1 parent
6a17f40042
commit
6c1da79b4a
5 files changed
+10
-10
No files matched your search
@@ -46,7 +46,7 @@
|
||||
показать или записать файл - всё с правами пользователя. Плашка «Агент» - делает шаги сам,
|
||||
спрашивая перед каждой командой и записью; «Думать» - сначала рассуждает (свёрнуто над
|
||||
ответом). Модели задаёт администратор в «Настройки › ИИ-ассистент»: их может быть несколько, у каждой своё
|
||||
название в чате (и короткое, до 7 символов, - для кнопки выбора), тип - Gradio (по умолчанию - прокси к Qwen Omni), OpenAI-совместимый API или Anthropic,
|
||||
название в чате (и короткое, до 9 символов, - для кнопки выбора), тип - Gradio (по умолчанию - прокси к Qwen Omni), OpenAI-совместимый API или Anthropic,
|
||||
адрес, модель и ключ (хранится на сервере, в браузер не уходит). Если моделей несколько, в чате рядом с
|
||||
плашками появляется выбор, первая - по умолчанию; выбор запоминается за пользователем. В «Аккаунт › Вид»
|
||||
можно показывать выбор всегда.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user