diff --git a/bot.go b/bot.go index 60d8f22..d1f4eaa 100644 --- a/bot.go +++ b/bot.go @@ -268,9 +268,7 @@ func warmUpModel() { // Continue with warmup attempt anyway } if loaded { - if err := notifyUser("model already loaded", "Model "+chatBody.Model+" is already loaded."); err != nil { - logger.Debug("failed to notify user", "error", err) - } + showToast("model already loaded", "Model "+chatBody.Model+" is already loaded.") return } go func() { @@ -483,9 +481,7 @@ func monitorModelLoad(modelID string) { continue } if loaded { - if err := notifyUser("model loaded", "Model "+modelID+" is now loaded and ready."); err != nil { - logger.Debug("failed to notify user", "error", err) - } + showToast("model loaded", "Model "+modelID+" is now loaded and ready.") refreshChatDisplay() return } @@ -572,9 +568,7 @@ func sendMsgToLLM(body io.Reader) { req, err := http.NewRequest("POST", cfg.CurrentAPI, body) if err != nil { logger.Error("newreq error", "error", err) - if err := notifyUser("error", "apicall failed:"+err.Error()); err != nil { - logger.Error("failed to notify", "error", err) - } + showToast("error", "apicall failed:"+err.Error()) streamDone <- true return } @@ -586,9 +580,7 @@ func sendMsgToLLM(body io.Reader) { resp, err := httpClient.Do(req) if err != nil { logger.Error("llamacpp api", "error", err) - if err := notifyUser("error", "apicall failed:"+err.Error()); err != nil { - logger.Error("failed to notify", "error", err) - } + showToast("error", "apicall failed:"+err.Error()) streamDone <- true return } @@ -599,9 +591,7 @@ func sendMsgToLLM(body io.Reader) { if err != nil { logger.Error("failed to read error response body", "error", err, "status_code", resp.StatusCode) detailedError := fmt.Sprintf("HTTP Status: %d, Failed to read response body: %v", resp.StatusCode, err) - if err := notifyUser("API Error", detailedError); err != nil { - logger.Error("failed to notify", "error", err) - } + showToast("API Error", detailedError) resp.Body.Close() streamDone <- true return @@ -609,9 +599,7 @@ func sendMsgToLLM(body io.Reader) { // Parse the error response for detailed information detailedError := extractDetailedErrorFromBytes(bodyBytes, resp.StatusCode) logger.Error("API returned error status", "status_code", resp.StatusCode, "detailed_error", detailedError) - if err := notifyUser("API Error", detailedError); err != nil { - logger.Error("failed to notify", "error", err) - } + showToast("API Error", detailedError) resp.Body.Close() streamDone <- true return @@ -648,16 +636,12 @@ func sendMsgToLLM(body io.Reader) { detailedError := fmt.Sprintf("Streaming connection closed unexpectedly (Status: %d). This may indicate an API error. Check your API provider and model settings.", resp.StatusCode) logger.Error("error reading response body", "error", err, "detailed_error", detailedError, "status_code", resp.StatusCode, "user_role", cfg.UserRole, "parser", chunkParser, "link", cfg.CurrentAPI) - if err := notifyUser("API Error", detailedError); err != nil { - logger.Error("failed to notify", "error", err) - } + showToast("API Error", detailedError) } else { logger.Error("error reading response body", "error", err, "line", string(line), "user_role", cfg.UserRole, "parser", chunkParser, "link", cfg.CurrentAPI) // if err.Error() != "EOF" { - if err := notifyUser("API error", err.Error()); err != nil { - logger.Error("failed to notify", "error", err) - } + showToast("API error", err.Error()) } streamDone <- true break @@ -684,9 +668,7 @@ func sendMsgToLLM(body io.Reader) { if err != nil { logger.Error("error parsing response body", "error", err, "line", string(line), "url", cfg.CurrentAPI) - if err := notifyUser("LLM Response Error", "Failed to parse LLM response: "+err.Error()); err != nil { - logger.Error("failed to notify user", "error", err) - } + showToast("LLM Response Error", "Failed to parse LLM response: "+err.Error()) streamDone <- true break } @@ -1456,15 +1438,15 @@ func refreshLocalModelsIfEmpty() { func summarizeAndStartNewChat() { if len(chatBody.Messages) == 0 { - _ = notifyUser("info", "No chat history to summarize") + showToast("info", "No chat history to summarize") return } - _ = notifyUser("info", "Summarizing chat history...") + showToast("info", "Summarizing chat history...") // Call the summarize_chat tool via agent summaryBytes := callToolWithAgent("summarize_chat", map[string]string{}) summary := string(summaryBytes) if summary == "" { - _ = notifyUser("error", "Failed to generate summary") + showToast("error", "Failed to generate summary") return } // Start a new chat @@ -1483,7 +1465,7 @@ func summarizeAndStartNewChat() { if err := updateStorageChat(activeChatName, chatBody.Messages); err != nil { logger.Warn("failed to update storage after injecting summary", "error", err) } - _ = notifyUser("info", "Chat summarized and new chat started with summary as tool response") + showToast("info", "Chat summarized and new chat started with summary as tool response") } func init() { diff --git a/helpfuncs.go b/helpfuncs.go index 3132c9d..038e275 100644 --- a/helpfuncs.go +++ b/helpfuncs.go @@ -491,10 +491,7 @@ func listChatRoles() []string { func deepseekModelValidator() error { if cfg.CurrentAPI == cfg.DeepSeekChatAPI || cfg.CurrentAPI == cfg.DeepSeekCompletionAPI { if chatBody.Model != "deepseek-chat" && chatBody.Model != "deepseek-reasoner" { - if err := notifyUser("bad request", "wrong deepseek model name"); err != nil { - logger.Warn("failed ot notify user", "error", err) - return err - } + showToast("bad request", "wrong deepseek model name") return nil } } @@ -694,9 +691,7 @@ func performSearch(term string) { searchResults = nil searchResultLengths = nil notification := "Pattern not found: " + term - if err := notifyUser("search", notification); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("search", notification) return } // Store the formatted text positions and lengths for accurate highlighting @@ -729,9 +724,7 @@ func highlightCurrentMatch() { textView.Highlight(currentRegion).ScrollToHighlight() // Send notification about which match we're at notification := fmt.Sprintf("Match %d of %d", searchIndex+1, len(searchResults)) - if err := notifyUser("search", notification); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("search", notification) } // showSearchBar shows the search input field as an overlay @@ -821,9 +814,7 @@ func addRegionTags(text string, positions []int, lengths []int, currentIdx int, // searchNext finds the next occurrence of the search term func searchNext() { if len(searchResults) == 0 { - if err := notifyUser("search", "No search results to navigate"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("search", "No search results to navigate") return } searchIndex = (searchIndex + 1) % len(searchResults) @@ -833,9 +824,7 @@ func searchNext() { // searchPrev finds the previous occurrence of the search term func searchPrev() { if len(searchResults) == 0 { - if err := notifyUser("search", "No search results to navigate"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("search", "No search results to navigate") return } if searchIndex == 0 { diff --git a/popups.go b/popups.go index eae50a3..38f42cd 100644 --- a/popups.go +++ b/popups.go @@ -40,9 +40,7 @@ func showModelSelectionPopup() { default: message = "No llama.cpp models loaded. Ensure llama.cpp server is running with models." } - if err := notifyUser("Empty list", message); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("Empty list", message) return } // Create a list primitive @@ -119,9 +117,7 @@ func showAPILinkSelectionPopup() { if len(apiLinks) == 0 { logger.Warn("no API links available for selection") message := "No API links available. Please configure API links in your config file." - if err := notifyUser("Empty list", message); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("Empty list", message) return } // Create a list primitive @@ -206,9 +202,7 @@ func showUserRoleSelectionPopup() { if len(roles) == 0 { logger.Warn("no roles available for selection") message := "No roles available for selection." - if err := notifyUser("Empty list", message); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("Empty list", message) return } // Create a list primitive @@ -285,9 +279,7 @@ func showBotRoleSelectionPopup() { if len(roles) == 0 { logger.Warn("no roles available for selection") message := "No roles available for selection." - if err := notifyUser("Empty list", message); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("Empty list", message) return } // Create a list primitive @@ -512,9 +504,7 @@ func showColorschemeSelectionPopup() { if len(schemeNames) == 0 { logger.Warn("no colorschemes available for selection") message := "No colorschemes available." - if err := notifyUser("Empty list", message); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("Empty list", message) return } // Create a list primitive diff --git a/props_table.go b/props_table.go index f8432cd..ec66812 100644 --- a/props_table.go +++ b/props_table.go @@ -259,9 +259,7 @@ func makePropsTable(props map[string]float32) *tview.Table { // Handle nil options if data.Options == nil { logger.Error("options list is nil for", "label", label) - if err := notifyUser("Configuration error", "Options list is nil for "+label); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("Configuration error", "Options list is nil for "+label) return } @@ -279,9 +277,7 @@ func makePropsTable(props map[string]float32) *tview.Table { message = "No llama.cpp models loaded. Ensure llama.cpp server is running with models." } } - if err := notifyUser("Empty list", message); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("Empty list", message) return } // Create a list primitive diff --git a/session.go b/session.go index 42d5001..980d998 100644 --- a/session.go +++ b/session.go @@ -168,19 +168,3 @@ func copyToClipboard(text string) error { cmd.Stdin = strings.NewReader(text) return cmd.Run() } - -func notifyUser(topic, message string) error { - // Sanitize message to remove control characters that notify-send doesn't handle - sanitized := strings.Map(func(r rune) rune { - if r < 32 && r != '\t' { - return -1 - } - return r - }, message) - // Truncate if too long - if len(sanitized) > 200 { - sanitized = sanitized[:197] + "..." - } - cmd := exec.Command("notify-send", topic, sanitized) - return cmd.Run() -} diff --git a/tables.go b/tables.go index 0cec551..baa1c36 100644 --- a/tables.go +++ b/tables.go @@ -147,9 +147,7 @@ func makeChatTable(chatMap map[string]models.Chat) *tview.Table { if err := store.RemoveChat(sc.ID); err != nil { logger.Error("failed to remove chat from db", "chat_id", sc.ID, "chat_name", sc.Name) } - if err := notifyUser("chat deleted", selectedChat+" was deleted"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("chat deleted", selectedChat+" was deleted") // load last chat chatBody.Messages = loadOldChatOrGetNew() textView.SetText(chatToText(chatBody.Messages, cfg.ShowSys)) @@ -162,9 +160,7 @@ func makeChatTable(chatMap map[string]models.Chat) *tview.Table { cc := GetCardByRole(agentName) if cc == nil { logger.Warn("no such card", "agent", agentName) - if err := notifyUser("error", "no such card: "+agentName); err != nil { - logger.Warn("failed ot notify", "error", err) - } + showToast("error", "no such card: "+agentName) return } cc.SysPrompt = chatBody.Messages[0].Content @@ -186,9 +182,7 @@ func makeChatTable(chatMap map[string]models.Chat) *tview.Table { cc := GetCardByRole(agentName) if cc == nil { logger.Warn("no such card", "agent", agentName) - if err := notifyUser("error", "no such card: "+agentName); err != nil { - logger.Warn("failed to notify", "error", err) - } + showToast("error", "no such card: "+agentName) return } newCard, err := pngmeta.ReadCard(cc.FilePath, cfg.UserRole) @@ -197,9 +191,7 @@ func makeChatTable(chatMap map[string]models.Chat) *tview.Table { newCard, err = pngmeta.ReadCardJson(cc.FilePath) if err != nil { logger.Error("failed to reload charcard", "path", cc.FilePath, "error", err) - if err := notifyUser("error", "failed to reload card: "+cc.FilePath); err != nil { - logger.Warn("failed to notify", "error", err) - } + showToast("error", "failed to reload card: "+cc.FilePath) return } } @@ -448,13 +440,13 @@ func makeRAGTable(fileList []string, loadedFiles []string) *tview.Flex { go func() { if err := ragger.LoadRAG(fpath); err != nil { logger.Error("failed to embed file", "chat", fpath, "error", err) - _ = notifyUser("RAG", "failed to embed file; error: "+err.Error()) + showToast("RAG", "failed to embed file; error: "+err.Error()) app.QueueUpdate(func() { pages.RemovePage(RAGPage) }) return } - _ = notifyUser("RAG", "file loaded successfully") + showToast("RAG", "file loaded successfully") app.QueueUpdate(func() { pages.RemovePage(RAGPage) }) @@ -465,13 +457,13 @@ func makeRAGTable(fileList []string, loadedFiles []string) *tview.Flex { go func() { if err := ragger.RemoveFile(f.name); err != nil { logger.Error("failed to unload file from RAG", "filename", f.name, "error", err) - _ = notifyUser("RAG", "failed to unload file; error: "+err.Error()) + showToast("RAG", "failed to unload file; error: "+err.Error()) app.QueueUpdate(func() { pages.RemovePage(RAGPage) }) return } - _ = notifyUser("RAG", "file unloaded successfully") + showToast("RAG", "file unloaded successfully") app.QueueUpdate(func() { pages.RemovePage(RAGPage) }) @@ -483,9 +475,7 @@ func makeRAGTable(fileList []string, loadedFiles []string) *tview.Flex { logger.Error("failed to delete file", "filename", fpath, "error", err) return } - if err := notifyUser("chat deleted", fpath+" was deleted"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("chat deleted", fpath+" was deleted") return default: pages.RemovePage(RAGPage) @@ -594,9 +584,7 @@ func makeAgentTable(agentList []string) *tview.Table { if err := store.RemoveChat(sc.ID); err != nil { logger.Error("failed to remove chat from db", "chat_id", sc.ID, "chat_name", sc.Name) } - if err := notifyUser("chat deleted", selected+" was deleted"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("chat deleted", selected+" was deleted") pages.RemovePage(agentPage) return default: @@ -667,13 +655,9 @@ func makeCodeBlockTable(codeBlocks []string) *tview.Table { switch tc.Text { case "copy": if err := copyToClipboard(selected); err != nil { - if err := notifyUser("error", err.Error()); err != nil { - logger.Error("failed to send notification", "error", err) - } - } - if err := notifyUser("copied", selected); err != nil { - logger.Error("failed to send notification", "error", err) + showToast("error", err.Error()) } + showToast("copied", selected) pages.RemovePage(codeBlockPage) app.SetFocus(textArea) return @@ -766,9 +750,7 @@ func makeImportChatTable(filenames []string) *tview.Table { if err := store.RemoveChat(sc.ID); err != nil { logger.Error("failed to remove chat from db", "chat_id", sc.ID, "chat_name", sc.Name) } - if err := notifyUser("chat deleted", selected+" was deleted"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("chat deleted", selected+" was deleted") pages.RemovePage(historyPage) return default: diff --git a/tools.go b/tools.go index 84ef23d..8cca673 100644 --- a/tools.go +++ b/tools.go @@ -268,7 +268,7 @@ func updateToolCapabilities() { } else { logger.Info("model does not have vision support", "model", cfg.CurrentModel, "api", cfg.CurrentAPI) if windowToolsAvailable && !prevHasVision && !modelHasVision { - _ = notifyUser("window tools", "Window capture-and-view unavailable: model lacks vision support") + showToast("window tools", "Window capture-and-view unavailable: model lacks vision support") } } registerWindowTools() diff --git a/tui.go b/tui.go index 67f2775..b23c3ff 100644 --- a/tui.go +++ b/tui.go @@ -140,7 +140,20 @@ func setShellMode(enabled bool) { // showToast displays a temporary message in the top‑right corner. // It auto‑hides after 3 seconds and disappears when clicked. func showToast(title, message string) { - // Create a small, bordered text view for the notification. + sanitize := func(s string, maxLen int) string { + sanitized := strings.Map(func(r rune) rune { + if r < 32 && r != '\t' { + return -1 + } + return r + }, s) + if len(sanitized) > maxLen { + sanitized = sanitized[:maxLen-3] + "..." + } + return sanitized + } + title = sanitize(title, 50) + message = sanitize(message, 197) notification := tview.NewTextView(). SetTextAlign(tview.AlignCenter). SetDynamicColors(true). @@ -363,9 +376,7 @@ func init() { defer colorText() editedMsg := editArea.GetText() if editedMsg == "" { - if err := notifyUser("edit", "no edit provided"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("edit", "no edit provided") pages.RemovePage(editMsgPage) return nil } @@ -395,9 +406,7 @@ func init() { case tcell.KeyEnter: newRole := roleEditWindow.GetText() if newRole == "" { - if err := notifyUser("edit", "no role provided"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("edit", "no role provided") pages.RemovePage(roleEditPage) return } @@ -424,9 +433,7 @@ func init() { siInt, err := strconv.Atoi(si) if err != nil { logger.Error("failed to convert provided index", "error", err, "si", si) - if err := notifyUser("cancel", "no index provided, copying user input"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("cancel", "no index provided, copying user input") if err := copyToClipboard(textArea.GetText()); err != nil { logger.Error("failed to copy to clipboard", "error", err) } @@ -437,9 +444,7 @@ func init() { if len(chatBody.Messages)-1 < selectedIndex || selectedIndex < 0 { msg := "chosen index is out of bounds, will copy user input" logger.Warn(msg, "index", selectedIndex) - if err := notifyUser("error", msg); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("error", msg) if err := copyToClipboard(textArea.GetText()); err != nil { logger.Error("failed to copy to clipboard", "error", err) } @@ -465,9 +470,7 @@ func init() { } previewLen := min(30, len(msgText)) notification := fmt.Sprintf("msg '%s' was copied to the clipboard", msgText[:previewLen]) - if err := notifyUser("copied", notification); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("copied", notification) hideIndexBar() // Hide overlay after copying } return nil @@ -499,9 +502,7 @@ func init() { logger.Error("failed to upsert chat", "error", err, "chat", currentChat) } notification := fmt.Sprintf("renamed chat to '%s'", activeChatName) - if err := notifyUser("renamed", notification); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("renamed", notification) } return event }) @@ -612,9 +613,6 @@ func init() { status = "enabled" } showToast("autoscroll", "Auto-scrolling "+status) - if err := notifyUser("autoscroll", "Auto-scrolling "+status); err != nil { - logger.Error("failed to send notification", "error", err) - } updateStatusLine() } // Handle Alt+7 to toggle injectRole @@ -631,9 +629,7 @@ func init() { if thinkingCollapsed { status = "collapsed" } - if err := notifyUser("thinking", "Thinking blocks "+status); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("thinking", "Thinking blocks "+status) return nil } // Handle Ctrl+T to toggle tool call/response visibility @@ -645,9 +641,7 @@ func init() { if toolCollapsed { status = "collapsed" } - if err := notifyUser("tools", "Tool calls/responses "+status); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("tools", "Tool calls/responses "+status) return nil } if event.Key() == tcell.KeyRune && event.Rune() == 'i' && event.Modifiers()&tcell.ModAlt != 0 { @@ -667,9 +661,7 @@ func init() { // Check if there are no chats for this agent if len(chatList) == 0 { notification := "no chats found for agent: " + cfg.AssistantRole - if err := notifyUser("info", notification); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("info", notification) return nil } chatMap := make(map[string]models.Chat) @@ -687,9 +679,7 @@ func init() { if event.Key() == tcell.KeyF2 && !botRespMode { // regen last msg if len(chatBody.Messages) == 0 { - if err := notifyUser("info", "no messages to regenerate"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("info", "no messages to regenerate") return nil } chatBody.Messages = chatBody.Messages[:len(chatBody.Messages)-1] @@ -715,9 +705,7 @@ func init() { return nil } if len(chatBody.Messages) == 0 { - if err := notifyUser("info", "no messages to delete"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("info", "no messages to delete") return nil } chatBody.Messages = chatBody.Messages[:len(chatBody.Messages)-1] @@ -776,9 +764,7 @@ func init() { } previewLen := min(30, len(msgText)) notification := fmt.Sprintf("msg '%s' was copied to the clipboard", msgText[:previewLen]) - if err := notifyUser("copied", notification); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("copied", notification) return nil } if event.Key() == tcell.KeyF8 { @@ -792,9 +778,7 @@ func init() { text := textView.GetText(false) cb := codeBlockRE.FindAllString(text, -1) if len(cb) == 0 { - if err := notifyUser("notify", "no code blocks in chat"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("notify", "no code blocks in chat") return nil } table := makeCodeBlockTable(cb) @@ -809,9 +793,7 @@ func init() { // read files in chat_exports filelist, err := os.ReadDir(exportDir) if err != nil { - if err := notifyUser("failed to load exports", err.Error()); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("failed to load exports", err.Error()) return nil } fli := []string{} @@ -841,9 +823,7 @@ func init() { logger.Error("failed to export chat;", "error", err, "chat_name", activeChatName) return nil } - if err := notifyUser("exported chat", "chat: "+activeChatName+" was exported"); err != nil { - logger.Error("failed to send notification", "error", err) - } + showToast("exported chat", "chat: "+activeChatName+" was exported") return nil } if event.Key() == tcell.KeyCtrlP { @@ -882,9 +862,7 @@ func init() { labels, err := initSysCards() if err != nil { logger.Error("failed to read sys dir", "error", err) - if err := notifyUser("error", "failed to read: "+cfg.SysDir); err != nil { - logger.Debug("failed to notify user", "error", err) - } + showToast("error", "failed to read: "+cfg.SysDir) return nil } at := makeAgentTable(labels) @@ -941,9 +919,7 @@ func init() { if err != nil { msg := "failed to inference user speech; error:" + err.Error() logger.Error(msg) - if err := notifyUser("stt error", msg); err != nil { - logger.Error("failed to notify user", "error", err) - } + showToast("stt error", msg) return nil } if userSpeech != "" { @@ -1023,26 +999,20 @@ func init() { // Create the RAG directory if it doesn't exist if mkdirErr := os.MkdirAll(cfg.RAGDir, 0755); mkdirErr != nil { logger.Error("failed to create RAG directory", "dir", cfg.RAGDir, "error", mkdirErr) - if notifyerr := notifyUser("failed to create RAG directory", mkdirErr.Error()); notifyerr != nil { - logger.Error("failed to send notification", "error", notifyerr) - } + showToast("failed to create RAG directory", mkdirErr.Error()) return nil } // Now try to read the directory again after creating it files, err = os.ReadDir(cfg.RAGDir) if err != nil { logger.Error("failed to read dir after creating it", "dir", cfg.RAGDir, "error", err) - if notifyerr := notifyUser("failed to read RAG directory", err.Error()); notifyerr != nil { - logger.Error("failed to send notification", "error", notifyerr) - } + showToast("failed to read RAG directory", err.Error()) return nil } } else { // Other error (permissions, etc.) logger.Error("failed to read dir", "dir", cfg.RAGDir, "error", err) - if notifyerr := notifyUser("failed to open RAG files dir", err.Error()); notifyerr != nil { - logger.Error("failed to send notification", "error", notifyerr) - } + showToast("failed to open RAG files dir", err.Error()) return nil } } @@ -1072,9 +1042,7 @@ func init() { if event.Key() == tcell.KeyRune && event.Modifiers() == tcell.ModAlt && event.Rune() == '9' { // Warm up (load) the currently selected model go warmUpModel() - if err := notifyUser("model warmup", "loading model: "+chatBody.Model); err != nil { - logger.Debug("failed to notify user", "error", err) - } + showToast("model warmup", "loading model: "+chatBody.Model) return nil } // cannot send msg in editMode or botRespMode