Files
Cyrene/backend/pkg/plugins/random/plugin.go
T
AskaEth 71f0a1abdb feat: Go模块路径迁移 + Docker生产部署适配 + ethend Docker兼容
- 所有Go模块路径从 github.com/yourname/cyrene-ai 迁移到 git.yeij.top/AskaEth/Cyrene
- 5个Go Dockerfile添加 GOPROXY=https://goproxy.cn,direct 解决国内构建问题
- ai-core go.mod 添加 pkg/plugins replace 指令
- Caddyfile 简化为 http:// 通配 + handle 保留 /api 前缀
- ethend Dockerfile 适配 (npm install + 仅 COPY package.json)
- ethend 新增 RUNNING_IN_DOCKER 环境变量,健康检查改用Docker服务名
- ethend 数据库状态检查支持Docker hostname (postgres/redis/qdrant/minio)
- process-manager 新增 CONTAINER_SVC_MAP + Docker模式自动检测
- 统一 docker-compose.dev.db.yml 卷名 (pg_data/redis_data/qdrant_data/minio_data)
- docker-compose.yml ethend服务挂载docker.sock + 端口变量化
- 清理 .env 统一后的残留文件与提示信息

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 13:43:22 +08:00

176 lines
4.9 KiB
Go

package random
import (
"context"
"crypto/rand"
"fmt"
"math/big"
mathrand "math/rand"
"strings"
"git.yeij.top/AskaEth/Cyrene/pkg/plugins/sdk"
)
type RandomPlugin struct{ sdk.BasePlugin }
func (p *RandomPlugin) Metadata() sdk.PluginMetadata {
return sdk.PluginMetadata{
Name: "random", DisplayName: "Random Generator", Version: "1.0.0",
Description: "Random generation: numbers, UUIDs, secure passwords, pick/shuffle",
Category: "utility", Author: sdk.PluginAuthor{Name: "Cyrene Team"},
}
}
func (p *RandomPlugin) Tools() []sdk.Tool { return []sdk.Tool{&RandomTool{}} }
type RandomTool struct{ sdk.BaseTool }
func (t *RandomTool) Definition() sdk.ToolDefinition {
return sdk.ToolDefinition{
ID: "random", Name: "random", DisplayName: "Random Generator",
Description: "Random generation. Random numbers, UUID v4, secure passwords, pick from list, shuffle list.",
Category: "utility", Complexity: sdk.ComplexitySimple,
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"action": map[string]interface{}{"type": "string", "enum": []string{"number", "uuid", "password", "pick", "shuffle"}},
"min": map[string]interface{}{"type": "number"},
"max": map[string]interface{}{"type": "number"},
"length": map[string]interface{}{"type": "number"},
"items": map[string]interface{}{"type": "array", "items": map[string]interface{}{"type": "string"}},
"count": map[string]interface{}{"type": "number"},
},
"required": []string{"action"},
},
}
}
func (t *RandomTool) Validate(args map[string]interface{}) error {
if _, ok := args["action"]; !ok {
return fmt.Errorf("missing required parameter: action")
}
return nil
}
func (t *RandomTool) Execute(_ context.Context, args map[string]interface{}) (*sdk.ToolResult, error) {
action, _ := args["action"].(string)
switch action {
case "number":
min := getIntArg(args, "min", 0)
max := getIntArg(args, "max", 100)
n, err := rand.Int(rand.Reader, big.NewInt(int64(max-min+1)))
if err != nil {
return &sdk.ToolResult{ToolName: "random", Success: false, Error: err.Error()}, nil
}
return &sdk.ToolResult{ToolName: "random", Success: true,
Output: fmt.Sprintf("%d", int(n.Int64())+min)}, nil
case "uuid":
uuid := make([]byte, 16)
rand.Read(uuid)
uuid[6] = (uuid[6] & 0x0f) | 0x40
uuid[8] = (uuid[8] & 0x3f) | 0x80
return &sdk.ToolResult{ToolName: "random", Success: true,
Output: fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])}, nil
case "password":
length := getIntArg(args, "length", 16)
if length < 4 {
length = 4
}
if length > 128 {
length = 128
}
upper := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lower := "abcdefghijklmnopqrstuvwxyz"
digits := "0123456789"
symbols := "!@#$%^&*()_+-=[]{}|;:,.<>?"
all := upper + lower + digits + symbols
bytes := make([]byte, length)
for i := range bytes {
idx, _ := rand.Int(rand.Reader, big.NewInt(int64(len(all))))
bytes[i] = all[idx.Int64()]
}
return &sdk.ToolResult{ToolName: "random", Success: true, Output: string(bytes)}, nil
case "pick":
items := getStringSliceArg(args, "items")
if len(items) == 0 {
return &sdk.ToolResult{ToolName: "random", Success: false, Error: "items list is empty"}, nil
}
count := getIntArg(args, "count", 1)
if count > len(items) {
count = len(items)
}
indices := shuffledIndices(len(items))
picked := make([]string, count)
for i := 0; i < count; i++ {
picked[i] = items[indices[i]]
}
return &sdk.ToolResult{ToolName: "random", Success: true, Output: strings.Join(picked, ", ")}, nil
case "shuffle":
items := getStringSliceArg(args, "items")
indices := shuffledIndices(len(items))
shuffled := make([]string, len(items))
for i, idx := range indices {
shuffled[i] = items[idx]
}
return &sdk.ToolResult{ToolName: "random", Success: true, Output: strings.Join(shuffled, ", ")}, nil
}
return &sdk.ToolResult{ToolName: "random", Success: false, Error: "unknown action: " + action}, nil
}
func getIntArg(args map[string]interface{}, key string, defaultVal int) int {
v, ok := args[key]
if !ok {
return defaultVal
}
switch n := v.(type) {
case float64:
return int(n)
case int:
return n
case int64:
return int(n)
}
return defaultVal
}
func getStringSliceArg(args map[string]interface{}, key string) []string {
v, ok := args[key]
if !ok {
return nil
}
switch s := v.(type) {
case []string:
return s
case []interface{}:
result := make([]string, len(s))
for i, item := range s {
result[i] = fmt.Sprint(item)
}
return result
}
return nil
}
func shuffledIndices(n int) []int {
indices := make([]int, n)
for i := range indices {
indices[i] = i
}
for i := n - 1; i > 0; i-- {
jBig, err := rand.Int(rand.Reader, big.NewInt(int64(i+1)))
if err != nil {
j := mathrand.Intn(i + 1)
indices[i], indices[j] = indices[j], indices[i]
continue
}
j := int(jBig.Int64())
indices[i], indices[j] = indices[j], indices[i]
}
return indices
}