Files
Ettore Di Giacinto 23c7064141 feat: enhance tool selection (#13)
* feat: enhance tool selection

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* try to adapt tests

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Make tests more stable

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Add autoplan test

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Don't load MCP prompts if we don't have any

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Reorder things

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* TEST

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Revert "TEST"

This reverts commit b08bbc56d5.

* TEST

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* TEST2

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Try to fix tests

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Add back guidelines

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* fixups

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Improve next action logic

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* tests

* tests2

* forcereasoning

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* maxiterations

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Fix tests

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Better error handling

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* test

* error handling

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Force text reply

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Two-step param generation approach

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Code cleanup

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Add a small note/comment

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Improve tests

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Small refinements

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

---------

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
2025-10-26 21:37:24 +01:00

109 lines
3.1 KiB
Go

package mock
import (
"context"
"fmt"
"runtime"
. "github.com/mudler/cogito"
"github.com/mudler/cogito/pkg/xlog"
"github.com/sashabaranov/go-openai"
)
// MockOpenAIClient implements the OpenAIClient for testing
type MockOpenAIClient struct {
AskResponses []Fragment
AskResponseIndex int
CreateChatCompletionResponses []openai.ChatCompletionResponse
CreateChatCompletionIndex int
AskError error
CreateChatCompletionError error
FragmentHistory []Fragment
}
func NewMockOpenAIClient() *MockOpenAIClient {
return &MockOpenAIClient{
AskResponses: []Fragment{},
CreateChatCompletionResponses: []openai.ChatCompletionResponse{},
}
}
func (m *MockOpenAIClient) Ask(ctx context.Context, f Fragment) (Fragment, error) {
m.FragmentHistory = append(m.FragmentHistory, f)
if m.AskError != nil {
return Fragment{}, m.AskError
}
if m.AskResponseIndex >= len(m.AskResponses) {
return Fragment{}, fmt.Errorf("no more Ask responses configured")
}
response := m.AskResponses[m.AskResponseIndex]
_, file, line, _ := runtime.Caller(1)
xlog.Info("Ask response", "response", response, "file", file, "line", line)
m.AskResponseIndex++
// Add the response to the fragment
response.Messages = append(f.Messages, response.Messages...)
response.ParentFragment = &f
return response, nil
}
func (m *MockOpenAIClient) CreateChatCompletion(ctx context.Context, request openai.ChatCompletionRequest) (openai.ChatCompletionResponse, error) {
if m.CreateChatCompletionError != nil {
return openai.ChatCompletionResponse{}, m.CreateChatCompletionError
}
if m.CreateChatCompletionIndex >= len(m.CreateChatCompletionResponses) {
return openai.ChatCompletionResponse{}, fmt.Errorf("no more CreateChatCompletion responses configured")
}
response := m.CreateChatCompletionResponses[m.CreateChatCompletionIndex]
m.CreateChatCompletionIndex++
xlog.Info("CreateChatCompletion response", "response", response)
return response, nil
}
// Helper methods for setting up mock responses
func (m *MockOpenAIClient) SetAskResponse(content string) {
fragment := NewEmptyFragment().AddMessage("assistant", content)
m.AskResponses = append(m.AskResponses, fragment)
}
func (m *MockOpenAIClient) SetAskError(err error) {
m.AskError = err
}
func (m *MockOpenAIClient) SetCreateChatCompletionResponse(response openai.ChatCompletionResponse) {
m.CreateChatCompletionResponses = append(m.CreateChatCompletionResponses, response)
}
func (m *MockOpenAIClient) AddCreateChatCompletionFunction(name, args string) {
m.SetCreateChatCompletionResponse(
openai.ChatCompletionResponse{
Choices: []openai.ChatCompletionChoice{
{
Message: openai.ChatCompletionMessage{
Role: "assistant",
ToolCalls: []openai.ToolCall{
{
Type: openai.ToolTypeFunction,
Function: openai.FunctionCall{
Name: name,
Arguments: args,
},
},
},
},
},
},
})
}
func (m *MockOpenAIClient) SetCreateChatCompletionError(err error) {
m.CreateChatCompletionError = err
}