Address #130 review: one toolCaller helper for the tool tests
Build image / build-and-push (push) Successful in 7s
Build image / build-and-push (push) Successful in 7s
The call/mustCall closures were copied between TestRecordKeepingTools and TestCatalogAndGardenTools; both now use a file-level toolCaller. The other notes are left as they are: the 'nothing to change' guard enumerates the args on purpose (it is the tool's own contract, next to the struct it checks), and wrapping a sentinel with %w is how every readable refusal in this package is built. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -123,6 +123,34 @@ func TestToolboxScenario(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// toolCaller returns the two ways a test drives a toolbox: call executes a
|
||||
// tool with JSON-encoded args and hands back the raw result (for asserting on
|
||||
// refusals), and mustCall fails the test on a tool error and decodes the
|
||||
// result into `into` when one is given.
|
||||
func toolCaller(t *testing.T, ctx context.Context, box *llm.Toolbox) (
|
||||
call func(name string, args any) llm.ToolResult,
|
||||
mustCall func(name string, args any, into any),
|
||||
) {
|
||||
t.Helper()
|
||||
call = func(name string, args any) llm.ToolResult {
|
||||
t.Helper()
|
||||
return box.Execute(ctx, llm.ToolCall{ID: "1", Name: name, Arguments: mustJSON(t, args)})
|
||||
}
|
||||
mustCall = func(name string, args any, into any) {
|
||||
t.Helper()
|
||||
res := call(name, args)
|
||||
if res.IsError {
|
||||
t.Fatalf("%s: %s", name, res.Content)
|
||||
}
|
||||
if into != nil {
|
||||
if err := json.Unmarshal([]byte(res.Content), into); err != nil {
|
||||
t.Fatalf("decode %s: %v (%s)", name, err, res.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
return call, mustCall
|
||||
}
|
||||
|
||||
func mustJSON(t *testing.T, v any) json.RawMessage {
|
||||
t.Helper()
|
||||
b, err := json.Marshal(v)
|
||||
@@ -750,22 +778,7 @@ func TestRecordKeepingTools(t *testing.T) {
|
||||
svc, owner := newAgentTestService(t)
|
||||
box := NewToolbox(svc, owner, "2026-08-23")
|
||||
|
||||
call := func(name string, args any) llm.ToolResult {
|
||||
t.Helper()
|
||||
return box.Execute(ctx, llm.ToolCall{ID: "1", Name: name, Arguments: mustJSON(t, args)})
|
||||
}
|
||||
mustCall := func(name string, args any, into any) {
|
||||
t.Helper()
|
||||
res := call(name, args)
|
||||
if res.IsError {
|
||||
t.Fatalf("%s: %s", name, res.Content)
|
||||
}
|
||||
if into != nil {
|
||||
if err := json.Unmarshal([]byte(res.Content), into); err != nil {
|
||||
t.Fatalf("decode %s: %v (%s)", name, err, res.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
call, mustCall := toolCaller(t, ctx, box)
|
||||
|
||||
g, err := svc.CreateGarden(ctx, owner, service.GardenInput{Name: "Home", WidthCM: 1200, HeightCM: 800, Notes: "Zone 6a."})
|
||||
if err != nil {
|
||||
@@ -940,22 +953,7 @@ func TestCatalogAndGardenTools(t *testing.T) {
|
||||
svc, owner := newAgentTestService(t)
|
||||
box := NewToolbox(svc, owner, "2026-08-23")
|
||||
|
||||
call := func(name string, args any) llm.ToolResult {
|
||||
t.Helper()
|
||||
return box.Execute(ctx, llm.ToolCall{ID: "1", Name: name, Arguments: mustJSON(t, args)})
|
||||
}
|
||||
mustCall := func(name string, args any, into any) {
|
||||
t.Helper()
|
||||
res := call(name, args)
|
||||
if res.IsError {
|
||||
t.Fatalf("%s: %s", name, res.Content)
|
||||
}
|
||||
if into != nil {
|
||||
if err := json.Unmarshal([]byte(res.Content), into); err != nil {
|
||||
t.Fatalf("decode %s: %v (%s)", name, err, res.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
call, mustCall := toolCaller(t, ctx, box)
|
||||
|
||||
// --- create_garden: defaults, then an imperial one with notes.
|
||||
var g domain.Garden
|
||||
|
||||
Reference in New Issue
Block a user