Chore: noblanks complaints
This commit is contained in:
34
bot_test.go
34
bot_test.go
@@ -1,12 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gf-lt/config"
|
"gf-lt/config"
|
||||||
"gf-lt/models"
|
"gf-lt/models"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConsolidateConsecutiveAssistantMessages(t *testing.T) {
|
func TestConsolidateConsecutiveAssistantMessages(t *testing.T) {
|
||||||
// Mock config for testing
|
// Mock config for testing
|
||||||
testCfg := &config.Config{
|
testCfg := &config.Config{
|
||||||
@@ -14,7 +12,6 @@ func TestConsolidateConsecutiveAssistantMessages(t *testing.T) {
|
|||||||
WriteNextMsgAsCompletionAgent: "",
|
WriteNextMsgAsCompletionAgent: "",
|
||||||
}
|
}
|
||||||
cfg = testCfg
|
cfg = testCfg
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
input []models.RoleMsg
|
input []models.RoleMsg
|
||||||
@@ -114,38 +111,31 @@ func TestConsolidateConsecutiveAssistantMessages(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result := consolidateAssistantMessages(tt.input)
|
result := consolidateAssistantMessages(tt.input)
|
||||||
|
|
||||||
if len(result) != len(tt.expected) {
|
if len(result) != len(tt.expected) {
|
||||||
t.Errorf("Expected %d messages, got %d", len(tt.expected), len(result))
|
t.Errorf("Expected %d messages, got %d", len(tt.expected), len(result))
|
||||||
t.Logf("Result: %+v", result)
|
t.Logf("Result: %+v", result)
|
||||||
t.Logf("Expected: %+v", tt.expected)
|
t.Logf("Expected: %+v", tt.expected)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, expectedMsg := range tt.expected {
|
for i, expectedMsg := range tt.expected {
|
||||||
if i >= len(result) {
|
if i >= len(result) {
|
||||||
t.Errorf("Result has fewer messages than expected at index %d", i)
|
t.Errorf("Result has fewer messages than expected at index %d", i)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
actualMsg := result[i]
|
actualMsg := result[i]
|
||||||
if actualMsg.Role != expectedMsg.Role {
|
if actualMsg.Role != expectedMsg.Role {
|
||||||
t.Errorf("Message %d: expected role '%s', got '%s'", i, expectedMsg.Role, actualMsg.Role)
|
t.Errorf("Message %d: expected role '%s', got '%s'", i, expectedMsg.Role, actualMsg.Role)
|
||||||
}
|
}
|
||||||
|
|
||||||
if actualMsg.Content != expectedMsg.Content {
|
if actualMsg.Content != expectedMsg.Content {
|
||||||
t.Errorf("Message %d: expected content '%s', got '%s'", i, expectedMsg.Content, actualMsg.Content)
|
t.Errorf("Message %d: expected content '%s', got '%s'", i, expectedMsg.Content, actualMsg.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
if actualMsg.ToolCallID != expectedMsg.ToolCallID {
|
if actualMsg.ToolCallID != expectedMsg.ToolCallID {
|
||||||
t.Errorf("Message %d: expected ToolCallID '%s', got '%s'", i, expectedMsg.ToolCallID, actualMsg.ToolCallID)
|
t.Errorf("Message %d: expected ToolCallID '%s', got '%s'", i, expectedMsg.ToolCallID, actualMsg.ToolCallID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional check: ensure no messages were lost
|
// Additional check: ensure no messages were lost
|
||||||
if !reflect.DeepEqual(result, tt.expected) {
|
if !reflect.DeepEqual(result, tt.expected) {
|
||||||
t.Errorf("Result does not match expected:\nResult: %+v\nExpected: %+v", result, tt.expected)
|
t.Errorf("Result does not match expected:\nResult: %+v\nExpected: %+v", result, tt.expected)
|
||||||
@@ -153,7 +143,6 @@ func TestConsolidateConsecutiveAssistantMessages(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnmarshalFuncCall(t *testing.T) {
|
func TestUnmarshalFuncCall(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -213,7 +202,6 @@ func TestUnmarshalFuncCall(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got, err := unmarshalFuncCall(tt.jsonStr)
|
got, err := unmarshalFuncCall(tt.jsonStr)
|
||||||
@@ -238,7 +226,6 @@ func TestUnmarshalFuncCall(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConvertJSONToMapStringString(t *testing.T) {
|
func TestConvertJSONToMapStringString(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -265,7 +252,6 @@ func TestConvertJSONToMapStringString(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got, err := convertJSONToMapStringString(tt.jsonStr)
|
got, err := convertJSONToMapStringString(tt.jsonStr)
|
||||||
@@ -287,7 +273,6 @@ func TestConvertJSONToMapStringString(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseKnownToTag(t *testing.T) {
|
func TestParseKnownToTag(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -378,7 +363,6 @@ func TestParseKnownToTag(t *testing.T) {
|
|||||||
wantKnownTo: []string{"Alice", "Bob", "Carl"},
|
wantKnownTo: []string{"Alice", "Bob", "Carl"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
// Set up config
|
// Set up config
|
||||||
@@ -402,7 +386,6 @@ func TestParseKnownToTag(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProcessMessageTag(t *testing.T) {
|
func TestProcessMessageTag(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -498,7 +481,6 @@ func TestProcessMessageTag(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
testCfg := &config.Config{
|
testCfg := &config.Config{
|
||||||
@@ -529,7 +511,6 @@ func TestProcessMessageTag(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterMessagesForCharacter(t *testing.T) {
|
func TestFilterMessagesForCharacter(t *testing.T) {
|
||||||
messages := []models.RoleMsg{
|
messages := []models.RoleMsg{
|
||||||
{Role: "system", Content: "System message", KnownTo: nil}, // visible to all
|
{Role: "system", Content: "System message", KnownTo: nil}, // visible to all
|
||||||
@@ -539,7 +520,6 @@ func TestFilterMessagesForCharacter(t *testing.T) {
|
|||||||
{Role: "Alice", Content: "Private to Carl", KnownTo: []string{"Alice", "Carl"}},
|
{Role: "Alice", Content: "Private to Carl", KnownTo: []string{"Alice", "Carl"}},
|
||||||
{Role: "Carl", Content: "Hi all", KnownTo: nil}, // visible to all
|
{Role: "Carl", Content: "Hi all", KnownTo: nil}, // visible to all
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
enabled bool
|
enabled bool
|
||||||
@@ -583,7 +563,6 @@ func TestFilterMessagesForCharacter(t *testing.T) {
|
|||||||
wantIndices: []int{0, 1, 5},
|
wantIndices: []int{0, 1, 5},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
testCfg := &config.Config{
|
testCfg := &config.Config{
|
||||||
@@ -591,15 +570,12 @@ func TestFilterMessagesForCharacter(t *testing.T) {
|
|||||||
CharSpecificContextTag: "@",
|
CharSpecificContextTag: "@",
|
||||||
}
|
}
|
||||||
cfg = testCfg
|
cfg = testCfg
|
||||||
|
|
||||||
got := filterMessagesForCharacter(messages, tt.character)
|
got := filterMessagesForCharacter(messages, tt.character)
|
||||||
|
|
||||||
if len(got) != len(tt.wantIndices) {
|
if len(got) != len(tt.wantIndices) {
|
||||||
t.Errorf("filterMessagesForCharacter() returned %d messages, want %d", len(got), len(tt.wantIndices))
|
t.Errorf("filterMessagesForCharacter() returned %d messages, want %d", len(got), len(tt.wantIndices))
|
||||||
t.Logf("got: %v", got)
|
t.Logf("got: %v", got)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, idx := range tt.wantIndices {
|
for i, idx := range tt.wantIndices {
|
||||||
if got[i].Content != messages[idx].Content {
|
if got[i].Content != messages[idx].Content {
|
||||||
t.Errorf("filterMessagesForCharacter() message %d content = %q, want %q", i, got[i].Content, messages[idx].Content)
|
t.Errorf("filterMessagesForCharacter() message %d content = %q, want %q", i, got[i].Content, messages[idx].Content)
|
||||||
@@ -608,7 +584,6 @@ func TestFilterMessagesForCharacter(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRoleMsgCopyPreservesKnownTo(t *testing.T) {
|
func TestRoleMsgCopyPreservesKnownTo(t *testing.T) {
|
||||||
// Test that the Copy() method preserves the KnownTo field
|
// Test that the Copy() method preserves the KnownTo field
|
||||||
originalMsg := models.RoleMsg{
|
originalMsg := models.RoleMsg{
|
||||||
@@ -616,9 +591,7 @@ func TestRoleMsgCopyPreservesKnownTo(t *testing.T) {
|
|||||||
Content: "Test message",
|
Content: "Test message",
|
||||||
KnownTo: []string{"Bob", "Charlie"},
|
KnownTo: []string{"Bob", "Charlie"},
|
||||||
}
|
}
|
||||||
|
|
||||||
copiedMsg := originalMsg.Copy()
|
copiedMsg := originalMsg.Copy()
|
||||||
|
|
||||||
if copiedMsg.Role != originalMsg.Role {
|
if copiedMsg.Role != originalMsg.Role {
|
||||||
t.Errorf("Copy() failed to preserve Role: got %q, want %q", copiedMsg.Role, originalMsg.Role)
|
t.Errorf("Copy() failed to preserve Role: got %q, want %q", copiedMsg.Role, originalMsg.Role)
|
||||||
}
|
}
|
||||||
@@ -635,7 +608,6 @@ func TestRoleMsgCopyPreservesKnownTo(t *testing.T) {
|
|||||||
t.Errorf("Copy() failed to preserve hasContentParts flag")
|
t.Errorf("Copy() failed to preserve hasContentParts flag")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKnownToFieldPreservationScenario(t *testing.T) {
|
func TestKnownToFieldPreservationScenario(t *testing.T) {
|
||||||
// Test the specific scenario from the log where KnownTo field was getting lost
|
// Test the specific scenario from the log where KnownTo field was getting lost
|
||||||
originalMsg := models.RoleMsg{
|
originalMsg := models.RoleMsg{
|
||||||
@@ -643,28 +615,22 @@ func TestKnownToFieldPreservationScenario(t *testing.T) {
|
|||||||
Content: `Alice: "Okay, Bob. The word is... **'Ephemeral'**. (ooc: @Bob@)"`,
|
Content: `Alice: "Okay, Bob. The word is... **'Ephemeral'**. (ooc: @Bob@)"`,
|
||||||
KnownTo: []string{"Bob"}, // This was detected in the log
|
KnownTo: []string{"Bob"}, // This was detected in the log
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Original message - Role: %s, Content: %s, KnownTo: %v",
|
t.Logf("Original message - Role: %s, Content: %s, KnownTo: %v",
|
||||||
originalMsg.Role, originalMsg.Content, originalMsg.KnownTo)
|
originalMsg.Role, originalMsg.Content, originalMsg.KnownTo)
|
||||||
|
|
||||||
// Simulate what happens when the message gets copied during processing
|
// Simulate what happens when the message gets copied during processing
|
||||||
copiedMsg := originalMsg.Copy()
|
copiedMsg := originalMsg.Copy()
|
||||||
|
|
||||||
t.Logf("Copied message - Role: %s, Content: %s, KnownTo: %v",
|
t.Logf("Copied message - Role: %s, Content: %s, KnownTo: %v",
|
||||||
copiedMsg.Role, copiedMsg.Content, copiedMsg.KnownTo)
|
copiedMsg.Role, copiedMsg.Content, copiedMsg.KnownTo)
|
||||||
|
|
||||||
// Check if KnownTo field survived the copy
|
// Check if KnownTo field survived the copy
|
||||||
if len(copiedMsg.KnownTo) == 0 {
|
if len(copiedMsg.KnownTo) == 0 {
|
||||||
t.Error("ERROR: KnownTo field was lost during copy!")
|
t.Error("ERROR: KnownTo field was lost during copy!")
|
||||||
} else {
|
} else {
|
||||||
t.Log("SUCCESS: KnownTo field was preserved during copy!")
|
t.Log("SUCCESS: KnownTo field was preserved during copy!")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the content is the same
|
// Verify the content is the same
|
||||||
if copiedMsg.Content != originalMsg.Content {
|
if copiedMsg.Content != originalMsg.Content {
|
||||||
t.Errorf("Content was changed during copy: got %s, want %s", copiedMsg.Content, originalMsg.Content)
|
t.Errorf("Content was changed during copy: got %s, want %s", copiedMsg.Content, originalMsg.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the KnownTo slice is properly copied
|
// Verify the KnownTo slice is properly copied
|
||||||
if !reflect.DeepEqual(copiedMsg.KnownTo, originalMsg.KnownTo) {
|
if !reflect.DeepEqual(copiedMsg.KnownTo, originalMsg.KnownTo) {
|
||||||
t.Errorf("KnownTo was not properly copied: got %v, want %v", copiedMsg.KnownTo, originalMsg.KnownTo)
|
t.Errorf("KnownTo was not properly copied: got %v, want %v", copiedMsg.KnownTo, originalMsg.KnownTo)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRoleMsgToTextWithImages(t *testing.T) {
|
func TestRoleMsgToTextWithImages(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -92,7 +90,6 @@ func TestRoleMsgToTextWithImages(t *testing.T) {
|
|||||||
expected: "[orange::i][image: /old/path/photo.jpg][-:-:-]",
|
expected: "[orange::i][image: /old/path/photo.jpg][-:-:-]",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result := tt.msg.ToText(tt.index)
|
result := tt.msg.ToText(tt.index)
|
||||||
@@ -110,12 +107,10 @@ func TestRoleMsgToTextWithImages(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractDisplayPath(t *testing.T) {
|
func TestExtractDisplayPath(t *testing.T) {
|
||||||
// Save original base dir
|
// Save original base dir
|
||||||
originalBaseDir := imageBaseDir
|
originalBaseDir := imageBaseDir
|
||||||
defer func() { imageBaseDir = originalBaseDir }()
|
defer func() { imageBaseDir = originalBaseDir }()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
baseDir string
|
baseDir string
|
||||||
@@ -153,7 +148,6 @@ func TestExtractDisplayPath(t *testing.T) {
|
|||||||
expected: "..._that_exceeds_sixty_characters_limit_yes_it_is_very_long.jpg",
|
expected: "..._that_exceeds_sixty_characters_limit_yes_it_is_very_long.jpg",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
imageBaseDir = tt.baseDir
|
imageBaseDir = tt.baseDir
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ func TestORModelsListModels(t *testing.T) {
|
|||||||
t.Errorf("expected 4 total models, got %d", len(allModels))
|
t.Errorf("expected 4 total models, got %d", len(allModels))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("integration with or_models.json", func(t *testing.T) {
|
t.Run("integration with or_models.json", func(t *testing.T) {
|
||||||
// Attempt to load the real data file from the project root
|
// Attempt to load the real data file from the project root
|
||||||
path := filepath.Join("..", "or_models.json")
|
path := filepath.Join("..", "or_models.json")
|
||||||
|
|||||||
111
tools.go
111
tools.go
@@ -172,12 +172,10 @@ func init() {
|
|||||||
panic("failed to init seachagent; error: " + err.Error())
|
panic("failed to init seachagent; error: " + err.Error())
|
||||||
}
|
}
|
||||||
WebSearcher = sa
|
WebSearcher = sa
|
||||||
|
|
||||||
if err := rag.Init(cfg, logger, store); err != nil {
|
if err := rag.Init(cfg, logger, store); err != nil {
|
||||||
logger.Warn("failed to init rag; rag_search tool will not be available", "error", err)
|
logger.Warn("failed to init rag; rag_search tool will not be available", "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getWebAgentClient returns a singleton AgentClient for web agents.
|
// getWebAgentClient returns a singleton AgentClient for web agents.
|
||||||
func getWebAgentClient() *agent.AgentClient {
|
func getWebAgentClient() *agent.AgentClient {
|
||||||
webAgentClientOnce.Do(func() {
|
webAgentClientOnce.Do(func() {
|
||||||
@@ -197,7 +195,6 @@ func getWebAgentClient() *agent.AgentClient {
|
|||||||
})
|
})
|
||||||
return webAgentClient
|
return webAgentClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerWebAgents registers WebAgentB instances for websearch and read_url tools.
|
// registerWebAgents registers WebAgentB instances for websearch and read_url tools.
|
||||||
func registerWebAgents() {
|
func registerWebAgents() {
|
||||||
webAgentsOnce.Do(func() {
|
webAgentsOnce.Do(func() {
|
||||||
@@ -212,7 +209,6 @@ func registerWebAgents() {
|
|||||||
agent.Register("summarize_chat", agent.NewWebAgentB(client, summarySysPrompt))
|
agent.Register("summarize_chat", agent.NewWebAgentB(client, summarySysPrompt))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// web search (depends on extra server)
|
// web search (depends on extra server)
|
||||||
func websearch(args map[string]string) []byte {
|
func websearch(args map[string]string) []byte {
|
||||||
// make http request return bytes
|
// make http request return bytes
|
||||||
@@ -246,7 +242,6 @@ func websearch(args map[string]string) []byte {
|
|||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// rag search (searches local document database)
|
// rag search (searches local document database)
|
||||||
func ragsearch(args map[string]string) []byte {
|
func ragsearch(args map[string]string) []byte {
|
||||||
query, ok := args["query"]
|
query, ok := args["query"]
|
||||||
@@ -265,21 +260,18 @@ func ragsearch(args map[string]string) []byte {
|
|||||||
"limit_arg", limitS, "error", err)
|
"limit_arg", limitS, "error", err)
|
||||||
limit = 3
|
limit = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
ragInstance := rag.GetInstance()
|
ragInstance := rag.GetInstance()
|
||||||
if ragInstance == nil {
|
if ragInstance == nil {
|
||||||
msg := "rag not initialized; rag_search tool is not available"
|
msg := "rag not initialized; rag_search tool is not available"
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
results, err := ragInstance.Search(query, limit)
|
results, err := ragInstance.Search(query, limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "rag search failed; error: " + err.Error()
|
msg := "rag search failed; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := json.Marshal(results)
|
data, err := json.Marshal(results)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "failed to marshal rag search result; error: " + err.Error()
|
msg := "failed to marshal rag search result; error: " + err.Error()
|
||||||
@@ -288,7 +280,6 @@ func ragsearch(args map[string]string) []byte {
|
|||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// web search raw (returns raw data without processing)
|
// web search raw (returns raw data without processing)
|
||||||
func websearchRaw(args map[string]string) []byte {
|
func websearchRaw(args map[string]string) []byte {
|
||||||
// make http request return bytes
|
// make http request return bytes
|
||||||
@@ -317,7 +308,6 @@ func websearchRaw(args map[string]string) []byte {
|
|||||||
// Return raw response without any processing
|
// Return raw response without any processing
|
||||||
return []byte(fmt.Sprintf("%+v", resp))
|
return []byte(fmt.Sprintf("%+v", resp))
|
||||||
}
|
}
|
||||||
|
|
||||||
// retrieves url content (text)
|
// retrieves url content (text)
|
||||||
func readURL(args map[string]string) []byte {
|
func readURL(args map[string]string) []byte {
|
||||||
// make http request return bytes
|
// make http request return bytes
|
||||||
@@ -341,7 +331,6 @@ func readURL(args map[string]string) []byte {
|
|||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// retrieves url content raw (returns raw content without processing)
|
// retrieves url content raw (returns raw content without processing)
|
||||||
func readURLRaw(args map[string]string) []byte {
|
func readURLRaw(args map[string]string) []byte {
|
||||||
// make http request return bytes
|
// make http request return bytes
|
||||||
@@ -360,7 +349,6 @@ func readURLRaw(args map[string]string) []byte {
|
|||||||
// Return raw response without any processing
|
// Return raw response without any processing
|
||||||
return []byte(fmt.Sprintf("%+v", resp))
|
return []byte(fmt.Sprintf("%+v", resp))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
consider cases:
|
consider cases:
|
||||||
- append mode (treat it like a journal appendix)
|
- append mode (treat it like a journal appendix)
|
||||||
@@ -390,7 +378,6 @@ func memorise(args map[string]string) []byte {
|
|||||||
msg := "info saved under the topic:" + args["topic"]
|
msg := "info saved under the topic:" + args["topic"]
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func recall(args map[string]string) []byte {
|
func recall(args map[string]string) []byte {
|
||||||
agent := cfg.AssistantRole
|
agent := cfg.AssistantRole
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
@@ -406,7 +393,6 @@ func recall(args map[string]string) []byte {
|
|||||||
answer := fmt.Sprintf("under the topic: %s is stored:\n%s", args["topic"], mind)
|
answer := fmt.Sprintf("under the topic: %s is stored:\n%s", args["topic"], mind)
|
||||||
return []byte(answer)
|
return []byte(answer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func recallTopics(args map[string]string) []byte {
|
func recallTopics(args map[string]string) []byte {
|
||||||
agent := cfg.AssistantRole
|
agent := cfg.AssistantRole
|
||||||
topics, err := store.RecallTopics(agent)
|
topics, err := store.RecallTopics(agent)
|
||||||
@@ -417,9 +403,7 @@ func recallTopics(args map[string]string) []byte {
|
|||||||
joinedS := strings.Join(topics, ";")
|
joinedS := strings.Join(topics, ";")
|
||||||
return []byte(joinedS)
|
return []byte(joinedS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// File Manipulation Tools
|
// File Manipulation Tools
|
||||||
|
|
||||||
func fileCreate(args map[string]string) []byte {
|
func fileCreate(args map[string]string) []byte {
|
||||||
path, ok := args["path"]
|
path, ok := args["path"]
|
||||||
if !ok || path == "" {
|
if !ok || path == "" {
|
||||||
@@ -427,24 +411,19 @@ func fileCreate(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
path = resolvePath(path)
|
path = resolvePath(path)
|
||||||
|
|
||||||
content, ok := args["content"]
|
content, ok := args["content"]
|
||||||
if !ok {
|
if !ok {
|
||||||
content = ""
|
content = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := writeStringToFile(path, content); err != nil {
|
if err := writeStringToFile(path, content); err != nil {
|
||||||
msg := "failed to create file; error: " + err.Error()
|
msg := "failed to create file; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := "file created successfully at " + path
|
msg := "file created successfully at " + path
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileRead(args map[string]string) []byte {
|
func fileRead(args map[string]string) []byte {
|
||||||
path, ok := args["path"]
|
path, ok := args["path"]
|
||||||
if !ok || path == "" {
|
if !ok || path == "" {
|
||||||
@@ -452,16 +431,13 @@ func fileRead(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
path = resolvePath(path)
|
path = resolvePath(path)
|
||||||
|
|
||||||
content, err := readStringFromFile(path)
|
content, err := readStringFromFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "failed to read file; error: " + err.Error()
|
msg := "failed to read file; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
result := map[string]string{
|
result := map[string]string{
|
||||||
"content": content,
|
"content": content,
|
||||||
"path": path,
|
"path": path,
|
||||||
@@ -472,10 +448,8 @@ func fileRead(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileWrite(args map[string]string) []byte {
|
func fileWrite(args map[string]string) []byte {
|
||||||
path, ok := args["path"]
|
path, ok := args["path"]
|
||||||
if !ok || path == "" {
|
if !ok || path == "" {
|
||||||
@@ -496,7 +470,6 @@ func fileWrite(args map[string]string) []byte {
|
|||||||
msg := "file written successfully at " + path
|
msg := "file written successfully at " + path
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileWriteAppend(args map[string]string) []byte {
|
func fileWriteAppend(args map[string]string) []byte {
|
||||||
path, ok := args["path"]
|
path, ok := args["path"]
|
||||||
if !ok || path == "" {
|
if !ok || path == "" {
|
||||||
@@ -517,7 +490,6 @@ func fileWriteAppend(args map[string]string) []byte {
|
|||||||
msg := "file written successfully at " + path
|
msg := "file written successfully at " + path
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileDelete(args map[string]string) []byte {
|
func fileDelete(args map[string]string) []byte {
|
||||||
path, ok := args["path"]
|
path, ok := args["path"]
|
||||||
if !ok || path == "" {
|
if !ok || path == "" {
|
||||||
@@ -525,19 +497,15 @@ func fileDelete(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
path = resolvePath(path)
|
path = resolvePath(path)
|
||||||
|
|
||||||
if err := removeFile(path); err != nil {
|
if err := removeFile(path); err != nil {
|
||||||
msg := "failed to delete file; error: " + err.Error()
|
msg := "failed to delete file; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := "file deleted successfully at " + path
|
msg := "file deleted successfully at " + path
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileMove(args map[string]string) []byte {
|
func fileMove(args map[string]string) []byte {
|
||||||
src, ok := args["src"]
|
src, ok := args["src"]
|
||||||
if !ok || src == "" {
|
if !ok || src == "" {
|
||||||
@@ -546,7 +514,6 @@ func fileMove(args map[string]string) []byte {
|
|||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
src = resolvePath(src)
|
src = resolvePath(src)
|
||||||
|
|
||||||
dst, ok := args["dst"]
|
dst, ok := args["dst"]
|
||||||
if !ok || dst == "" {
|
if !ok || dst == "" {
|
||||||
msg := "destination path not provided to file_move tool"
|
msg := "destination path not provided to file_move tool"
|
||||||
@@ -554,17 +521,14 @@ func fileMove(args map[string]string) []byte {
|
|||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
dst = resolvePath(dst)
|
dst = resolvePath(dst)
|
||||||
|
|
||||||
if err := moveFile(src, dst); err != nil {
|
if err := moveFile(src, dst); err != nil {
|
||||||
msg := "failed to move file; error: " + err.Error()
|
msg := "failed to move file; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := fmt.Sprintf("file moved successfully from %s to %s", src, dst)
|
msg := fmt.Sprintf("file moved successfully from %s to %s", src, dst)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileCopy(args map[string]string) []byte {
|
func fileCopy(args map[string]string) []byte {
|
||||||
src, ok := args["src"]
|
src, ok := args["src"]
|
||||||
if !ok || src == "" {
|
if !ok || src == "" {
|
||||||
@@ -573,7 +537,6 @@ func fileCopy(args map[string]string) []byte {
|
|||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
src = resolvePath(src)
|
src = resolvePath(src)
|
||||||
|
|
||||||
dst, ok := args["dst"]
|
dst, ok := args["dst"]
|
||||||
if !ok || dst == "" {
|
if !ok || dst == "" {
|
||||||
msg := "destination path not provided to file_copy tool"
|
msg := "destination path not provided to file_copy tool"
|
||||||
@@ -581,32 +544,26 @@ func fileCopy(args map[string]string) []byte {
|
|||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
dst = resolvePath(dst)
|
dst = resolvePath(dst)
|
||||||
|
|
||||||
if err := copyFile(src, dst); err != nil {
|
if err := copyFile(src, dst); err != nil {
|
||||||
msg := "failed to copy file; error: " + err.Error()
|
msg := "failed to copy file; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := fmt.Sprintf("file copied successfully from %s to %s", src, dst)
|
msg := fmt.Sprintf("file copied successfully from %s to %s", src, dst)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileList(args map[string]string) []byte {
|
func fileList(args map[string]string) []byte {
|
||||||
path, ok := args["path"]
|
path, ok := args["path"]
|
||||||
if !ok || path == "" {
|
if !ok || path == "" {
|
||||||
path = "." // default to current directory
|
path = "." // default to current directory
|
||||||
}
|
}
|
||||||
|
|
||||||
path = resolvePath(path)
|
path = resolvePath(path)
|
||||||
|
|
||||||
files, err := listDirectory(path)
|
files, err := listDirectory(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "failed to list directory; error: " + err.Error()
|
msg := "failed to list directory; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
result := map[string]interface{}{
|
result := map[string]interface{}{
|
||||||
"directory": path,
|
"directory": path,
|
||||||
"files": files,
|
"files": files,
|
||||||
@@ -617,19 +574,15 @@ func fileList(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions for file operations
|
// Helper functions for file operations
|
||||||
|
|
||||||
func resolvePath(p string) string {
|
func resolvePath(p string) string {
|
||||||
if filepath.IsAbs(p) {
|
if filepath.IsAbs(p) {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
return filepath.Join(cfg.FilePickerDir, p)
|
return filepath.Join(cfg.FilePickerDir, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func readStringFromFile(filename string) (string, error) {
|
func readStringFromFile(filename string) (string, error) {
|
||||||
data, err := os.ReadFile(filename)
|
data, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -637,26 +590,21 @@ func readStringFromFile(filename string) (string, error) {
|
|||||||
}
|
}
|
||||||
return string(data), nil
|
return string(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeStringToFile(filename string, data string) error {
|
func writeStringToFile(filename string, data string) error {
|
||||||
return os.WriteFile(filename, []byte(data), 0644)
|
return os.WriteFile(filename, []byte(data), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendStringToFile(filename string, data string) error {
|
func appendStringToFile(filename string, data string) error {
|
||||||
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
_, err = file.WriteString(data)
|
_, err = file.WriteString(data)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeFile(filename string) error {
|
func removeFile(filename string) error {
|
||||||
return os.Remove(filename)
|
return os.Remove(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
func moveFile(src, dst string) error {
|
func moveFile(src, dst string) error {
|
||||||
// First try with os.Rename (works within same filesystem)
|
// First try with os.Rename (works within same filesystem)
|
||||||
if err := os.Rename(src, dst); err == nil {
|
if err := os.Rename(src, dst); err == nil {
|
||||||
@@ -665,24 +613,20 @@ func moveFile(src, dst string) error {
|
|||||||
// If that fails (e.g., cross-filesystem), copy and delete
|
// If that fails (e.g., cross-filesystem), copy and delete
|
||||||
return copyAndRemove(src, dst)
|
return copyAndRemove(src, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFile(src, dst string) error {
|
func copyFile(src, dst string) error {
|
||||||
srcFile, err := os.Open(src)
|
srcFile, err := os.Open(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer srcFile.Close()
|
defer srcFile.Close()
|
||||||
|
|
||||||
dstFile, err := os.Create(dst)
|
dstFile, err := os.Create(dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer dstFile.Close()
|
defer dstFile.Close()
|
||||||
|
|
||||||
_, err = io.Copy(dstFile, srcFile)
|
_, err = io.Copy(dstFile, srcFile)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyAndRemove(src, dst string) error {
|
func copyAndRemove(src, dst string) error {
|
||||||
// Copy the file
|
// Copy the file
|
||||||
if err := copyFile(src, dst); err != nil {
|
if err := copyFile(src, dst); err != nil {
|
||||||
@@ -691,13 +635,11 @@ func copyAndRemove(src, dst string) error {
|
|||||||
// Remove the source file
|
// Remove the source file
|
||||||
return os.Remove(src)
|
return os.Remove(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
func listDirectory(path string) ([]string, error) {
|
func listDirectory(path string) ([]string, error) {
|
||||||
entries, err := os.ReadDir(path)
|
entries, err := os.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var files []string
|
var files []string
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
if entry.IsDir() {
|
if entry.IsDir() {
|
||||||
@@ -706,12 +648,9 @@ func listDirectory(path string) ([]string, error) {
|
|||||||
files = append(files, entry.Name())
|
files = append(files, entry.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command Execution Tool
|
// Command Execution Tool
|
||||||
|
|
||||||
func executeCommand(args map[string]string) []byte {
|
func executeCommand(args map[string]string) []byte {
|
||||||
command, ok := args["command"]
|
command, ok := args["command"]
|
||||||
if !ok || command == "" {
|
if !ok || command == "" {
|
||||||
@@ -719,7 +658,6 @@ func executeCommand(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get arguments - handle both single arg and multiple args
|
// Get arguments - handle both single arg and multiple args
|
||||||
var cmdArgs []string
|
var cmdArgs []string
|
||||||
if args["args"] != "" {
|
if args["args"] != "" {
|
||||||
@@ -738,52 +676,42 @@ func executeCommand(args map[string]string) []byte {
|
|||||||
argNum++
|
argNum++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isCommandAllowed(command, cmdArgs...) {
|
if !isCommandAllowed(command, cmdArgs...) {
|
||||||
msg := fmt.Sprintf("command '%s' is not allowed", command)
|
msg := fmt.Sprintf("command '%s' is not allowed", command)
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute with timeout for safety
|
// Execute with timeout for safety
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
cmd := exec.CommandContext(ctx, command, cmdArgs...)
|
cmd := exec.CommandContext(ctx, command, cmdArgs...)
|
||||||
|
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("command '%s' failed; error: %v; output: %s", command, err, string(output))
|
msg := fmt.Sprintf("command '%s' failed; error: %v; output: %s", command, err, string(output))
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if output is empty and return success message
|
// Check if output is empty and return success message
|
||||||
if len(output) == 0 {
|
if len(output) == 0 {
|
||||||
successMsg := fmt.Sprintf("command '%s %s' executed successfully and exited with code 0", command, strings.Join(cmdArgs, " "))
|
successMsg := fmt.Sprintf("command '%s %s' executed successfully and exited with code 0", command, strings.Join(cmdArgs, " "))
|
||||||
return []byte(successMsg)
|
return []byte(successMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions for command execution
|
// Helper functions for command execution
|
||||||
|
|
||||||
// Todo structure
|
// Todo structure
|
||||||
type TodoItem struct {
|
type TodoItem struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Task string `json:"task"`
|
Task string `json:"task"`
|
||||||
Status string `json:"status"` // "pending", "in_progress", "completed"
|
Status string `json:"status"` // "pending", "in_progress", "completed"
|
||||||
}
|
}
|
||||||
|
|
||||||
type TodoList struct {
|
type TodoList struct {
|
||||||
Items []TodoItem `json:"items"`
|
Items []TodoItem `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global todo list storage
|
// Global todo list storage
|
||||||
var globalTodoList = TodoList{
|
var globalTodoList = TodoList{
|
||||||
Items: []TodoItem{},
|
Items: []TodoItem{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo Management Tools
|
// Todo Management Tools
|
||||||
func todoCreate(args map[string]string) []byte {
|
func todoCreate(args map[string]string) []byte {
|
||||||
task, ok := args["task"]
|
task, ok := args["task"]
|
||||||
@@ -792,35 +720,28 @@ func todoCreate(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate simple ID
|
// Generate simple ID
|
||||||
id := fmt.Sprintf("todo_%d", len(globalTodoList.Items)+1)
|
id := fmt.Sprintf("todo_%d", len(globalTodoList.Items)+1)
|
||||||
|
|
||||||
newItem := TodoItem{
|
newItem := TodoItem{
|
||||||
ID: id,
|
ID: id,
|
||||||
Task: task,
|
Task: task,
|
||||||
Status: "pending",
|
Status: "pending",
|
||||||
}
|
}
|
||||||
|
|
||||||
globalTodoList.Items = append(globalTodoList.Items, newItem)
|
globalTodoList.Items = append(globalTodoList.Items, newItem)
|
||||||
|
|
||||||
result := map[string]string{
|
result := map[string]string{
|
||||||
"message": "todo created successfully",
|
"message": "todo created successfully",
|
||||||
"id": id,
|
"id": id,
|
||||||
"task": task,
|
"task": task,
|
||||||
"status": "pending",
|
"status": "pending",
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonResult, err := json.Marshal(result)
|
jsonResult, err := json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "failed to marshal result; error: " + err.Error()
|
msg := "failed to marshal result; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
|
|
||||||
func todoRead(args map[string]string) []byte {
|
func todoRead(args map[string]string) []byte {
|
||||||
id, ok := args["id"]
|
id, ok := args["id"]
|
||||||
if ok && id != "" {
|
if ok && id != "" {
|
||||||
@@ -851,7 +772,6 @@ func todoRead(args map[string]string) []byte {
|
|||||||
}
|
}
|
||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return all todos if no ID specified
|
// Return all todos if no ID specified
|
||||||
result := map[string]interface{}{
|
result := map[string]interface{}{
|
||||||
"todos": globalTodoList.Items,
|
"todos": globalTodoList.Items,
|
||||||
@@ -862,10 +782,8 @@ func todoRead(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
|
|
||||||
func todoUpdate(args map[string]string) []byte {
|
func todoUpdate(args map[string]string) []byte {
|
||||||
id, ok := args["id"]
|
id, ok := args["id"]
|
||||||
if !ok || id == "" {
|
if !ok || id == "" {
|
||||||
@@ -873,16 +791,13 @@ func todoUpdate(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
task, taskOk := args["task"]
|
task, taskOk := args["task"]
|
||||||
status, statusOk := args["status"]
|
status, statusOk := args["status"]
|
||||||
|
|
||||||
if !taskOk && !statusOk {
|
if !taskOk && !statusOk {
|
||||||
msg := "neither task nor status provided to todo_update tool"
|
msg := "neither task nor status provided to todo_update tool"
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find and update the todo
|
// Find and update the todo
|
||||||
for i, item := range globalTodoList.Items {
|
for i, item := range globalTodoList.Items {
|
||||||
if item.ID == id {
|
if item.ID == id {
|
||||||
@@ -906,23 +821,19 @@ func todoUpdate(args map[string]string) []byte {
|
|||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := map[string]string{
|
result := map[string]string{
|
||||||
"message": "todo updated successfully",
|
"message": "todo updated successfully",
|
||||||
"id": id,
|
"id": id,
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonResult, err := json.Marshal(result)
|
jsonResult, err := json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "failed to marshal result; error: " + err.Error()
|
msg := "failed to marshal result; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID not found
|
// ID not found
|
||||||
result := map[string]string{
|
result := map[string]string{
|
||||||
"error": fmt.Sprintf("todo with id %s not found", id),
|
"error": fmt.Sprintf("todo with id %s not found", id),
|
||||||
@@ -935,7 +846,6 @@ func todoUpdate(args map[string]string) []byte {
|
|||||||
}
|
}
|
||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
|
|
||||||
func todoDelete(args map[string]string) []byte {
|
func todoDelete(args map[string]string) []byte {
|
||||||
id, ok := args["id"]
|
id, ok := args["id"]
|
||||||
if !ok || id == "" {
|
if !ok || id == "" {
|
||||||
@@ -943,29 +853,24 @@ func todoDelete(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find and remove the todo
|
// Find and remove the todo
|
||||||
for i, item := range globalTodoList.Items {
|
for i, item := range globalTodoList.Items {
|
||||||
if item.ID == id {
|
if item.ID == id {
|
||||||
// Remove item from slice
|
// Remove item from slice
|
||||||
globalTodoList.Items = append(globalTodoList.Items[:i], globalTodoList.Items[i+1:]...)
|
globalTodoList.Items = append(globalTodoList.Items[:i], globalTodoList.Items[i+1:]...)
|
||||||
|
|
||||||
result := map[string]string{
|
result := map[string]string{
|
||||||
"message": "todo deleted successfully",
|
"message": "todo deleted successfully",
|
||||||
"id": id,
|
"id": id,
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonResult, err := json.Marshal(result)
|
jsonResult, err := json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "failed to marshal result; error: " + err.Error()
|
msg := "failed to marshal result; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID not found
|
// ID not found
|
||||||
result := map[string]string{
|
result := map[string]string{
|
||||||
"error": fmt.Sprintf("todo with id %s not found", id),
|
"error": fmt.Sprintf("todo with id %s not found", id),
|
||||||
@@ -978,7 +883,6 @@ func todoDelete(args map[string]string) []byte {
|
|||||||
}
|
}
|
||||||
return jsonResult
|
return jsonResult
|
||||||
}
|
}
|
||||||
|
|
||||||
var gitReadSubcommands = map[string]bool{
|
var gitReadSubcommands = map[string]bool{
|
||||||
"status": true,
|
"status": true,
|
||||||
"log": true,
|
"log": true,
|
||||||
@@ -990,7 +894,6 @@ var gitReadSubcommands = map[string]bool{
|
|||||||
"shortlog": true,
|
"shortlog": true,
|
||||||
"describe": true,
|
"describe": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func isCommandAllowed(command string, args ...string) bool {
|
func isCommandAllowed(command string, args ...string) bool {
|
||||||
allowedCommands := map[string]bool{
|
allowedCommands := map[string]bool{
|
||||||
"grep": true,
|
"grep": true,
|
||||||
@@ -1031,7 +934,6 @@ func isCommandAllowed(command string, args ...string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func summarizeChat(args map[string]string) []byte {
|
func summarizeChat(args map[string]string) []byte {
|
||||||
if len(chatBody.Messages) == 0 {
|
if len(chatBody.Messages) == 0 {
|
||||||
return []byte("No chat history to summarize.")
|
return []byte("No chat history to summarize.")
|
||||||
@@ -1040,9 +942,7 @@ func summarizeChat(args map[string]string) []byte {
|
|||||||
chatText := chatToText(chatBody.Messages, true) // include system and tool messages
|
chatText := chatToText(chatBody.Messages, true) // include system and tool messages
|
||||||
return []byte(chatText)
|
return []byte(chatText)
|
||||||
}
|
}
|
||||||
|
|
||||||
type fnSig func(map[string]string) []byte
|
type fnSig func(map[string]string) []byte
|
||||||
|
|
||||||
var fnMap = map[string]fnSig{
|
var fnMap = map[string]fnSig{
|
||||||
"recall": recall,
|
"recall": recall,
|
||||||
"recall_topics": recallTopics,
|
"recall_topics": recallTopics,
|
||||||
@@ -1067,7 +967,6 @@ var fnMap = map[string]fnSig{
|
|||||||
"todo_delete": todoDelete,
|
"todo_delete": todoDelete,
|
||||||
"summarize_chat": summarizeChat,
|
"summarize_chat": summarizeChat,
|
||||||
}
|
}
|
||||||
|
|
||||||
// callToolWithAgent calls the tool and applies any registered agent.
|
// callToolWithAgent calls the tool and applies any registered agent.
|
||||||
func callToolWithAgent(name string, args map[string]string) []byte {
|
func callToolWithAgent(name string, args map[string]string) []byte {
|
||||||
registerWebAgents()
|
registerWebAgents()
|
||||||
@@ -1081,7 +980,6 @@ func callToolWithAgent(name string, args map[string]string) []byte {
|
|||||||
}
|
}
|
||||||
return raw
|
return raw
|
||||||
}
|
}
|
||||||
|
|
||||||
// openai style def
|
// openai style def
|
||||||
var baseTools = []models.Tool{
|
var baseTools = []models.Tool{
|
||||||
// rag_search
|
// rag_search
|
||||||
@@ -1239,7 +1137,6 @@ var baseTools = []models.Tool{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// file_create
|
// file_create
|
||||||
models.Tool{
|
models.Tool{
|
||||||
Type: "function",
|
Type: "function",
|
||||||
@@ -1262,7 +1159,6 @@ var baseTools = []models.Tool{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// file_read
|
// file_read
|
||||||
models.Tool{
|
models.Tool{
|
||||||
Type: "function",
|
Type: "function",
|
||||||
@@ -1281,7 +1177,6 @@ var baseTools = []models.Tool{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// file_write
|
// file_write
|
||||||
models.Tool{
|
models.Tool{
|
||||||
Type: "function",
|
Type: "function",
|
||||||
@@ -1304,7 +1199,6 @@ var baseTools = []models.Tool{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// file_write_append
|
// file_write_append
|
||||||
models.Tool{
|
models.Tool{
|
||||||
Type: "function",
|
Type: "function",
|
||||||
@@ -1327,7 +1221,6 @@ var baseTools = []models.Tool{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// file_delete
|
// file_delete
|
||||||
models.Tool{
|
models.Tool{
|
||||||
Type: "function",
|
Type: "function",
|
||||||
@@ -1346,7 +1239,6 @@ var baseTools = []models.Tool{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// file_move
|
// file_move
|
||||||
models.Tool{
|
models.Tool{
|
||||||
Type: "function",
|
Type: "function",
|
||||||
@@ -1369,7 +1261,6 @@ var baseTools = []models.Tool{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// file_copy
|
// file_copy
|
||||||
models.Tool{
|
models.Tool{
|
||||||
Type: "function",
|
Type: "function",
|
||||||
@@ -1392,7 +1283,6 @@ var baseTools = []models.Tool{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// file_list
|
// file_list
|
||||||
models.Tool{
|
models.Tool{
|
||||||
Type: "function",
|
Type: "function",
|
||||||
@@ -1411,7 +1301,6 @@ var baseTools = []models.Tool{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// execute_command
|
// execute_command
|
||||||
models.Tool{
|
models.Tool{
|
||||||
Type: "function",
|
Type: "function",
|
||||||
|
|||||||
Reference in New Issue
Block a user