Files
Cyrene/backend/tool-engine/internal/service/tool_service.go
T
AskaEth 78e3f450c2 feat: Round 5 - Memory Service, Tool Engine, Call Records, Thinking Logs
- Fix: Session history flash (race condition + WS guard)
- Fix: Chat background overlay + sidebar transparency
- Fix: IoT device control (Chinese action names, status field)
- Feat: Independent memory-service (port 8091, 13 endpoints)
- Feat: Independent tool-engine service (port 8092, 13 tools)
- Feat: Tool call logs with paginated DevTools panel
- Feat: Thinking log records with DevTools panel
- Feat: Future development roadmap document
- Chore: Updated .gitignore, go.work, DevTools config
- Chore: 5-service health check, project review docs
2026-05-18 20:05:14 +08:00

124 lines
3.2 KiB
Go

package service
import (
"context"
"fmt"
"log"
"github.com/yourname/cyrene-ai/tool-engine/internal/model"
"github.com/yourname/cyrene-ai/tool-engine/internal/tools"
)
// ToolService 工具执行引擎
type ToolService struct {
registry map[string]tools.Tool
}
// NewToolService 创建工具服务,注册所有工具
func NewToolService(iotClient tools.IoTClientInterface, dataDir string) *ToolService {
svc := &ToolService{
registry: make(map[string]tools.Tool),
}
// 注册所有 13 个工具
svc.Register(tools.NewCalculatorTool())
svc.Register(tools.NewDateTimeTool())
svc.Register(tools.NewTextTool())
svc.Register(tools.NewCryptoTool())
svc.Register(tools.NewRandomTool())
svc.Register(tools.NewMarkdownTool())
svc.Register(tools.NewJSONTool())
svc.Register(tools.NewFileTool(dataDir))
svc.Register(tools.NewHTTPTool())
svc.Register(tools.NewWebSearchTool())
svc.Register(tools.NewWebFetchTool())
// IoT 工具(需要 IoT 客户端)
if iotClient != nil {
svc.Register(tools.NewIoTQueryTool(iotClient))
svc.Register(tools.NewIoTControlTool(iotClient))
} else {
log.Println("[tool-service] IoT 客户端未配置,跳过 IoT 工具注册")
}
return svc
}
// Register 注册工具
func (s *ToolService) Register(tool tools.Tool) {
def := tool.Definition()
s.registry[def.Name] = tool
log.Printf("[tool-service] 已注册工具: %s", def.Name)
}
// ListTools 获取所有工具定义
func (s *ToolService) ListTools() []model.ToolDefinition {
defs := make([]model.ToolDefinition, 0, len(s.registry))
for _, tool := range s.registry {
defs = append(defs, tool.Definition())
}
return defs
}
// GetTool 获取单个工具定义
func (s *ToolService) GetTool(name string) (*model.ToolDefinition, bool) {
tool, ok := s.registry[name]
if !ok {
return nil, false
}
def := tool.Definition()
return &def, true
}
// Execute 执行单个工具
func (s *ToolService) Execute(ctx context.Context, name string, arguments map[string]interface{}) (*model.ToolResult, error) {
tool, ok := s.registry[name]
if !ok {
return &model.ToolResult{
Output: "",
Error: fmt.Sprintf("工具 %s 不存在", name),
}, nil
}
log.Printf("[tool-service] 执行工具: %s", name)
result, err := tool.Execute(ctx, arguments)
if err != nil {
log.Printf("[tool-service] 工具 %s 执行错误: %v", name, err)
return &model.ToolResult{
Output: "",
Error: fmt.Sprintf("执行工具 %s 失败: %v", name, err),
}, nil
}
if result.Error != "" {
log.Printf("[tool-service] 工具 %s 返回错误: %s", name, result.Error)
} else {
log.Printf("[tool-service] 工具 %s 执行成功", name)
}
return result, nil
}
// ExecuteBatch 批量执行工具调用
func (s *ToolService) ExecuteBatch(ctx context.Context, calls []model.ToolCall) *model.BatchExecuteResponse {
results := make([]model.ToolResult, 0, len(calls))
for _, call := range calls {
result, err := s.Execute(ctx, call.Name, call.Arguments)
if err != nil {
results = append(results, model.ToolResult{
ID: call.ID,
Output: "",
Error: err.Error(),
})
continue
}
result.ID = call.ID
results = append(results, *result)
}
return &model.BatchExecuteResponse{
Results: results,
}
}