mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-06-12 16:13:09 +08:00
add subagent all/# controls and session window filters
This commit is contained in:
@@ -93,6 +93,12 @@ func statusCmd() {
|
|||||||
if data, err := os.ReadFile(triggerStats); err == nil {
|
if data, err := os.ReadFile(triggerStats); err == nil {
|
||||||
fmt.Printf("Trigger Stats: %s\n", strings.TrimSpace(string(data)))
|
fmt.Printf("Trigger Stats: %s\n", strings.TrimSpace(string(data)))
|
||||||
}
|
}
|
||||||
|
if errs, err := collectRecentTriggerErrors(filepath.Join(workspace, "memory", "trigger-audit.jsonl"), 5); err == nil && len(errs) > 0 {
|
||||||
|
fmt.Println("Recent Trigger Errors:")
|
||||||
|
for _, e := range errs {
|
||||||
|
fmt.Printf(" - %s\n", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sessionsDir := filepath.Join(filepath.Dir(configPath), "sessions")
|
sessionsDir := filepath.Join(filepath.Dir(configPath), "sessions")
|
||||||
if kinds, err := collectSessionKindCounts(sessionsDir); err == nil && len(kinds) > 0 {
|
if kinds, err := collectSessionKindCounts(sessionsDir); err == nil && len(kinds) > 0 {
|
||||||
@@ -142,6 +148,40 @@ func collectSessionKindCounts(sessionsDir string) (map[string]int, error) {
|
|||||||
return counts, nil
|
return counts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func collectRecentTriggerErrors(path string, limit int) ([]string, error) {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
lines := strings.Split(strings.TrimSpace(string(data)), "\n")
|
||||||
|
if len(lines) == 1 && strings.TrimSpace(lines[0]) == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
out := make([]string, 0, limit)
|
||||||
|
for i := len(lines) - 1; i >= 0; i-- {
|
||||||
|
line := strings.TrimSpace(lines[i])
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var row struct {
|
||||||
|
Time string `json:"time"`
|
||||||
|
Trigger string `json:"trigger"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal([]byte(line), &row); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(row.Error) == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out = append(out, fmt.Sprintf("[%s/%s] %s", row.Time, row.Trigger, row.Error))
|
||||||
|
if len(out) >= limit {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func collectRecentSubagentSessions(sessionsDir string, limit int) ([]string, error) {
|
func collectRecentSubagentSessions(sessionsDir string, limit int) ([]string, error) {
|
||||||
entries, err := os.ReadDir(sessionsDir)
|
entries, err := os.ReadDir(sessionsDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ func (t *SessionsTool) Parameters() map[string]interface{} {
|
|||||||
"active_minutes": map[string]interface{}{"type": "integer", "description": "only sessions updated in recent N minutes (list action)"},
|
"active_minutes": map[string]interface{}{"type": "integer", "description": "only sessions updated in recent N minutes (list action)"},
|
||||||
"kinds": map[string]interface{}{"type": "array", "items": map[string]interface{}{"type": "string"}, "description": "optional session kinds filter for list"},
|
"kinds": map[string]interface{}{"type": "array", "items": map[string]interface{}{"type": "string"}, "description": "optional session kinds filter for list"},
|
||||||
"include_tools": map[string]interface{}{"type": "boolean", "description": "include tool role messages in history", "default": false},
|
"include_tools": map[string]interface{}{"type": "boolean", "description": "include tool role messages in history", "default": false},
|
||||||
|
"around": map[string]interface{}{"type": "integer", "description": "1-indexed message index center for history window"},
|
||||||
|
"before": map[string]interface{}{"type": "integer", "description": "1-indexed message index upper bound (exclusive)"},
|
||||||
|
"after": map[string]interface{}{"type": "integer", "description": "1-indexed message index lower bound (exclusive)"},
|
||||||
},
|
},
|
||||||
"required": []string{"action"},
|
"required": []string{"action"},
|
||||||
}
|
}
|
||||||
@@ -59,6 +62,18 @@ func (t *SessionsTool) Execute(ctx context.Context, args map[string]interface{})
|
|||||||
if v, ok := args["include_tools"].(bool); ok {
|
if v, ok := args["include_tools"].(bool); ok {
|
||||||
includeTools = v
|
includeTools = v
|
||||||
}
|
}
|
||||||
|
around := 0
|
||||||
|
if v, ok := args["around"].(float64); ok && int(v) > 0 {
|
||||||
|
around = int(v)
|
||||||
|
}
|
||||||
|
before := 0
|
||||||
|
if v, ok := args["before"].(float64); ok && int(v) > 0 {
|
||||||
|
before = int(v)
|
||||||
|
}
|
||||||
|
after := 0
|
||||||
|
if v, ok := args["after"].(float64); ok && int(v) > 0 {
|
||||||
|
after = int(v)
|
||||||
|
}
|
||||||
activeMinutes := 0
|
activeMinutes := 0
|
||||||
if v, ok := args["active_minutes"].(float64); ok && int(v) > 0 {
|
if v, ok := args["active_minutes"].(float64); ok && int(v) > 0 {
|
||||||
activeMinutes = int(v)
|
activeMinutes = int(v)
|
||||||
@@ -126,10 +141,57 @@ func (t *SessionsTool) Execute(ctx context.Context, args map[string]interface{})
|
|||||||
if key == "" {
|
if key == "" {
|
||||||
return "key is required for history", nil
|
return "key is required for history", nil
|
||||||
}
|
}
|
||||||
h := t.historyFn(key, limit*3)
|
h := t.historyFn(key, 0)
|
||||||
if len(h) == 0 {
|
if len(h) == 0 {
|
||||||
return "No history.", nil
|
return "No history.", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Window selectors are 1-indexed (human-friendly)
|
||||||
|
if around > 0 {
|
||||||
|
center := around - 1
|
||||||
|
if center < 0 {
|
||||||
|
center = 0
|
||||||
|
}
|
||||||
|
if center >= len(h) {
|
||||||
|
center = len(h) - 1
|
||||||
|
}
|
||||||
|
half := limit / 2
|
||||||
|
if half < 1 {
|
||||||
|
half = 1
|
||||||
|
}
|
||||||
|
start := center - half
|
||||||
|
if start < 0 {
|
||||||
|
start = 0
|
||||||
|
}
|
||||||
|
end := center + half + 1
|
||||||
|
if end > len(h) {
|
||||||
|
end = len(h)
|
||||||
|
}
|
||||||
|
h = h[start:end]
|
||||||
|
} else {
|
||||||
|
start := 0
|
||||||
|
end := len(h)
|
||||||
|
if after > 0 {
|
||||||
|
start = after
|
||||||
|
if start > len(h) {
|
||||||
|
start = len(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if before > 0 {
|
||||||
|
end = before - 1
|
||||||
|
if end < 0 {
|
||||||
|
end = 0
|
||||||
|
}
|
||||||
|
if end > len(h) {
|
||||||
|
end = len(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if start > end {
|
||||||
|
start = end
|
||||||
|
}
|
||||||
|
h = h[start:end]
|
||||||
|
}
|
||||||
|
|
||||||
if !includeTools {
|
if !includeTools {
|
||||||
filtered := make([]providers.Message, 0, len(h))
|
filtered := make([]providers.Message, 0, len(h))
|
||||||
for _, m := range h {
|
for _, m := range h {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func (t *SubagentsTool) Parameters() map[string]interface{} {
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": map[string]interface{}{
|
"properties": map[string]interface{}{
|
||||||
"action": map[string]interface{}{"type": "string", "description": "list|info|kill|steer|send|log"},
|
"action": map[string]interface{}{"type": "string", "description": "list|info|kill|steer|send|log"},
|
||||||
"id": map[string]interface{}{"type": "string", "description": "subagent id for info/kill/steer/send/log"},
|
"id": map[string]interface{}{"type": "string", "description": "subagent id/#index/all for info/kill/steer/send/log"},
|
||||||
"message": map[string]interface{}{"type": "string", "description": "steering message for steer/send action"},
|
"message": map[string]interface{}{"type": "string", "description": "steering message for steer/send action"},
|
||||||
},
|
},
|
||||||
"required": []string{"action"},
|
"required": []string{"action"},
|
||||||
@@ -70,6 +70,19 @@ func (t *SubagentsTool) Execute(ctx context.Context, args map[string]interface{}
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("ID: %s\nStatus: %s\nLabel: %s\nCreated: %d\nUpdated: %d\nSteering Count: %d\nTask: %s\nResult:\n%s", task.ID, task.Status, task.Label, task.Created, task.Updated, len(task.Steering), task.Task, task.Result), nil
|
return fmt.Sprintf("ID: %s\nStatus: %s\nLabel: %s\nCreated: %d\nUpdated: %d\nSteering Count: %d\nTask: %s\nResult:\n%s", task.ID, task.Status, task.Label, task.Created, task.Updated, len(task.Steering), task.Task, task.Result), nil
|
||||||
case "kill":
|
case "kill":
|
||||||
|
if strings.EqualFold(strings.TrimSpace(id), "all") {
|
||||||
|
tasks := t.manager.ListTasks()
|
||||||
|
if len(tasks) == 0 {
|
||||||
|
return "No subagents.", nil
|
||||||
|
}
|
||||||
|
killed := 0
|
||||||
|
for _, task := range tasks {
|
||||||
|
if t.manager.KillTask(task.ID) {
|
||||||
|
killed++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("subagent kill requested for %d tasks", killed), nil
|
||||||
|
}
|
||||||
resolvedID, err := t.resolveTaskID(id)
|
resolvedID, err := t.resolveTaskID(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.Error(), nil
|
return err.Error(), nil
|
||||||
|
|||||||
Reference in New Issue
Block a user