mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-15 01:37:31 +08:00
feat: ship subagent runtime and remove autonomy/task legacy
This commit is contained in:
123
pkg/tools/subagent_runtime_control_test.go
Normal file
123
pkg/tools/subagent_runtime_control_test.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSubagentSpawnEnforcesTaskQuota(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
workspace := t.TempDir()
|
||||
manager := NewSubagentManager(nil, workspace, nil, nil)
|
||||
manager.SetRunFunc(func(ctx context.Context, task *SubagentTask) (string, error) {
|
||||
return "ok", nil
|
||||
})
|
||||
store := manager.ProfileStore()
|
||||
if store == nil {
|
||||
t.Fatalf("expected profile store")
|
||||
}
|
||||
if _, err := store.Upsert(SubagentProfile{
|
||||
AgentID: "coder",
|
||||
MaxTaskChars: 8,
|
||||
}); err != nil {
|
||||
t.Fatalf("failed to create profile: %v", err)
|
||||
}
|
||||
|
||||
_, err := manager.Spawn(context.Background(), SubagentSpawnOptions{
|
||||
Task: "this task is too long",
|
||||
AgentID: "coder",
|
||||
OriginChannel: "cli",
|
||||
OriginChatID: "direct",
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatalf("expected max_task_chars quota to reject spawn")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubagentRunWithRetryEventuallySucceeds(t *testing.T) {
|
||||
workspace := t.TempDir()
|
||||
manager := NewSubagentManager(nil, workspace, nil, nil)
|
||||
attempts := 0
|
||||
manager.SetRunFunc(func(ctx context.Context, task *SubagentTask) (string, error) {
|
||||
attempts++
|
||||
if attempts == 1 {
|
||||
return "", errors.New("temporary failure")
|
||||
}
|
||||
return "retry success", nil
|
||||
})
|
||||
|
||||
_, err := manager.Spawn(context.Background(), SubagentSpawnOptions{
|
||||
Task: "retry task",
|
||||
AgentID: "coder",
|
||||
OriginChannel: "cli",
|
||||
OriginChatID: "direct",
|
||||
MaxRetries: 1,
|
||||
RetryBackoff: 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("spawn failed: %v", err)
|
||||
}
|
||||
|
||||
task := waitSubagentDone(t, manager, 4*time.Second)
|
||||
if task.Status != "completed" {
|
||||
t.Fatalf("expected completed task, got %s (%s)", task.Status, task.Result)
|
||||
}
|
||||
if task.RetryCount != 1 {
|
||||
t.Fatalf("expected retry_count=1, got %d", task.RetryCount)
|
||||
}
|
||||
if attempts < 2 {
|
||||
t.Fatalf("expected at least 2 attempts, got %d", attempts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubagentRunWithTimeoutFails(t *testing.T) {
|
||||
workspace := t.TempDir()
|
||||
manager := NewSubagentManager(nil, workspace, nil, nil)
|
||||
manager.SetRunFunc(func(ctx context.Context, task *SubagentTask) (string, error) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return "", ctx.Err()
|
||||
case <-time.After(2 * time.Second):
|
||||
return "unexpected", nil
|
||||
}
|
||||
})
|
||||
|
||||
_, err := manager.Spawn(context.Background(), SubagentSpawnOptions{
|
||||
Task: "timeout task",
|
||||
AgentID: "coder",
|
||||
OriginChannel: "cli",
|
||||
OriginChatID: "direct",
|
||||
TimeoutSec: 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("spawn failed: %v", err)
|
||||
}
|
||||
|
||||
task := waitSubagentDone(t, manager, 4*time.Second)
|
||||
if task.Status != "failed" {
|
||||
t.Fatalf("expected failed task on timeout, got %s", task.Status)
|
||||
}
|
||||
if task.RetryCount != 0 {
|
||||
t.Fatalf("expected retry_count=0, got %d", task.RetryCount)
|
||||
}
|
||||
}
|
||||
|
||||
func waitSubagentDone(t *testing.T, manager *SubagentManager, timeout time.Duration) *SubagentTask {
|
||||
t.Helper()
|
||||
deadline := time.Now().Add(timeout)
|
||||
for time.Now().Before(deadline) {
|
||||
tasks := manager.ListTasks()
|
||||
if len(tasks) > 0 {
|
||||
task := tasks[0]
|
||||
if task.Status != "running" {
|
||||
return task
|
||||
}
|
||||
}
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
}
|
||||
t.Fatalf("timeout waiting for subagent completion")
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user