Chore: linter complaints
This commit is contained in:
@@ -77,17 +77,18 @@ func (ag *AgentClient) buildRequest(sysprompt, msg string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
prompt := strings.TrimSpace(sb.String())
|
prompt := strings.TrimSpace(sb.String())
|
||||||
|
|
||||||
if isDeepSeek {
|
switch {
|
||||||
|
case isDeepSeek:
|
||||||
// DeepSeek completion
|
// DeepSeek completion
|
||||||
req := models.NewDSCompletionReq(prompt, model, defaultProps["temperature"], []string{})
|
req := models.NewDSCompletionReq(prompt, model, defaultProps["temperature"], []string{})
|
||||||
req.Stream = false // Agents don't need streaming
|
req.Stream = false // Agents don't need streaming
|
||||||
return json.Marshal(req)
|
return json.Marshal(req)
|
||||||
} else if isOpenRouter {
|
case isOpenRouter:
|
||||||
// OpenRouter completion
|
// OpenRouter completion
|
||||||
req := models.NewOpenRouterCompletionReq(model, prompt, defaultProps, []string{})
|
req := models.NewOpenRouterCompletionReq(model, prompt, defaultProps, []string{})
|
||||||
req.Stream = false // Agents don't need streaming
|
req.Stream = false // Agents don't need streaming
|
||||||
return json.Marshal(req)
|
return json.Marshal(req)
|
||||||
} else {
|
default:
|
||||||
// Assume llama.cpp completion
|
// Assume llama.cpp completion
|
||||||
req := models.NewLCPReq(prompt, model, nil, defaultProps, []string{})
|
req := models.NewLCPReq(prompt, model, nil, defaultProps, []string{})
|
||||||
req.Stream = false // Agents don't need streaming
|
req.Stream = false // Agents don't need streaming
|
||||||
@@ -103,15 +104,16 @@ func (ag *AgentClient) buildRequest(sysprompt, msg string) ([]byte, error) {
|
|||||||
Messages: messages,
|
Messages: messages,
|
||||||
}
|
}
|
||||||
|
|
||||||
if isDeepSeek {
|
switch {
|
||||||
|
case isDeepSeek:
|
||||||
// DeepSeek chat
|
// DeepSeek chat
|
||||||
req := models.NewDSChatReq(*chatBody)
|
req := models.NewDSChatReq(*chatBody)
|
||||||
return json.Marshal(req)
|
return json.Marshal(req)
|
||||||
} else if isOpenRouter {
|
case isOpenRouter:
|
||||||
// OpenRouter chat
|
// OpenRouter chat
|
||||||
req := models.NewOpenRouterChatReq(*chatBody, defaultProps)
|
req := models.NewOpenRouterChatReq(*chatBody, defaultProps)
|
||||||
return json.Marshal(req)
|
return json.Marshal(req)
|
||||||
} else {
|
default:
|
||||||
// Assume llama.cpp chat (OpenAI format)
|
// Assume llama.cpp chat (OpenAI format)
|
||||||
req := models.OpenAIReq{
|
req := models.OpenAIReq{
|
||||||
ChatBody: chatBody,
|
ChatBody: chatBody,
|
||||||
|
|||||||
21
bot.go
21
bot.go
@@ -113,7 +113,7 @@ func parseKnownToTag(content string) []string {
|
|||||||
// processMessageTag processes a message for known_to tag and sets KnownTo field.
|
// processMessageTag processes a message for known_to tag and sets KnownTo field.
|
||||||
// It also ensures the sender's role is included in KnownTo.
|
// It also ensures the sender's role is included in KnownTo.
|
||||||
// If KnownTo already set (e.g., from DB), preserves it unless new tag found.
|
// If KnownTo already set (e.g., from DB), preserves it unless new tag found.
|
||||||
func processMessageTag(msg models.RoleMsg) models.RoleMsg {
|
func processMessageTag(msg *models.RoleMsg) *models.RoleMsg {
|
||||||
if cfg == nil || !cfg.CharSpecificContextEnabled {
|
if cfg == nil || !cfg.CharSpecificContextEnabled {
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,8 @@ func warmUpModel() {
|
|||||||
go func() {
|
go func() {
|
||||||
var data []byte
|
var data []byte
|
||||||
var err error
|
var err error
|
||||||
if strings.HasSuffix(cfg.CurrentAPI, "/completion") {
|
switch {
|
||||||
|
case strings.HasSuffix(cfg.CurrentAPI, "/completion"):
|
||||||
// Old completion endpoint
|
// Old completion endpoint
|
||||||
req := models.NewLCPReq(".", chatBody.Model, nil, map[string]float32{
|
req := models.NewLCPReq(".", chatBody.Model, nil, map[string]float32{
|
||||||
"temperature": 0.8,
|
"temperature": 0.8,
|
||||||
@@ -307,7 +308,7 @@ func warmUpModel() {
|
|||||||
}, []string{})
|
}, []string{})
|
||||||
req.Stream = false
|
req.Stream = false
|
||||||
data, err = json.Marshal(req)
|
data, err = json.Marshal(req)
|
||||||
} else if strings.Contains(cfg.CurrentAPI, "/v1/chat/completions") {
|
case strings.Contains(cfg.CurrentAPI, "/v1/chat/completions"):
|
||||||
// OpenAI-compatible chat endpoint
|
// OpenAI-compatible chat endpoint
|
||||||
req := models.OpenAIReq{
|
req := models.OpenAIReq{
|
||||||
ChatBody: &models.ChatBody{
|
ChatBody: &models.ChatBody{
|
||||||
@@ -320,7 +321,7 @@ func warmUpModel() {
|
|||||||
Tools: nil,
|
Tools: nil,
|
||||||
}
|
}
|
||||||
data, err = json.Marshal(req)
|
data, err = json.Marshal(req)
|
||||||
} else {
|
default:
|
||||||
// Unknown local endpoint, skip
|
// Unknown local endpoint, skip
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -861,14 +862,14 @@ out:
|
|||||||
// lastM.Content = lastM.Content + respText.String()
|
// lastM.Content = lastM.Content + respText.String()
|
||||||
// Process the updated message to check for known_to tags in resumed response
|
// Process the updated message to check for known_to tags in resumed response
|
||||||
updatedMsg := chatBody.Messages[len(chatBody.Messages)-1]
|
updatedMsg := chatBody.Messages[len(chatBody.Messages)-1]
|
||||||
processedMsg := processMessageTag(updatedMsg)
|
processedMsg := processMessageTag(&updatedMsg)
|
||||||
chatBody.Messages[len(chatBody.Messages)-1] = processedMsg
|
chatBody.Messages[len(chatBody.Messages)-1] = *processedMsg
|
||||||
} else {
|
} else {
|
||||||
newMsg := models.RoleMsg{
|
newMsg := models.RoleMsg{
|
||||||
Role: botPersona, Content: respText.String(),
|
Role: botPersona, Content: respText.String(),
|
||||||
}
|
}
|
||||||
// Process the new message to check for known_to tags in LLM response
|
// Process the new message to check for known_to tags in LLM response
|
||||||
newMsg = processMessageTag(newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
cleanChatBody()
|
cleanChatBody()
|
||||||
@@ -889,7 +890,7 @@ out:
|
|||||||
if cfg.AutoTurn {
|
if cfg.AutoTurn {
|
||||||
lastMsg := chatBody.Messages[len(chatBody.Messages)-1]
|
lastMsg := chatBody.Messages[len(chatBody.Messages)-1]
|
||||||
if len(lastMsg.KnownTo) > 0 {
|
if len(lastMsg.KnownTo) > 0 {
|
||||||
triggerPrivateMessageResponses(lastMsg)
|
triggerPrivateMessageResponses(&lastMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -970,7 +971,7 @@ func unmarshalFuncCall(jsonStr string) (*models.FuncCall, error) {
|
|||||||
|
|
||||||
// findCall: adds chatRoundReq into the chatRoundChan and returns true if does
|
// findCall: adds chatRoundReq into the chatRoundChan and returns true if does
|
||||||
func findCall(msg, toolCall string) bool {
|
func findCall(msg, toolCall string) bool {
|
||||||
fc := &models.FuncCall{}
|
var fc *models.FuncCall
|
||||||
if toolCall != "" {
|
if toolCall != "" {
|
||||||
// HTML-decode the tool call string to handle encoded characters like < -> <=
|
// HTML-decode the tool call string to handle encoded characters like < -> <=
|
||||||
decodedToolCall := html.UnescapeString(toolCall)
|
decodedToolCall := html.UnescapeString(toolCall)
|
||||||
@@ -1306,7 +1307,7 @@ func init() {
|
|||||||
|
|
||||||
// triggerPrivateMessageResponses checks if a message was sent privately to specific characters
|
// triggerPrivateMessageResponses checks if a message was sent privately to specific characters
|
||||||
// and triggers those non-user characters to respond
|
// and triggers those non-user characters to respond
|
||||||
func triggerPrivateMessageResponses(msg models.RoleMsg) {
|
func triggerPrivateMessageResponses(msg *models.RoleMsg) {
|
||||||
if cfg == nil || !cfg.CharSpecificContextEnabled {
|
if cfg == nil || !cfg.CharSpecificContextEnabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -506,7 +506,7 @@ func TestProcessMessageTag(t *testing.T) {
|
|||||||
CharSpecificContextTag: tt.tag,
|
CharSpecificContextTag: tt.tag,
|
||||||
}
|
}
|
||||||
cfg = testCfg
|
cfg = testCfg
|
||||||
got := processMessageTag(tt.msg)
|
got := processMessageTag(&tt.msg)
|
||||||
if len(got.KnownTo) != len(tt.wantMsg.KnownTo) {
|
if len(got.KnownTo) != len(tt.wantMsg.KnownTo) {
|
||||||
t.Errorf("processMessageTag() KnownTo length = %v, want %v", len(got.KnownTo), len(tt.wantMsg.KnownTo))
|
t.Errorf("processMessageTag() KnownTo length = %v, want %v", len(got.KnownTo), len(tt.wantMsg.KnownTo))
|
||||||
t.Logf("got: %v", got.KnownTo)
|
t.Logf("got: %v", got.KnownTo)
|
||||||
|
|||||||
12
llm.go
12
llm.go
@@ -159,7 +159,7 @@ func (lcp LCPCompletion) FormMsg(msg, role string, resume bool) (io.Reader, erro
|
|||||||
}
|
}
|
||||||
if msg != "" { // otherwise let the bot to continue
|
if msg != "" { // otherwise let the bot to continue
|
||||||
newMsg := models.RoleMsg{Role: role, Content: msg}
|
newMsg := models.RoleMsg{Role: role, Content: msg}
|
||||||
newMsg = processMessageTag(newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
if !resume {
|
||||||
@@ -319,7 +319,7 @@ func (op LCPChat) FormMsg(msg, role string, resume bool) (io.Reader, error) {
|
|||||||
// Create a simple text message
|
// Create a simple text message
|
||||||
newMsg = models.NewRoleMsg(role, msg)
|
newMsg = models.NewRoleMsg(role, msg)
|
||||||
}
|
}
|
||||||
newMsg = processMessageTag(newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
logger.Debug("LCPChat FormMsg: added message to chatBody", "role", newMsg.Role,
|
logger.Debug("LCPChat FormMsg: added message to chatBody", "role", newMsg.Role,
|
||||||
"content_len", len(newMsg.Content), "message_count_after_add", len(chatBody.Messages))
|
"content_len", len(newMsg.Content), "message_count_after_add", len(chatBody.Messages))
|
||||||
@@ -413,7 +413,7 @@ func (ds DeepSeekerCompletion) FormMsg(msg, role string, resume bool) (io.Reader
|
|||||||
}
|
}
|
||||||
if msg != "" { // otherwise let the bot to continue
|
if msg != "" { // otherwise let the bot to continue
|
||||||
newMsg := models.RoleMsg{Role: role, Content: msg}
|
newMsg := models.RoleMsg{Role: role, Content: msg}
|
||||||
newMsg = processMessageTag(newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
if !resume {
|
||||||
@@ -504,7 +504,7 @@ func (ds DeepSeekerChat) FormMsg(msg, role string, resume bool) (io.Reader, erro
|
|||||||
}
|
}
|
||||||
if msg != "" { // otherwise let the bot continue
|
if msg != "" { // otherwise let the bot continue
|
||||||
newMsg := models.RoleMsg{Role: role, Content: msg}
|
newMsg := models.RoleMsg{Role: role, Content: msg}
|
||||||
newMsg = processMessageTag(newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
if !resume {
|
||||||
@@ -586,7 +586,7 @@ func (or OpenRouterCompletion) FormMsg(msg, role string, resume bool) (io.Reader
|
|||||||
logger.Debug("formmsg openroutercompletion", "link", cfg.CurrentAPI)
|
logger.Debug("formmsg openroutercompletion", "link", cfg.CurrentAPI)
|
||||||
if msg != "" { // otherwise let the bot to continue
|
if msg != "" { // otherwise let the bot to continue
|
||||||
newMsg := models.RoleMsg{Role: role, Content: msg}
|
newMsg := models.RoleMsg{Role: role, Content: msg}
|
||||||
newMsg = processMessageTag(newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
if !resume {
|
||||||
@@ -707,7 +707,7 @@ func (or OpenRouterChat) FormMsg(msg, role string, resume bool) (io.Reader, erro
|
|||||||
// Create a simple text message
|
// Create a simple text message
|
||||||
newMsg = models.NewRoleMsg(role, msg)
|
newMsg = models.NewRoleMsg(role, msg)
|
||||||
}
|
}
|
||||||
newMsg = processMessageTag(newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
if !resume {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ type Chat struct {
|
|||||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Chat) ToHistory() ([]RoleMsg, error) {
|
func (c *Chat) ToHistory() ([]RoleMsg, error) {
|
||||||
resp := []RoleMsg{}
|
resp := []RoleMsg{}
|
||||||
if err := json.Unmarshal([]byte(c.Msgs), &resp); err != nil {
|
if err := json.Unmarshal([]byte(c.Msgs), &resp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ type RoleMsg struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements custom JSON marshaling for RoleMsg
|
// MarshalJSON implements custom JSON marshaling for RoleMsg
|
||||||
func (m RoleMsg) MarshalJSON() ([]byte, error) {
|
func (m *RoleMsg) MarshalJSON() ([]byte, error) {
|
||||||
if m.hasContentParts {
|
if m.hasContentParts {
|
||||||
// Use structured content format
|
// Use structured content format
|
||||||
aux := struct {
|
aux := struct {
|
||||||
@@ -166,11 +166,11 @@ func (m *RoleMsg) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m RoleMsg) ToText(i int) string {
|
func (m *RoleMsg) ToText(i int) string {
|
||||||
icon := fmt.Sprintf("(%d)", i)
|
icon := fmt.Sprintf("(%d)", i)
|
||||||
|
|
||||||
// Convert content to string representation
|
// Convert content to string representation
|
||||||
contentStr := ""
|
var contentStr string
|
||||||
if !m.hasContentParts {
|
if !m.hasContentParts {
|
||||||
contentStr = m.Content
|
contentStr = m.Content
|
||||||
} else {
|
} else {
|
||||||
@@ -198,8 +198,8 @@ func (m RoleMsg) ToText(i int) string {
|
|||||||
return strings.ReplaceAll(textMsg, "\n\n", "\n")
|
return strings.ReplaceAll(textMsg, "\n\n", "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m RoleMsg) ToPrompt() string {
|
func (m *RoleMsg) ToPrompt() string {
|
||||||
contentStr := ""
|
var contentStr string
|
||||||
if !m.hasContentParts {
|
if !m.hasContentParts {
|
||||||
contentStr = m.Content
|
contentStr = m.Content
|
||||||
} else {
|
} else {
|
||||||
@@ -240,7 +240,7 @@ func NewMultimodalMsg(role string, contentParts []interface{}) RoleMsg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasContent returns true if the message has either string content or structured content parts
|
// HasContent returns true if the message has either string content or structured content parts
|
||||||
func (m RoleMsg) HasContent() bool {
|
func (m *RoleMsg) HasContent() bool {
|
||||||
if m.Content != "" {
|
if m.Content != "" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -251,17 +251,17 @@ func (m RoleMsg) HasContent() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsContentParts returns true if the message uses structured content parts
|
// IsContentParts returns true if the message uses structured content parts
|
||||||
func (m RoleMsg) IsContentParts() bool {
|
func (m *RoleMsg) IsContentParts() bool {
|
||||||
return m.hasContentParts
|
return m.hasContentParts
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContentParts returns the content parts of the message
|
// GetContentParts returns the content parts of the message
|
||||||
func (m RoleMsg) GetContentParts() []interface{} {
|
func (m *RoleMsg) GetContentParts() []interface{} {
|
||||||
return m.ContentParts
|
return m.ContentParts
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy creates a copy of the RoleMsg with all fields
|
// Copy creates a copy of the RoleMsg with all fields
|
||||||
func (m RoleMsg) Copy() RoleMsg {
|
func (m *RoleMsg) Copy() RoleMsg {
|
||||||
return RoleMsg{
|
return RoleMsg{
|
||||||
Role: m.Role,
|
Role: m.Role,
|
||||||
Content: m.Content,
|
Content: m.Content,
|
||||||
@@ -382,12 +382,14 @@ func (cb *ChatBody) MakeStopSliceExcluding(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Add multiple variations to catch different formatting
|
// Add multiple variations to catch different formatting
|
||||||
ss = append(ss, role+":\n") // Most common: role with newline
|
ss = append(ss,
|
||||||
ss = append(ss, role+":") // Role with colon but no newline
|
role+":\n", // Most common: role with newline
|
||||||
ss = append(ss, role+": ") // Role with colon and single space
|
role+":", // Role with colon but no newline
|
||||||
ss = append(ss, role+": ") // Role with colon and double space (common tokenization)
|
role+": ", // Role with colon and single space
|
||||||
ss = append(ss, role+": \n") // Role with colon and double space (common tokenization)
|
role+": ", // Role with colon and double space (common tokenization)
|
||||||
ss = append(ss, role+": ") // Role with colon and triple space
|
role+": \n", // Role with colon and double space (common tokenization)
|
||||||
|
role+": ", // Role with colon and triple space
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return ss
|
return ss
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,8 @@ type ORModels struct {
|
|||||||
|
|
||||||
func (orm *ORModels) ListModels(free bool) []string {
|
func (orm *ORModels) ListModels(free bool) []string {
|
||||||
resp := []string{}
|
resp := []string{}
|
||||||
for _, model := range orm.Data {
|
for i := range orm.Data {
|
||||||
|
model := &orm.Data[i] // Take address of element to avoid copying
|
||||||
if free {
|
if free {
|
||||||
if model.Pricing.Prompt == "0" && model.Pricing.Completion == "0" {
|
if model.Pricing.Prompt == "0" && model.Pricing.Completion == "0" {
|
||||||
// treat missing request as free
|
// treat missing request as free
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ func createTextChunk(embed PngEmbed) ([]byte, error) {
|
|||||||
if err := binary.Write(chunk, binary.BigEndian, uint32(len(data))); err != nil {
|
if err := binary.Write(chunk, binary.BigEndian, uint32(len(data))); err != nil {
|
||||||
return nil, fmt.Errorf("error writing chunk length: %w", err)
|
return nil, fmt.Errorf("error writing chunk length: %w", err)
|
||||||
}
|
}
|
||||||
if _, err := chunk.Write([]byte(textChunkType)); err != nil {
|
if _, err := chunk.WriteString(textChunkType); err != nil {
|
||||||
return nil, fmt.Errorf("error writing chunk type: %w", err)
|
return nil, fmt.Errorf("error writing chunk type: %w", err)
|
||||||
}
|
}
|
||||||
if _, err := chunk.Write(data); err != nil {
|
if _, err := chunk.Write(data); err != nil {
|
||||||
|
|||||||
@@ -313,11 +313,12 @@ func makePropsTable(props map[string]float32) *tview.Table {
|
|||||||
logger.Warn("empty options list for", "label", label, "api", cfg.CurrentAPI, "localModelsLen", len(LocalModels), "orModelsLen", len(ORFreeModels))
|
logger.Warn("empty options list for", "label", label, "api", cfg.CurrentAPI, "localModelsLen", len(LocalModels), "orModelsLen", len(ORFreeModels))
|
||||||
message := "No options available for " + label
|
message := "No options available for " + label
|
||||||
if label == "Select a model" {
|
if label == "Select a model" {
|
||||||
if strings.Contains(cfg.CurrentAPI, "openrouter.ai") {
|
switch {
|
||||||
|
case strings.Contains(cfg.CurrentAPI, "openrouter.ai"):
|
||||||
message = "No OpenRouter models available. Check token and connection."
|
message = "No OpenRouter models available. Check token and connection."
|
||||||
} else if strings.Contains(cfg.CurrentAPI, "api.deepseek.com") {
|
case strings.Contains(cfg.CurrentAPI, "api.deepseek.com"):
|
||||||
message = "DeepSeek models should be available. Please report bug."
|
message = "DeepSeek models should be available. Please report bug."
|
||||||
} else {
|
default:
|
||||||
message = "No llama.cpp models loaded. Ensure llama.cpp server is running with models."
|
message = "No llama.cpp models loaded. Ensure llama.cpp server is running with models."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ func (r *RAG) LoadRAG(fpath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adjust batch size if needed
|
// Adjust batch size if needed
|
||||||
if len(paragraphs) < int(r.cfg.RAGBatchSize) && len(paragraphs) > 0 {
|
if len(paragraphs) < r.cfg.RAGBatchSize && len(paragraphs) > 0 {
|
||||||
r.cfg.RAGBatchSize = len(paragraphs)
|
r.cfg.RAGBatchSize = len(paragraphs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ func (r *RAG) LoadRAG(fpath string) error {
|
|||||||
ctn := 0
|
ctn := 0
|
||||||
totalParagraphs := len(paragraphs)
|
totalParagraphs := len(paragraphs)
|
||||||
for {
|
for {
|
||||||
if int(right) > totalParagraphs {
|
if right > totalParagraphs {
|
||||||
batchCh <- map[int][]string{left: paragraphs[left:]}
|
batchCh <- map[int][]string{left: paragraphs[left:]}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
65
tables.go
65
tables.go
@@ -30,7 +30,7 @@ func makeChatTable(chatMap map[string]models.Chat) *tview.Table {
|
|||||||
// Add header row (row 0)
|
// Add header row (row 0)
|
||||||
for c := 0; c < cols; c++ {
|
for c := 0; c < cols; c++ {
|
||||||
color := tcell.ColorWhite
|
color := tcell.ColorWhite
|
||||||
headerText := ""
|
var headerText string
|
||||||
switch c {
|
switch c {
|
||||||
case 0:
|
case 0:
|
||||||
headerText = "Chat Name"
|
headerText = "Chat Name"
|
||||||
@@ -259,19 +259,20 @@ func makeRAGTable(fileList []string) *tview.Flex {
|
|||||||
for r := 0; r < rows; r++ {
|
for r := 0; r < rows; r++ {
|
||||||
for c := 0; c < cols; c++ {
|
for c := 0; c < cols; c++ {
|
||||||
color := tcell.ColorWhite
|
color := tcell.ColorWhite
|
||||||
if c < 1 {
|
switch {
|
||||||
|
case c < 1:
|
||||||
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
||||||
tview.NewTableCell(fileList[r]).
|
tview.NewTableCell(fileList[r]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
SetAlign(tview.AlignCenter).
|
SetAlign(tview.AlignCenter).
|
||||||
SetSelectable(false))
|
SetSelectable(false))
|
||||||
} else if c == 1 { // Action description column - not selectable
|
case c == 1: // Action description column - not selectable
|
||||||
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
||||||
tview.NewTableCell("(Action)").
|
tview.NewTableCell("(Action)").
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
SetAlign(tview.AlignCenter).
|
SetAlign(tview.AlignCenter).
|
||||||
SetSelectable(false))
|
SetSelectable(false))
|
||||||
} else { // Action button column - selectable
|
default: // Action button column - selectable
|
||||||
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
||||||
tview.NewTableCell(actions[c-1]).
|
tview.NewTableCell(actions[c-1]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
@@ -406,19 +407,20 @@ func makeLoadedRAGTable(fileList []string) *tview.Flex {
|
|||||||
for r := 0; r < rows; r++ {
|
for r := 0; r < rows; r++ {
|
||||||
for c := 0; c < cols; c++ {
|
for c := 0; c < cols; c++ {
|
||||||
color := tcell.ColorWhite
|
color := tcell.ColorWhite
|
||||||
if c < 1 {
|
switch {
|
||||||
|
case c < 1:
|
||||||
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
||||||
tview.NewTableCell(fileList[r]).
|
tview.NewTableCell(fileList[r]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
SetAlign(tview.AlignCenter).
|
SetAlign(tview.AlignCenter).
|
||||||
SetSelectable(false))
|
SetSelectable(false))
|
||||||
} else if c == 1 { // Action description column - not selectable
|
case c == 1: // Action description column - not selectable
|
||||||
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
||||||
tview.NewTableCell("(Action)").
|
tview.NewTableCell("(Action)").
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
SetAlign(tview.AlignCenter).
|
SetAlign(tview.AlignCenter).
|
||||||
SetSelectable(false))
|
SetSelectable(false))
|
||||||
} else { // Action button column - selectable
|
default: // Action button column - selectable
|
||||||
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
|
||||||
tview.NewTableCell(actions[c-1]).
|
tview.NewTableCell(actions[c-1]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
@@ -487,13 +489,14 @@ func makeAgentTable(agentList []string) *tview.Table {
|
|||||||
for r := 0; r < rows; r++ {
|
for r := 0; r < rows; r++ {
|
||||||
for c := 0; c < cols; c++ {
|
for c := 0; c < cols; c++ {
|
||||||
color := tcell.ColorWhite
|
color := tcell.ColorWhite
|
||||||
if c < 1 {
|
switch {
|
||||||
|
case c < 1:
|
||||||
chatActTable.SetCell(r, c,
|
chatActTable.SetCell(r, c,
|
||||||
tview.NewTableCell(agentList[r]).
|
tview.NewTableCell(agentList[r]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
SetAlign(tview.AlignCenter).
|
SetAlign(tview.AlignCenter).
|
||||||
SetSelectable(false))
|
SetSelectable(false))
|
||||||
} else if c == 1 {
|
case c == 1:
|
||||||
if actions[c-1] == "filepath" {
|
if actions[c-1] == "filepath" {
|
||||||
cc, ok := sysMap[agentList[r]]
|
cc, ok := sysMap[agentList[r]]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -510,7 +513,7 @@ func makeAgentTable(agentList []string) *tview.Table {
|
|||||||
tview.NewTableCell(actions[c-1]).
|
tview.NewTableCell(actions[c-1]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
SetAlign(tview.AlignCenter))
|
SetAlign(tview.AlignCenter))
|
||||||
} else {
|
default:
|
||||||
chatActTable.SetCell(r, c,
|
chatActTable.SetCell(r, c,
|
||||||
tview.NewTableCell(actions[c-1]).
|
tview.NewTableCell(actions[c-1]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
@@ -600,13 +603,14 @@ func makeCodeBlockTable(codeBlocks []string) *tview.Table {
|
|||||||
if len(codeBlocks[r]) < 30 {
|
if len(codeBlocks[r]) < 30 {
|
||||||
previewLen = len(codeBlocks[r])
|
previewLen = len(codeBlocks[r])
|
||||||
}
|
}
|
||||||
if c < 1 {
|
switch {
|
||||||
|
case c < 1:
|
||||||
table.SetCell(r, c,
|
table.SetCell(r, c,
|
||||||
tview.NewTableCell(codeBlocks[r][:previewLen]).
|
tview.NewTableCell(codeBlocks[r][:previewLen]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
SetAlign(tview.AlignCenter).
|
SetAlign(tview.AlignCenter).
|
||||||
SetSelectable(false))
|
SetSelectable(false))
|
||||||
} else {
|
default:
|
||||||
table.SetCell(r, c,
|
table.SetCell(r, c,
|
||||||
tview.NewTableCell(actions[c-1]).
|
tview.NewTableCell(actions[c-1]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
@@ -671,13 +675,14 @@ func makeImportChatTable(filenames []string) *tview.Table {
|
|||||||
for r := 0; r < rows; r++ {
|
for r := 0; r < rows; r++ {
|
||||||
for c := 0; c < cols; c++ {
|
for c := 0; c < cols; c++ {
|
||||||
color := tcell.ColorWhite
|
color := tcell.ColorWhite
|
||||||
if c < 1 {
|
switch {
|
||||||
|
case c < 1:
|
||||||
chatActTable.SetCell(r, c,
|
chatActTable.SetCell(r, c,
|
||||||
tview.NewTableCell(filenames[r]).
|
tview.NewTableCell(filenames[r]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
SetAlign(tview.AlignCenter).
|
SetAlign(tview.AlignCenter).
|
||||||
SetSelectable(false))
|
SetSelectable(false))
|
||||||
} else {
|
default:
|
||||||
chatActTable.SetCell(r, c,
|
chatActTable.SetCell(r, c,
|
||||||
tview.NewTableCell(actions[c-1]).
|
tview.NewTableCell(actions[c-1]).
|
||||||
SetTextColor(color).
|
SetTextColor(color).
|
||||||
@@ -861,25 +866,23 @@ func makeFilePicker() *tview.Flex {
|
|||||||
currentStackPos = len(dirStack) - 1
|
currentStackPos = len(dirStack) - 1
|
||||||
statusView.SetText("Current: " + newDir)
|
statusView.SetText("Current: " + newDir)
|
||||||
})
|
})
|
||||||
} else {
|
} else if hasAllowedExtension(name) {
|
||||||
// Only show files that have allowed extensions (from config)
|
// Only show files that have allowed extensions (from config)
|
||||||
if hasAllowedExtension(name) {
|
// Capture the file name for the closure to avoid loop variable issues
|
||||||
// Capture the file name for the closure to avoid loop variable issues
|
fileName := name
|
||||||
fileName := name
|
fullFilePath := path.Join(dir, fileName)
|
||||||
fullFilePath := path.Join(dir, fileName)
|
listView.AddItem(fileName+" [gray](File)[-]", "", 0, func() {
|
||||||
listView.AddItem(fileName+" [gray](File)[-]", "", 0, func() {
|
selectedFile = fullFilePath
|
||||||
selectedFile = fullFilePath
|
statusView.SetText("Selected: " + selectedFile)
|
||||||
|
// Check if the file is an image
|
||||||
|
if isImageFile(fileName) {
|
||||||
|
// For image files, offer to attach to the next LLM message
|
||||||
|
statusView.SetText("Selected image: " + selectedFile)
|
||||||
|
} else {
|
||||||
|
// For non-image files, display as before
|
||||||
statusView.SetText("Selected: " + selectedFile)
|
statusView.SetText("Selected: " + selectedFile)
|
||||||
// Check if the file is an image
|
}
|
||||||
if isImageFile(fileName) {
|
})
|
||||||
// For image files, offer to attach to the next LLM message
|
|
||||||
statusView.SetText("Selected image: " + selectedFile)
|
|
||||||
} else {
|
|
||||||
// For non-image files, display as before
|
|
||||||
statusView.SetText("Selected: " + selectedFile)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statusView.SetText("Current: " + dir)
|
statusView.SetText("Current: " + dir)
|
||||||
|
|||||||
25
tui.go
25
tui.go
@@ -533,8 +533,7 @@ func init() {
|
|||||||
})
|
})
|
||||||
textView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
textView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||||
// Handle vim-like navigation in TextView
|
// Handle vim-like navigation in TextView
|
||||||
switch event.Key() {
|
if event.Key() == tcell.KeyRune {
|
||||||
case tcell.KeyRune:
|
|
||||||
switch event.Rune() {
|
switch event.Rune() {
|
||||||
case 'j':
|
case 'j':
|
||||||
// For line down
|
// For line down
|
||||||
@@ -672,17 +671,18 @@ func init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
m := chatBody.Messages[selectedIndex]
|
m := chatBody.Messages[selectedIndex]
|
||||||
if roleEditMode {
|
switch {
|
||||||
|
case roleEditMode:
|
||||||
hideIndexBar() // Hide overlay first
|
hideIndexBar() // Hide overlay first
|
||||||
// Set the current role as the default text in the input field
|
// Set the current role as the default text in the input field
|
||||||
roleEditWindow.SetText(m.Role)
|
roleEditWindow.SetText(m.Role)
|
||||||
pages.AddPage(roleEditPage, roleEditWindow, true, true)
|
pages.AddPage(roleEditPage, roleEditWindow, true, true)
|
||||||
roleEditMode = false // Reset the flag
|
roleEditMode = false // Reset the flag
|
||||||
} else if editMode {
|
case editMode:
|
||||||
hideIndexBar() // Hide overlay first
|
hideIndexBar() // Hide overlay first
|
||||||
pages.AddPage(editMsgPage, editArea, true, true)
|
pages.AddPage(editMsgPage, editArea, true, true)
|
||||||
editArea.SetText(m.Content, true)
|
editArea.SetText(m.Content, true)
|
||||||
} else {
|
default:
|
||||||
if err := copyToClipboard(m.Content); err != nil {
|
if err := copyToClipboard(m.Content); err != nil {
|
||||||
logger.Error("failed to copy to clipboard", "error", err)
|
logger.Error("failed to copy to clipboard", "error", err)
|
||||||
}
|
}
|
||||||
@@ -760,22 +760,19 @@ func init() {
|
|||||||
pages.RemovePage(helpPage)
|
pages.RemovePage(helpPage)
|
||||||
})
|
})
|
||||||
helpView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
helpView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||||
switch event.Key() {
|
if event.Key() == tcell.KeyEnter {
|
||||||
case tcell.KeyEnter:
|
|
||||||
return event
|
return event
|
||||||
default:
|
}
|
||||||
if event.Key() == tcell.KeyRune && event.Rune() == 'x' {
|
if event.Key() == tcell.KeyRune && event.Rune() == 'x' {
|
||||||
pages.RemovePage(helpPage)
|
pages.RemovePage(helpPage)
|
||||||
return nil
|
return nil
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
//
|
//
|
||||||
imgView = tview.NewImage()
|
imgView = tview.NewImage()
|
||||||
imgView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
imgView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||||
switch event.Key() {
|
if event.Key() == tcell.KeyEnter {
|
||||||
case tcell.KeyEnter:
|
|
||||||
pages.RemovePage(imgPage)
|
pages.RemovePage(imgPage)
|
||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user