v0.50.0 c4ec31f

resident_subagent_tools_test.go RawHistoryFolder

1package modes
2
3import (
4	"context"
5	"testing"
6
7	"github.com/bnema/zut/packages/agent/subagents"
8	"github.com/bnema/zut/packages/agent/tools"
9	"github.com/bnema/zut/packages/core"
10)
11
12// TestApplyAutoSubagentsToolReplacesOneFacadeEntry covers the interactive
13// refresh path: the previously installed facade is replaced by exactly one
14// entry whose non-nil fields are the currently granted actions, and unrelated
15// tools survive.
16func TestApplyAutoSubagentsToolReplacesOneFacadeEntry(t *testing.T) {
17	manager := subagents.NewResidentManager(t.TempDir(), nil)
18	t.Cleanup(func() { _ = manager.Close(context.Background()) })
19	preSeeded := &tools.SubagentTool{}
20	agent := core.NewAgent(nil, "model", "", core.Registry{
21		"read": &tools.GrepTool{},
22		// A previously installed facade, as a prior refresh would have left it.
23		"subagent": preSeeded,
24	})
25	allowed, resumeAllowed := true, true
26	interactive := NewInteractive(InteractiveConfig{
27		Agent:                          agent,
28		ResidentManager:                manager,
29		AutoSubagentsToolAllowed:       &allowed,
30		AutoSubagentsStatusToolAllowed: &allowed,
31		AutoSubagentsStopToolAllowed:   &allowed,
32		AutoSubagentsResumeToolAllowed: &resumeAllowed,
33		// Interrupt is left unset, so it follows the spawn grant.
34	})
35
36	interactive.applyAutoSubagentsTool()
37
38	assertFacade := func(wantResume bool) {
39		t.Helper()
40		snapshot := agent.ToolsSnapshot()
41		if _, ok := snapshot["read"]; !ok {
42			t.Fatal("interactive refresh dropped an unrelated tool")
43		}
44		found := 0
45		for name := range snapshot {
46			switch name {
47			case tools.SubagentToolName:
48				found++
49			case "subagent_spawn", "subagent_status", "subagent_stop", "subagent_resume":
50				t.Fatalf("legacy tool key %q is present", name)
51			}
52		}
53		if found != 1 {
54			t.Fatalf("registry has %d %q entries, want 1", found, tools.SubagentToolName)
55		}
56		facade, ok := snapshot[tools.SubagentToolName].(*tools.SubagentTool)
57		if !ok {
58			t.Fatalf("registry entry %q = %T, want *tools.SubagentTool", tools.SubagentToolName, snapshot[tools.SubagentToolName])
59		}
60		if facade == preSeeded {
61			t.Fatal("interactive refresh reused the pre-seeded facade instead of replacing it")
62		}
63		if facade.Spawn == nil || facade.Status == nil || facade.Stop == nil || facade.Interrupt == nil {
64			t.Fatalf("facade actions = spawn:%v status:%v stop:%v interrupt:%v", facade.Spawn != nil, facade.Status != nil, facade.Stop != nil, facade.Interrupt != nil)
65		}
66		if (facade.Resume != nil) != wantResume {
67			t.Fatalf("facade resume = %v, want %v", facade.Resume != nil, wantResume)
68		}
69	}
70
71	assertFacade(true)
72
73	// A later policy change must replace the installed facade, not merge or
74	// duplicate it.
75	resumeAllowed = false
76	interactive.applyAutoSubagentsTool()
77	assertFacade(false)
78}

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 477

↑↓ moveenter openesc close