v0.48.1 deaab59

interactive_completion_delivery_test.go RawHistoryFolder

1package modes
2
3import (
4	"context"
5	"encoding/json"
6	"strings"
7	"testing"
8	"time"
9
10	"github.com/bnema/zut/packages/agent/subagents"
11	"github.com/bnema/zut/packages/agent/tools"
12	"github.com/bnema/zut/packages/core"
13	"github.com/bnema/zut/packages/provider"
14)
15
16func TestInteractiveWaitReportAcceptance(t *testing.T) {
17	for _, reset := range []bool{false, true} {
18		name := "accepted"
19		if reset {
20			name = "cancelled tracking"
21		}
22		t.Run(name, func(t *testing.T) {
23			ctx, cancel := context.WithCancel(t.Context())
24			defer cancel()
25			ag := core.NewAgent(nil, "test", "", nil)
26			i := &Interactive{agent: ag, busy: true, runCtx: ctx}
27			release := i.beginCompletionDeliveryHold()
28			defer release()
29			manager := subagents.NewResidentManager(t.TempDir(), func(_ subagents.ResidentChildSpec, journal *subagents.ResidentJournal) (subagents.ResidentRuntime, error) {
30				return subagents.ResidentTurnRunner(func(context.Context, string) error {
31					if reset {
32						i.cancelCoordinator()
33					}
34					return journal.RecordAgentEvent(core.EvAssistantMessage{Message: provider.Message{Role: provider.RoleAssistant, Content: []provider.Content{provider.TextBlock{Text: "interactive report"}}}})
35				}), nil
36			})
37			t.Cleanup(func() { _ = manager.Close(context.Background()) })
38			manager.SetAcceptedObserver(func(spec subagents.ResidentChildSpec, turn, _ string) { i.TrackResidentSubagent(spec.ID, turn) })
39			manager.SetCompletionObserver(i.ReportResidentSubagent)
40			spawn := &tools.SubagentSpawnTool{
41				ResidentManager: manager, Enabled: func() bool { return true },
42				BuildResidentSpec: func(context.Context, tools.ResidentSpawnRequest) (subagents.ResidentChildSpec, error) {
43					return subagents.ResidentChildSpec{ID: "worker", SessionID: "session", Provider: "openai", Model: "test"}, nil
44				},
45			}
46			result, err := spawn.Execute(ctx, json.RawMessage(`{"task":"report","wait":5}`), nil)
47			if err != nil || result.IsError {
48				t.Fatalf("spawn = (%#v, %v)", result, err)
49			}
50			encoded, err := json.Marshal(result.Content)
51			if err != nil {
52				t.Fatal(err)
53			}
54			if strings.Contains(string(encoded), "interactive report") != reset {
55				t.Fatalf("reset=%t tool result=%s", reset, encoded)
56			}
57			if reset {
58				if strings.Contains(string(encoded), "host_update") || ag.QueuedMessageCount() != 0 {
59					t.Fatalf("rejected completion claimed host delivery: %s", encoded)
60				}
61				return
62			}
63			deadline := time.NewTimer(5 * time.Second)
64			defer deadline.Stop()
65			tick := time.NewTicker(time.Millisecond)
66			defer tick.Stop()
67			for {
68				queued := ag.PendingQueuedMessages()
69				if len(queued) != 0 {
70					if len(queued) != 1 || !queued[0].HostEvent || strings.Count(queued[0].Text, "interactive report") != 1 || !strings.Contains(queued[0].Text, "[auto-subagents update]") {
71						t.Fatalf("queued host report = %#v", queued)
72					}
73					return
74				}
75				select {
76				case <-deadline.C:
77					t.Fatal("accepted completion did not slide in")
78				case <-tick.C:
79				}
80			}
81		})
82	}
83}

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