Chore: one init for clear call order
This commit is contained in:
52
bot.go
52
bot.go
@@ -1548,55 +1548,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
// Initialize scrollToEndEnabled based on config
|
// Initialize scrollToEndEnabled based on config
|
||||||
scrollToEndEnabled = cfg.AutoScrollEnabled
|
scrollToEndEnabled = cfg.AutoScrollEnabled
|
||||||
go updateModelLists()
|
|
||||||
go chatWatcher(ctx)
|
go chatWatcher(ctx)
|
||||||
}
|
initTUI()
|
||||||
|
initTools()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|||||||
49
helpfuncs.go
49
helpfuncs.go
@@ -964,3 +964,52 @@ func extractDisplayPath(p, bp string) string {
|
|||||||
}
|
}
|
||||||
return p
|
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
|
||||||
|
}
|
||||||
|
|||||||
55
tools.go
55
tools.go
@@ -207,7 +207,7 @@ var (
|
|||||||
modelHasVision bool
|
modelHasVision bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func initTools() {
|
||||||
sysMap[basicCard.ID] = basicCard
|
sysMap[basicCard.ID] = basicCard
|
||||||
roleToID["assistant"] = basicCard.ID
|
roleToID["assistant"] = basicCard.ID
|
||||||
sa, err := searcher.NewWebSurfer(searcher.SearcherTypeScraper, "")
|
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
3
tui.go
@@ -224,7 +224,7 @@ func showToast(title, message string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func initTUI() {
|
||||||
// Start background goroutine to update model color cache
|
// Start background goroutine to update model color cache
|
||||||
startModelColorUpdater()
|
startModelColorUpdater()
|
||||||
tview.Styles = colorschemes["default"]
|
tview.Styles = colorschemes["default"]
|
||||||
@@ -1173,4 +1173,5 @@ func init() {
|
|||||||
}
|
}
|
||||||
return event
|
return event
|
||||||
})
|
})
|
||||||
|
go updateModelLists()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user