v0.50.1 a637010

subagent_delivery_test.go RawHistoryFolder

1package agent
2
3import (
4	"context"
5	"encoding/json"
6	"net/http"
7	"net/http/httptest"
8	"strings"
9	"testing"
10
11	"github.com/bnema/zut/packages/agent/subagents"
12	"github.com/bnema/zut/packages/core"
13)
14
15func TestOrchestratedWaitDeliversReportOnlyThroughContinuation(t *testing.T) {
16	t.Setenv("ZUT_HOME", t.TempDir())
17	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
18		w.Header().Set("content-type", "text/event-stream")
19		writeOpenAIChunk(t, w, map[string]any{
20			"choices": []any{map[string]any{"index": 0, "delta": map[string]string{"content": "synthetic child report"}, "finish_reason": "stop"}},
21		})
22	}))
23	defer server.Close()
24	tracker := subagents.NewCompletionTracker()
25	args := Args{CWD: t.TempDir(), Provider: "openai", Model: "gpt-4o", APIKey: "synthetic", BaseURL: server.URL, NoContextFiles: true, NoSkill: true, NoLSP: true}
26	runtime := newOrchestratedRuntime(t.Context(), args, Resolved{CWD: args.CWD, Provider: args.Provider, Model: args.Model, BaseURL: args.BaseURL}, Config{}, tracker)
27	t.Cleanup(func() { _ = runtime.ResidentManager().Close(context.Background()) })
28	facade := runtime.InjectTools(core.Registry{})["subagent"]
29	if facade == nil {
30		t.Fatal("subagent tool unavailable")
31	}
32	result, err := facade.Execute(t.Context(), json.RawMessage(`{"action":"spawn","task":"return a report","wait":5}`), nil)
33	if err != nil || result.IsError {
34		t.Fatalf("spawn = (%#v, %v)", result, err)
35	}
36	encoded, err := json.Marshal(result.Content)
37	if err != nil {
38		t.Fatal(err)
39	}
40	if strings.Contains(string(encoded), "synthetic child report") || !strings.Contains(string(encoded), "host_update") {
41		t.Fatalf("tool report = %s", encoded)
42	}
43	calls := 0
44	got, err := runHeadlessContinuation(t.Context(), tracker, "initial", func(_ context.Context, prompt string) (string, error) {
45		calls++
46		if strings.Count(prompt, "[auto-subagents update]") != 1 || strings.Count(prompt, "synthetic child report") != 1 {
47			t.Errorf("continuation report = %q", prompt)
48		}
49		return "synthesis", nil
50	})
51	if err != nil || calls != 1 || got != "synthesis" {
52		t.Fatalf("continuation = (%q, %v), calls=%d", got, err, calls)
53	}
54}

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