model.go RawHistoryFolder
1package subagents
2
3import "time"
4
5// ProcessState describes the lifetime of the supervised child process. It is
6// intentionally independent from TurnState: an alive worker can be idle
7// between turns, and a disconnected supervisor does not imply that the
8// worker's current turn failed.
9type ProcessState string
10
11const (
12 ProcessPending ProcessState = "pending"
13 ProcessStarting ProcessState = "starting"
14 ProcessAlive ProcessState = "alive"
15 ProcessDetached ProcessState = "detached"
16 ProcessExited ProcessState = "exited"
17 ProcessKilled ProcessState = "killed"
18)
19
20// TurnState describes one delegated prompt inside a worker process.
21type TurnState string
22
23const (
24 TurnIdle TurnState = "idle"
25 TurnQueued TurnState = "queued"
26 TurnRunning TurnState = "running"
27 TurnCanceling TurnState = "canceling"
28 TurnSucceeded TurnState = "succeeded"
29 TurnFailed TurnState = "failed"
30 TurnCanceled TurnState = "canceled"
31)
32
33// WorkspaceMode selects how a child is allowed to access the repository.
34type WorkspaceMode string
35
36const (
37 WorkspaceShared WorkspaceMode = "shared"
38 WorkspaceWorktree WorkspaceMode = "worktree"
39)
40
41// CaptureMode controls which durable worktree output is collected.
42type CaptureMode string
43
44const (
45 CapturePatch CaptureMode = "patch"
46 CaptureDiff CaptureMode = "diff"
47)
48
49// SubagentPolicy contains manager-owned safety and resource limits. normalize
50// replaces zero MaxOutputBytes, MaxOutputLines, QueueTimeout, and
51// DefaultTimeout values with positive manager defaults. Other zero values retain
52// their documented semantics.
53type SubagentPolicy struct {
54 MaxConcurrent int
55 MaxConcurrentPerParent int
56 MaxTotalSpawned int
57 QueueTimeout time.Duration
58 DefaultTimeout time.Duration
59 MaxTurns int
60 MaxOutputBytes int
61 MaxOutputLines int
62 AllowedTools []string
63 AllowedRoots []string
64 HeartbeatInterval time.Duration
65 IdleTimeout time.Duration
66 ReconnectTimeout time.Duration
67 CancelGracePeriod time.Duration
68}
69
70func (p *SubagentPolicy) normalize() {
71 if p.MaxConcurrent <= 0 {
72 p.MaxConcurrent = 8
73 }
74 if p.MaxConcurrentPerParent <= 0 {
75 p.MaxConcurrentPerParent = 4
76 }
77 if p.MaxTotalSpawned <= 0 {
78 p.MaxTotalSpawned = 32
79 }
80 if p.QueueTimeout <= 0 {
81 p.QueueTimeout = 30 * time.Minute
82 }
83 if p.DefaultTimeout <= 0 {
84 p.DefaultTimeout = 20 * time.Minute
85 }
86 if p.MaxTurns <= 0 {
87 p.MaxTurns = 3
88 }
89 if p.MaxOutputBytes <= 0 {
90 p.MaxOutputBytes = 500_000
91 }
92 if p.MaxOutputLines <= 0 {
93 p.MaxOutputLines = 5_000
94 }
95 if p.HeartbeatInterval <= 0 {
96 p.HeartbeatInterval = 10 * time.Second
97 }
98 if p.IdleTimeout <= 0 {
99 p.IdleTimeout = 7 * time.Minute
100 }
101 if p.ReconnectTimeout <= 0 {
102 p.ReconnectTimeout = 5 * time.Second
103 }
104 if p.CancelGracePeriod <= 0 {
105 p.CancelGracePeriod = 10 * time.Second
106 }
107}
108
109func (p SubagentPolicy) allowedTool(name string) bool {
110 if len(p.AllowedTools) == 0 {
111 return true
112 }
113 for _, allowed := range p.AllowedTools {
114 if allowed == name {
115 return true
116 }
117 }
118 return false
119}