package agent import ( "context" "encoding/json" "testing" "nub/internal/llm" "nub/internal/tool" ) // askRecordingTool prüft, dass env.Ask beim Tool ankommt und tatsächlich // l.AskUser ist, nicht irgendein Default. type askRecordingTool struct{} func (askRecordingTool) Name() string { return "echo" } func (askRecordingTool) Description() string { return "echoes input" } func (askRecordingTool) Schema() json.RawMessage { return json.RawMessage(`{"type":"object"}`) } func (askRecordingTool) Run(ctx context.Context, input json.RawMessage, env tool.Env) (tool.Result, error) { if env.Ask == nil { return tool.Result{ForModel: "no ask hook", IsError: true}, nil } answer, err := env.Ask(ctx, "which format?", []string{"json", "yaml"}) if err != nil { return tool.Result{ForModel: err.Error(), IsError: true}, nil } return tool.Result{ForModel: "got: " + answer}, nil } func TestRunTools_EnvAskIsWiredToLoopAskUser(t *testing.T) { provider := &fakeProvider{batches: [][]llm.Event{ toolCallEvents("call_1", "echo", `{}`), textEvents("done"), }} loop, reg := newTestLoop(provider) reg.Register(askRecordingTool{}) var gotQuestion string loop.AskUser = func(ctx context.Context, question string, options []string) (string, error) { gotQuestion = question return "json please", nil } events := runOneRound(t, loop) out := findToolCallOutput(events) if out == nil { t.Fatal("expected a ToolCallOutput event") } if out.Result.IsError { t.Fatalf("unexpected error: %s", out.Result.ForModel) } if out.Result.ForModel != "got: json please" { t.Errorf("ForModel = %q", out.Result.ForModel) } if gotQuestion != "which format?" { t.Errorf("question passed through = %q", gotQuestion) } } func TestRunTools_EnvAskNilWithoutLoopAskUser(t *testing.T) { provider := &fakeProvider{batches: [][]llm.Event{ toolCallEvents("call_1", "echo", `{}`), textEvents("done"), }} loop, reg := newTestLoop(provider) reg.Register(askRecordingTool{}) // loop.AskUser bleibt nil (Print-Modus-Fall). events := runOneRound(t, loop) out := findToolCallOutput(events) if out == nil { t.Fatal("expected a ToolCallOutput event") } if !out.Result.IsError || out.Result.ForModel != "no ask hook" { t.Errorf("expected the tool to observe env.Ask == nil, got: %+v", out.Result) } }