Chore: one init for clear call order

This commit is contained in:
Grail Finder
2026-03-07 19:11:13 +03:00
parent bf655a1087
commit 4f0bce50c5
4 changed files with 54 additions and 105 deletions

52
bot.go
View File

@@ -1548,55 +1548,7 @@ func init() {
}
// Initialize scrollToEndEnabled based on config
scrollToEndEnabled = cfg.AutoScrollEnabled
go updateModelLists()
go chatWatcher(ctx)
}
func getValidKnowToRecipient(msg *models.RoleMsg) (string, bool) {
if cfg == nil || !cfg.CharSpecificContextEnabled {
return "", false
}
// case where all roles are in the tag => public message
cr := listChatRoles()
slices.Sort(cr)
slices.Sort(msg.KnownTo)
if slices.Equal(cr, msg.KnownTo) {
logger.Info("got msg with tag mentioning every role")
return "", false
}
// Check each character in the KnownTo list
for _, recipient := range msg.KnownTo {
if recipient == msg.Role || recipient == cfg.ToolRole {
// weird cases, skip
continue
}
// Skip if this is the user character (user handles their own turn)
// If user is in KnownTo, stop processing - it's the user's turn
if recipient == cfg.UserRole || recipient == cfg.WriteNextMsgAs {
return "", false
}
return recipient, true
}
return "", false
}
// triggerPrivateMessageResponses checks if a message was sent privately to specific characters
// and triggers those non-user characters to respond
func triggerPrivateMessageResponses(msg *models.RoleMsg) {
recipient, ok := getValidKnowToRecipient(msg)
if !ok || recipient == "" {
return
}
// Trigger the recipient character to respond
triggerMsg := recipient + ":\n"
// Send empty message so LLM continues naturally from the conversation
crr := &models.ChatRoundReq{
UserMsg: triggerMsg,
Role: recipient,
Resume: true,
}
fmt.Fprintf(textView, "\n[-:-:b](%d) ", len(chatBody.Messages))
fmt.Fprint(textView, roleToIcon(recipient))
fmt.Fprint(textView, "[-:-:-]\n")
chatRoundChan <- crr
initTUI()
initTools()
}

View File

@@ -964,3 +964,52 @@ func extractDisplayPath(p, bp string) string {
}
return p
}
func getValidKnowToRecipient(msg *models.RoleMsg) (string, bool) {
if cfg == nil || !cfg.CharSpecificContextEnabled {
return "", false
}
// case where all roles are in the tag => public message
cr := listChatRoles()
slices.Sort(cr)
slices.Sort(msg.KnownTo)
if slices.Equal(cr, msg.KnownTo) {
logger.Info("got msg with tag mentioning every role")
return "", false
}
// Check each character in the KnownTo list
for _, recipient := range msg.KnownTo {
if recipient == msg.Role || recipient == cfg.ToolRole {
// weird cases, skip
continue
}
// Skip if this is the user character (user handles their own turn)
// If user is in KnownTo, stop processing - it's the user's turn
if recipient == cfg.UserRole || recipient == cfg.WriteNextMsgAs {
return "", false
}
return recipient, true
}
return "", false
}
// triggerPrivateMessageResponses checks if a message was sent privately to specific characters
// and triggers those non-user characters to respond
func triggerPrivateMessageResponses(msg *models.RoleMsg) {
recipient, ok := getValidKnowToRecipient(msg)
if !ok || recipient == "" {
return
}
// Trigger the recipient character to respond
triggerMsg := recipient + ":\n"
// Send empty message so LLM continues naturally from the conversation
crr := &models.ChatRoundReq{
UserMsg: triggerMsg,
Role: recipient,
Resume: true,
}
fmt.Fprintf(textView, "\n[-:-:b](%d) ", len(chatBody.Messages))
fmt.Fprint(textView, roleToIcon(recipient))
fmt.Fprint(textView, "[-:-:-]\n")
chatRoundChan <- crr
}

View File

@@ -207,7 +207,7 @@ var (
modelHasVision bool
)
func init() {
func initTools() {
sysMap[basicCard.ID] = basicCard
roleToID["assistant"] = basicCard.ID
sa, err := searcher.NewWebSurfer(searcher.SearcherTypeScraper, "")
@@ -2273,56 +2273,3 @@ var baseTools = []models.Tool{
},
},
}
func init() {
if windowToolsAvailable {
baseTools = append(baseTools,
models.Tool{
Type: "function",
Function: models.ToolFunc{
Name: "list_windows",
Description: "List all visible windows with their IDs and names. Returns a map of window ID to window name.",
Parameters: models.ToolFuncParams{
Type: "object",
Required: []string{},
Properties: map[string]models.ToolArgProps{},
},
},
},
models.Tool{
Type: "function",
Function: models.ToolFunc{
Name: "capture_window",
Description: "Capture a screenshot of a specific window and save it to /tmp. Requires window parameter (window ID or name substring).",
Parameters: models.ToolFuncParams{
Type: "object",
Required: []string{"window"},
Properties: map[string]models.ToolArgProps{
"window": models.ToolArgProps{
Type: "string",
Description: "window ID or window name (partial match)",
},
},
},
},
},
models.Tool{
Type: "function",
Function: models.ToolFunc{
Name: "capture_window_and_view",
Description: "Capture a screenshot of a specific window, save it to /tmp, and return the image for viewing. Requires window parameter (window ID or name substring).",
Parameters: models.ToolFuncParams{
Type: "object",
Required: []string{"window"},
Properties: map[string]models.ToolArgProps{
"window": models.ToolArgProps{
Type: "string",
Description: "window ID or window name (partial match)",
},
},
},
},
},
)
}
}

3
tui.go
View File

@@ -224,7 +224,7 @@ func showToast(title, message string) {
})
}
func init() {
func initTUI() {
// Start background goroutine to update model color cache
startModelColorUpdater()
tview.Styles = colorschemes["default"]
@@ -1173,4 +1173,5 @@ func init() {
}
return event
})
go updateModelLists()
}