Files
yhh a534ead0ab refactor(delegation): sub-agent orchestration leaves the agent package
The task tool, read-only tasks, fleets, parallel tasks, the sub-agent
store and records, profiles and the child's capability grant move from
internal/runtime/agent to internal/runtime/delegation. They are clients
of the agent: they build child agents and run them. The executor loop
now names none of them.

What the loop itself does for a child stays in agent. child_run.go holds
running an agent as a child and composing its answer and host receipts.
child_registry.go holds shaping the child's tool surface. Delegation uses
a small exported surface for these: AppendHostReceipts, AttachReviewReport,
CompleteSubtaskContract, ExpandToolPatterns, MaxToolOutputBytes,
NormalizeToolSchemas, SubagentImageNote, VisionRefFor, WithCallContext
and the host-receipt labels.

Tests followed the code. The ones that check the agent's own judgements
against the real delegation tools (batch skipping, the plan-mode barrier,
contract hints, delegation profiles across the proxy) run as agent_test
in the agent directory through export_test.go. The user-turn retention
test is split so each package pins its half. Test helpers used on both
sides are copied, since neither test binary may import the other. One
test more than before, from that split; none dropped.

Baseline: the moved files carry their debt unchanged under the new path,
and task.go gains the one import line the move costs (-allow-widen).
2026-09-23 22:36:35 -07:00

29 lines
962 B
Go

package agent
import (
"context"
"strings"
"testing"
)
// The delegate exists because something had to look at the picture. Left
// unsaid, it reads the path in its task and calls read_file — which reads text
// and refuses, so the whole delegation ends in an error about NUL bytes.
func TestSubagentIsToldTheImagesRideTheMessage(t *testing.T) {
bare := SubagentImageNote(context.Background())
if bare != "" {
t.Fatalf("a task with no attachment must carry no note, got %q", bare)
}
ctx := WithSubagentImageCandidates(context.Background(), []string{"data:image/png;base64,AAA", "data:image/png;base64,BBB"})
note := SubagentImageNote(ctx)
if !strings.Contains(note, "2 image(s)") {
t.Fatalf("note = %q, want the count", note)
}
for _, want := range []string{"attached to this message", "Never call read_file on an image", "hexdump"} {
if !strings.Contains(note, want) {
t.Fatalf("note = %q, want it to rule out %q", note, want)
}
}
}