1package fantasy
2
3import (
4 "context"
5 "fmt"
6 "testing"
7
8 "github.com/stretchr/testify/require"
9)
10
11// Example of a simple typed tool using the function approach
12type CalculatorInput struct {
13 Expression string `json:"expression" description:"Mathematical expression to evaluate"`
14}
15
16func TestTypedToolFuncExample(t *testing.T) {
17 // Create a typed tool using the function API
18 tool := NewAgentTool(
19 "calculator",
20 "Evaluates simple mathematical expressions",
21 func(ctx context.Context, input CalculatorInput, _ ToolCall) (ToolResponse, error) {
22 if input.Expression == "2+2" {
23 return NewTextResponse("4"), nil
24 }
25 return NewTextErrorResponse("unsupported expression"), nil
26 },
27 )
28
29 // Check the tool info
30 info := tool.Info()
31 require.Equal(t, "calculator", info.Name)
32 require.Len(t, info.Required, 1)
33 require.Equal(t, "expression", info.Required[0])
34
35 // Test execution
36 call := ToolCall{
37 ID: "test-1",
38 Name: "calculator",
39 Input: `{"expression": "2+2"}`,
40 }
41
42 result, err := tool.Run(context.Background(), call)
43 require.NoError(t, err)
44 require.Equal(t, "4", result.Content)
45 require.False(t, result.IsError)
46}
47
48func TestEnumToolExample(t *testing.T) {
49 type WeatherInput struct {
50 Location string `json:"location" description:"City name"`
51 Units string `json:"units" enum:"celsius,fahrenheit" description:"Temperature units"`
52 }
53
54 // Create a weather tool with enum support
55 tool := NewAgentTool(
56 "weather",
57 "Gets current weather for a location",
58 func(ctx context.Context, input WeatherInput, _ ToolCall) (ToolResponse, error) {
59 temp := "22°C"
60 if input.Units == "fahrenheit" {
61 temp = "72°F"
62 }
63 return NewTextResponse(fmt.Sprintf("Weather in %s: %s, sunny", input.Location, temp)), nil
64 },
65 )
66 // Check that the schema includes enum values
67 info := tool.Info()
68 unitsParam, ok := info.Parameters["units"].(map[string]any)
69 require.True(t, ok, "Expected units parameter to exist")
70 enumValues, ok := unitsParam["enum"].([]any)
71 require.True(t, ok)
72 require.Len(t, enumValues, 2)
73
74 // Test execution with enum value
75 call := ToolCall{
76 ID: "test-2",
77 Name: "weather",
78 Input: `{"location": "San Francisco", "units": "fahrenheit"}`,
79 }
80
81 result, err := tool.Run(context.Background(), call)
82 require.NoError(t, err)
83 require.Contains(t, result.Content, "San Francisco")
84 require.Contains(t, result.Content, "72°F")
85}
86
87func TestNewImageResponse(t *testing.T) {
88 imageData := []byte{0x89, 0x50, 0x4E, 0x47} // PNG header bytes
89 mediaType := "image/png"
90
91 resp := NewImageResponse(imageData, mediaType)
92
93 require.Equal(t, "image", resp.Type)
94 require.Equal(t, imageData, resp.Data)
95 require.Equal(t, mediaType, resp.MediaType)
96 require.False(t, resp.IsError)
97 require.Empty(t, resp.Content)
98}
99
100func TestNewMediaResponse(t *testing.T) {
101 audioData := []byte{0x52, 0x49, 0x46, 0x46} // RIFF header bytes
102 mediaType := "audio/wav"
103
104 resp := NewMediaResponse(audioData, mediaType)
105
106 require.Equal(t, "media", resp.Type)
107 require.Equal(t, audioData, resp.Data)
108 require.Equal(t, mediaType, resp.MediaType)
109 require.False(t, resp.IsError)
110 require.Empty(t, resp.Content)
111}