v0.15.0 6b178f8

model.go RawHistoryFolder

1package subagents
2
3import "time"
4
5// WebSearchPolicy is the capability decision propagated from a host agent to
6// a subagent worker. Inherit is used only before a supervisor resolves the
7// child decision; persisted and launched workers use Allow or Deny so their
8// capability does not change with a later config edit.
9type WebSearchPolicy uint8
10
11const (
12	WebSearchInherit WebSearchPolicy = iota
13	WebSearchDeny
14	WebSearchAllow
15)
16
17func (p WebSearchPolicy) Allows() bool { return p == WebSearchAllow }
18
19// childPolicy turns an unresolved or corrupt policy into an explicit deny.
20// Inherit is useful while a supervisor is resolving a spawn request, but it
21// must never cross the worker boundary because the child may otherwise apply
22// its own default-enabled configuration.
23func (p WebSearchPolicy) childPolicy() WebSearchPolicy {
24	if p == WebSearchAllow {
25		return WebSearchAllow
26	}
27	return WebSearchDeny
28}
29
30func (p WebSearchPolicy) String() string {
31	switch p {
32	case WebSearchAllow:
33		return "allow"
34	case WebSearchDeny:
35		return "deny"
36	case WebSearchInherit:
37		return "inherit"
38	default:
39		// Unknown values must not serialize as inherit: that would let a
40		// worker fall back to its own default and potentially regain access.
41		return "deny"
42	}
43}
44
45func childWebSearchPolicy(policy WebSearchPolicy, subagent string, toolNames []string) WebSearchPolicy {
46	if subagent != "" && NamedWebSearchPolicy(toolNames) != WebSearchAllow {
47		return WebSearchDeny
48	}
49	return policy.childPolicy()
50}
51
52// NamedWebSearchPolicy requires a named profile to opt in explicitly. An
53// omitted or empty profile tools list therefore denies web search without
54// changing the default selection of the other built-in tools.
55func NamedWebSearchPolicy(toolNames []string) WebSearchPolicy {
56	for _, name := range toolNames {
57		if name == "web_search" {
58			return WebSearchAllow
59		}
60	}
61	return WebSearchDeny
62}
63
64// ProcessState describes the lifetime of the supervised child process. It is
65// intentionally independent from TurnState: an alive worker can be idle
66// between turns, and a disconnected supervisor does not imply that the
67// worker's current turn failed.
68type ProcessState string
69
70const (
71	ProcessPending  ProcessState = "pending"
72	ProcessStarting ProcessState = "starting"
73	ProcessAlive    ProcessState = "alive"
74	ProcessDetached ProcessState = "detached"
75	ProcessExited   ProcessState = "exited"
76	ProcessKilled   ProcessState = "killed"
77)
78
79// TurnState describes one delegated prompt inside a worker process.
80type TurnState string
81
82const (
83	TurnIdle      TurnState = "idle"
84	TurnQueued    TurnState = "queued"
85	TurnRunning   TurnState = "running"
86	TurnCanceling TurnState = "canceling"
87	TurnSucceeded TurnState = "succeeded"
88	TurnFailed    TurnState = "failed"
89	TurnCanceled  TurnState = "canceled"
90)
91
92// WorkspaceMode selects how a child is allowed to access the repository.
93type WorkspaceMode string
94
95const (
96	WorkspaceShared   WorkspaceMode = "shared"
97	WorkspaceWorktree WorkspaceMode = "worktree"
98)
99
100// CaptureMode controls which durable worktree output is collected.
101type CaptureMode string
102
103const (
104	CapturePatch CaptureMode = "patch"
105	CaptureDiff  CaptureMode = "diff"
106)
107
108// SubagentPolicy contains manager-owned safety and resource limits. normalize
109// replaces zero MaxOutputBytes, MaxOutputLines, QueueTimeout, StartupTimeout,
110// and DefaultTimeout values with positive manager defaults. Other zero values
111// retain their documented semantics.
112type SubagentPolicy struct {
113	MaxConcurrent          int
114	MaxConcurrentPerParent int
115	QueueTimeout           time.Duration
116	StartupTimeout         time.Duration
117	DefaultTimeout         time.Duration
118	MaxTurns               int
119	MaxOutputBytes         int
120	MaxOutputLines         int
121	AllowedTools           []string
122	AllowedRoots           []string
123	HeartbeatInterval      time.Duration
124	IdleTimeout            time.Duration
125	ReconnectTimeout       time.Duration
126	CancelGracePeriod      time.Duration
127}
128
129func (p *SubagentPolicy) normalize() {
130	if p.MaxConcurrent <= 0 {
131		p.MaxConcurrent = 8
132	}
133	if p.MaxConcurrentPerParent <= 0 {
134		p.MaxConcurrentPerParent = 4
135	}
136	if p.QueueTimeout <= 0 {
137		p.QueueTimeout = 5 * time.Minute
138	}
139	if p.StartupTimeout <= 0 {
140		p.StartupTimeout = time.Minute
141	}
142	if p.DefaultTimeout <= 0 {
143		p.DefaultTimeout = 20 * time.Minute
144	}
145	if p.MaxTurns <= 0 {
146		p.MaxTurns = 3
147	}
148	if p.MaxOutputBytes <= 0 {
149		p.MaxOutputBytes = 500_000
150	}
151	if p.MaxOutputLines <= 0 {
152		p.MaxOutputLines = 5_000
153	}
154	if p.HeartbeatInterval <= 0 {
155		p.HeartbeatInterval = 10 * time.Second
156	}
157	if p.IdleTimeout <= 0 {
158		p.IdleTimeout = 7 * time.Minute
159	}
160	if p.ReconnectTimeout <= 0 {
161		p.ReconnectTimeout = 5 * time.Second
162	}
163	if p.CancelGracePeriod <= 0 {
164		p.CancelGracePeriod = 10 * time.Second
165	}
166}
167
168func (p SubagentPolicy) allowedTool(name string) bool {
169	if len(p.AllowedTools) == 0 {
170		return true
171	}
172	for _, allowed := range p.AllowedTools {
173		if allowed == name {
174			return true
175		}
176	}
177	return false
178}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close