mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-14 22:09:37 +08:00
feat: ship subagent runtime and remove autonomy/task legacy
This commit is contained in:
181
pkg/tools/tool_allowlist_groups.go
Normal file
181
pkg/tools/tool_allowlist_groups.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ToolAllowlistGroup struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Aliases []string `json:"aliases,omitempty"`
|
||||
Tools []string `json:"tools"`
|
||||
}
|
||||
|
||||
var defaultToolAllowlistGroups = []ToolAllowlistGroup{
|
||||
{
|
||||
Name: "files_read",
|
||||
Description: "Read-only workspace file tools",
|
||||
Aliases: []string{"file_read", "readonly_files"},
|
||||
Tools: []string{"read_file", "list_dir", "repo_map", "read"},
|
||||
},
|
||||
{
|
||||
Name: "files_write",
|
||||
Description: "Workspace file modification tools",
|
||||
Aliases: []string{"file_write"},
|
||||
Tools: []string{"write_file", "edit_file", "write", "edit"},
|
||||
},
|
||||
{
|
||||
Name: "memory_read",
|
||||
Description: "Read-only memory tools",
|
||||
Aliases: []string{"mem_read"},
|
||||
Tools: []string{"memory_search", "memory_get"},
|
||||
},
|
||||
{
|
||||
Name: "memory_write",
|
||||
Description: "Memory write tools",
|
||||
Aliases: []string{"mem_write"},
|
||||
Tools: []string{"memory_write"},
|
||||
},
|
||||
{
|
||||
Name: "memory_all",
|
||||
Description: "All memory tools",
|
||||
Aliases: []string{"memory"},
|
||||
Tools: []string{"memory_search", "memory_get", "memory_write"},
|
||||
},
|
||||
{
|
||||
Name: "pipeline",
|
||||
Description: "Pipeline orchestration tools",
|
||||
Aliases: []string{"pipelines"},
|
||||
Tools: []string{"pipeline_create", "pipeline_status", "pipeline_state_set", "pipeline_dispatch"},
|
||||
},
|
||||
{
|
||||
Name: "subagents",
|
||||
Description: "Subagent management tools",
|
||||
Aliases: []string{"subagent", "agent_runtime"},
|
||||
Tools: []string{"spawn", "subagents", "subagent_profile"},
|
||||
},
|
||||
}
|
||||
|
||||
func ToolAllowlistGroups() []ToolAllowlistGroup {
|
||||
out := make([]ToolAllowlistGroup, 0, len(defaultToolAllowlistGroups))
|
||||
for _, g := range defaultToolAllowlistGroups {
|
||||
item := ToolAllowlistGroup{
|
||||
Name: strings.ToLower(strings.TrimSpace(g.Name)),
|
||||
Description: strings.TrimSpace(g.Description),
|
||||
Aliases: normalizeAllowlistTokenList(g.Aliases),
|
||||
Tools: normalizeAllowlistTokenList(g.Tools),
|
||||
}
|
||||
if item.Name == "" {
|
||||
continue
|
||||
}
|
||||
out = append(out, item)
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
|
||||
return out
|
||||
}
|
||||
|
||||
func ExpandToolAllowlistEntries(entries []string) []string {
|
||||
if len(entries) == 0 {
|
||||
return nil
|
||||
}
|
||||
groups := ToolAllowlistGroups()
|
||||
resolved := make(map[string][]string, len(groups))
|
||||
for _, g := range groups {
|
||||
if g.Name != "" {
|
||||
resolved[g.Name] = g.Tools
|
||||
}
|
||||
for _, alias := range g.Aliases {
|
||||
resolved[alias] = g.Tools
|
||||
}
|
||||
}
|
||||
|
||||
out := map[string]struct{}{}
|
||||
for _, raw := range entries {
|
||||
token := normalizeAllowlistToken(raw)
|
||||
if token == "" {
|
||||
continue
|
||||
}
|
||||
if token == "*" || token == "all" {
|
||||
out[token] = struct{}{}
|
||||
continue
|
||||
}
|
||||
|
||||
if groupName, isGroupToken := parseAllowlistGroupToken(token); isGroupToken {
|
||||
if members, ok := resolved[groupName]; ok {
|
||||
for _, name := range members {
|
||||
out[name] = struct{}{}
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Keep unknown group token as-is to preserve user intent and avoid silent mutation.
|
||||
out[token] = struct{}{}
|
||||
continue
|
||||
}
|
||||
|
||||
if members, ok := resolved[token]; ok {
|
||||
for _, name := range members {
|
||||
out[name] = struct{}{}
|
||||
}
|
||||
continue
|
||||
}
|
||||
out[token] = struct{}{}
|
||||
}
|
||||
|
||||
if len(out) == 0 {
|
||||
return nil
|
||||
}
|
||||
result := make([]string, 0, len(out))
|
||||
for name := range out {
|
||||
result = append(result, name)
|
||||
}
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
|
||||
func parseAllowlistGroupToken(token string) (string, bool) {
|
||||
token = normalizeAllowlistToken(token)
|
||||
if token == "" {
|
||||
return "", false
|
||||
}
|
||||
if strings.HasPrefix(token, "group:") {
|
||||
v := normalizeAllowlistToken(strings.TrimPrefix(token, "group:"))
|
||||
if v != "" {
|
||||
return v, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
if strings.HasPrefix(token, "@") {
|
||||
v := normalizeAllowlistToken(strings.TrimPrefix(token, "@"))
|
||||
if v != "" {
|
||||
return v, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func normalizeAllowlistTokenList(in []string) []string {
|
||||
if len(in) == 0 {
|
||||
return nil
|
||||
}
|
||||
seen := map[string]struct{}{}
|
||||
out := make([]string, 0, len(in))
|
||||
for _, item := range in {
|
||||
v := normalizeAllowlistToken(item)
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[v]; ok {
|
||||
continue
|
||||
}
|
||||
seen[v] = struct{}{}
|
||||
out = append(out, v)
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
|
||||
func normalizeAllowlistToken(in string) string {
|
||||
return strings.ToLower(strings.TrimSpace(in))
|
||||
}
|
||||
Reference in New Issue
Block a user