feat(tools/io): 内置 IO/网络工具(file(路径安全)/http(SSRF防护)/web-search/web-fetch/knowledge)+ 大小截断
This commit is contained in:
1 parent
488cf9c79c
commit
3ce9489f8e
17 files changed
+2223
No files matched your search
@@ -0,0 +1,99 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/config"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory"
|
||||
)
|
||||
|
||||
// stubRetriever is a fake KnowledgeRetriever for testing knowledge responses.
|
||||
type stubRetriever struct {
|
||||
results []memory.Result
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *stubRetriever) Retrieve(ctx context.Context, personaID, query string, topK int) ([]memory.Result, error) {
|
||||
_ = ctx
|
||||
return s.results, s.err
|
||||
}
|
||||
|
||||
// knowledgeToolForTest builds a tools set with opts and returns the knowledge
|
||||
// tool.
|
||||
func knowledgeToolForTest(t *testing.T, opts ...Option) *knowledgeTool {
|
||||
t.Helper()
|
||||
return findTool(t, buildTools(t, &config.Config{}, opts...), "knowledge").(*knowledgeTool)
|
||||
}
|
||||
|
||||
func TestKnowledge_NoKnowledgeBase(t *testing.T) {
|
||||
t.Parallel()
|
||||
kt := knowledgeToolForTest(t) // no retriever wired
|
||||
_, err := kt.Execute(context.Background(), map[string]any{"query": "cyrene"})
|
||||
if err == nil || !strings.Contains(err.Error(), "no knowledge base") {
|
||||
t.Fatalf("expected no-knowledge-base error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKnowledge_ReturnsResults(t *testing.T) {
|
||||
t.Parallel()
|
||||
sr := &stubRetriever{results: []memory.Result{
|
||||
{Item: memory.MemoryItem{ID: "1", Content: "Cyrene 是主人", Kind: memory.KindWorldEvent, Scope: memory.ScopeProject}, Score: 0.9},
|
||||
}}
|
||||
kt := knowledgeToolForTest(t, WithKnowledgeRetriever(sr))
|
||||
|
||||
got, err := kt.Execute(context.Background(), map[string]any{"query": "cyrene", "persona": "p1", "top_k": 5})
|
||||
if err != nil {
|
||||
t.Fatalf("Execute: %v", err)
|
||||
}
|
||||
m := got.(map[string]any)
|
||||
if m["count"].(int) != 1 {
|
||||
t.Fatalf("count = %v", m["count"])
|
||||
}
|
||||
results := m["results"].([]map[string]any)
|
||||
if results[0]["content"] != "Cyrene 是主人" {
|
||||
t.Fatalf("content = %v", results[0]["content"])
|
||||
}
|
||||
if results[0]["kind"] != "world_event" {
|
||||
t.Fatalf("kind = %v", results[0]["kind"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestKnowledge_EmptyResults(t *testing.T) {
|
||||
t.Parallel()
|
||||
kt := knowledgeToolForTest(t, WithKnowledgeRetriever(&stubRetriever{}))
|
||||
got, err := kt.Execute(context.Background(), map[string]any{"query": "nothing"})
|
||||
if err != nil {
|
||||
t.Fatalf("Execute: %v", err)
|
||||
}
|
||||
m := got.(map[string]any)
|
||||
if m["count"].(int) != 0 {
|
||||
t.Fatalf("count = %v", m["count"])
|
||||
}
|
||||
if m["note"] != "no relevant knowledge found" {
|
||||
t.Fatalf("note = %v", m["note"])
|
||||
}
|
||||
if _, ok := m["results"].([]map[string]any); !ok {
|
||||
t.Fatalf("results absent or wrong type: %T", m["results"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestKnowledge_RetrieverError(t *testing.T) {
|
||||
t.Parallel()
|
||||
kt := knowledgeToolForTest(t, WithKnowledgeRetriever(&stubRetriever{err: errors.New("boom")}))
|
||||
_, err := kt.Execute(context.Background(), map[string]any{"query": "x"})
|
||||
if err == nil || !strings.Contains(err.Error(), "retrieve") {
|
||||
t.Fatalf("expected retrieve error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKnowledge_MissingQuery(t *testing.T) {
|
||||
t.Parallel()
|
||||
kt := knowledgeToolForTest(t, WithKnowledgeRetriever(&stubRetriever{}))
|
||||
_, err := kt.Execute(context.Background(), map[string]any{})
|
||||
if err == nil || !strings.Contains(err.Error(), "query is required") {
|
||||
t.Fatalf("expected query-required error, got %v", err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user