yao/agent/robot/cache/load.go
Max df5836d8cc Enhance Robot API with Bio Field and CRUD Operations
- Added a `Bio` field to the `Robot` structure, allowing for a description of the robot.
- Updated the `cleanupAPITestRobots` function to delete robots with member IDs starting with both "robot_api_" and "api_robot_".
- Implemented new API functions for creating, updating, and removing robots, ensuring proper validation and cache management.
- Enhanced request and response types in `api/types.go` to include the new `Bio` field.
- Added comprehensive tests for the new CRUD operations in `robot_test.go`, ensuring robust validation and error handling.
2026-01-22 11:50:25 +08:00

117 lines
2.7 KiB
Go

package cache
import (
"fmt"
"github.com/yaoapp/gou/model"
"github.com/yaoapp/kun/maps"
"github.com/yaoapp/yao/agent/robot/types"
)
// memberModel is the model name for member table
// Can be changed via SetMemberModel() during system initialization
var memberModel = "__yao.member"
// memberFields are the fields to select when loading robots
var memberFields = []interface{}{
"id",
"member_id",
"team_id",
"display_name",
"bio",
"system_prompt",
"robot_status",
"autonomous_mode",
"robot_config",
"robot_email",
}
// SetMemberModel sets the member model name
// Call this during system initialization to override the default
func SetMemberModel(model string) {
if model != "" {
memberModel = model
}
}
// Load loads all active robots from database with pagination
// Query: member_type='robot' AND autonomous_mode=true AND status='active'
func (c *Cache) Load(ctx *types.Context) error {
m := model.Select(memberModel)
// Clear existing cache first
c.mu.Lock()
c.robots = make(map[string]*types.Robot)
c.byTeam = make(map[string][]string)
c.mu.Unlock()
// Paginate to handle large number of robots
page := 1
pageSize := 100 // load 100 robots per page
totalLoaded := 0
for {
// Query with pagination
result, err := m.Paginate(model.QueryParam{
Select: memberFields,
Wheres: []model.QueryWhere{
{Column: "member_type", Value: "robot"},
{Column: "autonomous_mode", Value: true},
{Column: "status", Value: "active"},
},
}, page, pageSize)
if err != nil {
return fmt.Errorf("failed to load robots (page %d): %w", page, err)
}
// Extract records from pagination result
data, ok := result.Get("data").([]maps.MapStr)
if !ok || len(data) == 0 {
break
}
// Parse and add each robot
for _, record := range data {
robot, err := types.NewRobotFromMap(map[string]interface{}(record))
if err != nil {
// Log error but continue loading other robots
continue
}
c.Add(robot)
totalLoaded++
}
// Check if there are more pages
total, _ := result.Get("total").(int)
if totalLoaded >= total {
break
}
page++
}
return nil
}
// LoadByID loads a single robot from database by member ID
func (c *Cache) LoadByID(ctx *types.Context, memberID string) (*types.Robot, error) {
m := model.Select(memberModel)
records, err := m.Get(model.QueryParam{
Select: memberFields,
Wheres: []model.QueryWhere{
{Column: "member_id", Value: memberID},
{Column: "member_type", Value: "robot"},
},
Limit: 1,
})
if err != nil {
return nil, fmt.Errorf("failed to load robot %s: %w", memberID, err)
}
if len(records) == 0 {
return nil, types.ErrRobotNotFound
}
return types.NewRobotFromMap(map[string]interface{}(records[0]))
}