test(agent): cover image fallback execution path for image candidates
This commit is contained in:
parent
89ff10ceb0
commit
fd40b3df17
1 changed files with 75 additions and 0 deletions
|
|
@ -91,6 +91,33 @@ func (r *recordingProvider) GetDefaultModel() string {
|
|||
return "mock-model"
|
||||
}
|
||||
|
||||
type imageFallbackProbeProvider struct {
|
||||
calls []string
|
||||
}
|
||||
|
||||
func (p *imageFallbackProbeProvider) Chat(
|
||||
ctx context.Context,
|
||||
messages []providers.Message,
|
||||
tools []providers.ToolDefinition,
|
||||
model string,
|
||||
opts map[string]any,
|
||||
) (*providers.LLMResponse, error) {
|
||||
p.calls = append(p.calls, model)
|
||||
if model == "gemini-2.5-flash-lite" {
|
||||
// This error is non-retriable in text fallback Execute(), but should still
|
||||
// fail over in ExecuteImage() which only treats image size/dimension as terminal.
|
||||
return nil, fmt.Errorf("string should match pattern")
|
||||
}
|
||||
return &providers.LLMResponse{
|
||||
Content: "image fallback ok",
|
||||
ToolCalls: []providers.ToolCall{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *imageFallbackProbeProvider) GetDefaultModel() string {
|
||||
return "image-fallback-probe"
|
||||
}
|
||||
|
||||
func newTestAgentLoop(
|
||||
t *testing.T,
|
||||
) (al *AgentLoop, cfg *config.Config, msgBus *bus.MessageBus, provider *mockProvider, cleanup func()) {
|
||||
|
|
@ -620,6 +647,54 @@ func TestRunAgentLoop_DoesNotUseImageModelWhenOnlyHistoryHasImages(t *testing.T)
|
|||
}
|
||||
}
|
||||
|
||||
func TestRunAgentLoop_UsesImageFallbackExecutionForImageCandidates(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
cfg := &config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
Workspace: tmpDir,
|
||||
ModelName: "text-main",
|
||||
ImageModel: "vision-main",
|
||||
ImageModelFallbacks: []string{"vision-backup"},
|
||||
MaxTokens: 4096,
|
||||
MaxToolIterations: 5,
|
||||
},
|
||||
},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "text-main", Model: "openai/gpt-5.4"},
|
||||
{ModelName: "vision-main", Model: "gemini/gemini-2.5-flash-lite"},
|
||||
{ModelName: "vision-backup", Model: "anthropic/claude-3-7-sonnet"},
|
||||
},
|
||||
}
|
||||
|
||||
msgBus := bus.NewMessageBus()
|
||||
provider := &imageFallbackProbeProvider{}
|
||||
al := NewAgentLoop(cfg, msgBus, provider)
|
||||
agent := al.registry.GetDefaultAgent()
|
||||
|
||||
resp, err := al.runAgentLoop(context.Background(), agent, processOptions{
|
||||
SessionKey: "image-fallback-session",
|
||||
Channel: "telegram",
|
||||
ChatID: "chat-1",
|
||||
UserMessage: "describe this image",
|
||||
Media: []string{"data:image/png;base64,AAAA"},
|
||||
DefaultResponse: "fallback",
|
||||
SendResponse: false,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("runAgentLoop returned error: %v", err)
|
||||
}
|
||||
if resp != "image fallback ok" {
|
||||
t.Fatalf("response = %q, want %q", resp, "image fallback ok")
|
||||
}
|
||||
if len(provider.calls) != 2 {
|
||||
t.Fatalf("provider calls = %d, want 2", len(provider.calls))
|
||||
}
|
||||
if provider.calls[0] != "gemini-2.5-flash-lite" || provider.calls[1] != "claude-3-7-sonnet" {
|
||||
t.Fatalf("provider calls = %v, want [gemini-2.5-flash-lite claude-3-7-sonnet]", provider.calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewAgentLoop_StateInitialized(t *testing.T) {
|
||||
// Create temp workspace
|
||||
tmpDir, err := os.MkdirTemp("", "agent-test-*")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue