diff options
| author | adamdottv <[email protected]> | 2025-05-15 12:44:16 -0500 |
|---|---|---|
| committer | adamdottv <[email protected]> | 2025-05-15 12:44:16 -0500 |
| commit | a65e593ab4f35e1a647832ba36be2c696e1f5165 (patch) | |
| tree | 38eed9994399e426a418c1e0424fe55133b648f4 /internal/llm/tools/batch_test.go | |
| parent | 5d9058eb74581091d84b2cd935927da636b3dd37 (diff) | |
| download | opencode-a65e593ab4f35e1a647832ba36be2c696e1f5165.tar.gz opencode-a65e593ab4f35e1a647832ba36be2c696e1f5165.zip | |
feat: batch tool
Diffstat (limited to 'internal/llm/tools/batch_test.go')
| -rw-r--r-- | internal/llm/tools/batch_test.go | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/internal/llm/tools/batch_test.go b/internal/llm/tools/batch_test.go new file mode 100644 index 000000000..1d5f05640 --- /dev/null +++ b/internal/llm/tools/batch_test.go @@ -0,0 +1,224 @@ +package tools + +import ( + "context" + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +// MockTool is a simple tool implementation for testing +type MockTool struct { + name string + description string + response ToolResponse + err error +} + +func (m *MockTool) Info() ToolInfo { + return ToolInfo{ + Name: m.name, + Description: m.description, + Parameters: map[string]any{}, + Required: []string{}, + } +} + +func (m *MockTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) { + return m.response, m.err +} + +func TestBatchTool(t *testing.T) { + t.Parallel() + + t.Run("successful batch execution", func(t *testing.T) { + t.Parallel() + + // Create mock tools + mockTools := map[string]BaseTool{ + "tool1": &MockTool{ + name: "tool1", + description: "Mock Tool 1", + response: NewTextResponse("Tool 1 Response"), + err: nil, + }, + "tool2": &MockTool{ + name: "tool2", + description: "Mock Tool 2", + response: NewTextResponse("Tool 2 Response"), + err: nil, + }, + } + + // Create batch tool + batchTool := NewBatchTool(mockTools) + + // Create batch call + input := `{ + "calls": [ + { + "name": "tool1", + "input": {} + }, + { + "name": "tool2", + "input": {} + } + ] + }` + + call := ToolCall{ + ID: "test-batch", + Name: "batch", + Input: input, + } + + // Execute batch + response, err := batchTool.Run(context.Background(), call) + + // Verify results + assert.NoError(t, err) + assert.Equal(t, ToolResponseTypeText, response.Type) + assert.False(t, response.IsError) + + // Parse the response + var batchResult BatchResult + err = json.Unmarshal([]byte(response.Content), &batchResult) + assert.NoError(t, err) + + // Verify batch results + assert.Len(t, batchResult.Results, 2) + assert.Empty(t, batchResult.Results[0].Error) + assert.Empty(t, batchResult.Results[1].Error) + assert.Empty(t, batchResult.Results[0].Separator) + assert.NotEmpty(t, batchResult.Results[1].Separator) + + // Verify individual results + var result1 ToolResponse + err = json.Unmarshal(batchResult.Results[0].Result, &result1) + assert.NoError(t, err) + assert.Equal(t, "Tool 1 Response", result1.Content) + + var result2 ToolResponse + err = json.Unmarshal(batchResult.Results[1].Result, &result2) + assert.NoError(t, err) + assert.Equal(t, "Tool 2 Response", result2.Content) + }) + + t.Run("tool not found", func(t *testing.T) { + t.Parallel() + + // Create mock tools + mockTools := map[string]BaseTool{ + "tool1": &MockTool{ + name: "tool1", + description: "Mock Tool 1", + response: NewTextResponse("Tool 1 Response"), + err: nil, + }, + } + + // Create batch tool + batchTool := NewBatchTool(mockTools) + + // Create batch call with non-existent tool + input := `{ + "calls": [ + { + "name": "tool1", + "input": {} + }, + { + "name": "nonexistent", + "input": {} + } + ] + }` + + call := ToolCall{ + ID: "test-batch", + Name: "batch", + Input: input, + } + + // Execute batch + response, err := batchTool.Run(context.Background(), call) + + // Verify results + assert.NoError(t, err) + assert.Equal(t, ToolResponseTypeText, response.Type) + assert.False(t, response.IsError) + + // Parse the response + var batchResult BatchResult + err = json.Unmarshal([]byte(response.Content), &batchResult) + assert.NoError(t, err) + + // Verify batch results + assert.Len(t, batchResult.Results, 2) + assert.Empty(t, batchResult.Results[0].Error) + assert.Contains(t, batchResult.Results[1].Error, "tool not found: nonexistent") + }) + + t.Run("empty calls", func(t *testing.T) { + t.Parallel() + + // Create batch tool with empty tools map + batchTool := NewBatchTool(map[string]BaseTool{}) + + // Create batch call with empty calls + input := `{ + "calls": [] + }` + + call := ToolCall{ + ID: "test-batch", + Name: "batch", + Input: input, + } + + // Execute batch + response, err := batchTool.Run(context.Background(), call) + + // Verify results + assert.NoError(t, err) + assert.Equal(t, ToolResponseTypeText, response.Type) + assert.True(t, response.IsError) + assert.Contains(t, response.Content, "no tool calls provided") + }) + + t.Run("invalid input", func(t *testing.T) { + t.Parallel() + + // Create batch tool with empty tools map + batchTool := NewBatchTool(map[string]BaseTool{}) + + // Create batch call with invalid JSON + input := `{ + "calls": [ + { + "name": "tool1", + "input": { + "invalid": json + } + } + ] + }` + + call := ToolCall{ + ID: "test-batch", + Name: "batch", + Input: input, + } + + // Execute batch + response, err := batchTool.Run(context.Background(), call) + + // Verify results + assert.NoError(t, err) + assert.Equal(t, ToolResponseTypeText, response.Type) + assert.True(t, response.IsError) + assert.Contains(t, response.Content, "error parsing parameters") + }) +}
\ No newline at end of file |
