77 lines
2.6 KiB
Go
77 lines
2.6 KiB
Go
package agent
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"ollie/pkg/backend"
|
|
)
|
|
|
|
// TestTextToolCall_DetectedAsUnsupported verifies that when a model emits a tool
|
|
// call as plain text (no API-level tool calls) the loop returns a
|
|
// ToolUnsupportedError so freeloader can blacklist and cycle.
|
|
func TestTextToolCall_DetectedAsUnsupported(t *testing.T) {
|
|
be := defaultBE()
|
|
// Model responds with text that mimics a tool invocation instead of using
|
|
// the function-calling API.
|
|
be.respond = func(_ context.Context, _ []backend.Message, _ []backend.Tool, _ backend.GenerationParams) (<-chan backend.StreamEvent, error) {
|
|
return textStream(`execute_code: steps=[{code: "print('hi')"}]`), nil
|
|
}
|
|
|
|
c := newCore(t, be, nil)
|
|
c.cfg.Tools = []backend.Tool{{Name: "execute_code", Description: "run code"}}
|
|
|
|
evs := collectEvents(context.Background(), c, "run something")
|
|
|
|
errEvs := byRole(evs, "error")
|
|
if len(errEvs) == 0 {
|
|
t.Fatal("expected an error event; got none")
|
|
}
|
|
// The error must mention tool_unsupported behaviour (not a plain backend error).
|
|
if got := errEvs[0]; got == "" {
|
|
t.Error("error event content is empty")
|
|
}
|
|
}
|
|
|
|
// TestTextToolCall_NoFalsePositive verifies that a normal text response that
|
|
// does not contain a tool-call pattern is not mistakenly flagged.
|
|
func TestTextToolCall_NoFalsePositive(t *testing.T) {
|
|
be := defaultBE()
|
|
be.respond = func(_ context.Context, _ []backend.Message, _ []backend.Tool, _ backend.GenerationParams) (<-chan backend.StreamEvent, error) {
|
|
return textStream("Here is how execute_code works in general."), nil
|
|
}
|
|
|
|
c := newCore(t, be, nil)
|
|
c.cfg.Tools = []backend.Tool{{Name: "execute_code", Description: "run code"}}
|
|
|
|
evs := collectEvents(context.Background(), c, "explain tools")
|
|
|
|
errEvs := byRole(evs, "error")
|
|
if len(errEvs) != 0 {
|
|
t.Errorf("unexpected error events: %v", errEvs)
|
|
}
|
|
assistEvs := byRole(evs, "assistant")
|
|
if len(assistEvs) == 0 {
|
|
t.Error("expected assistant response; got none")
|
|
}
|
|
}
|
|
|
|
// TestTextToolCall_NoToolsConfigured verifies that when no tools are configured
|
|
// the detection does not fire (nothing to detect against).
|
|
func TestTextToolCall_NoToolsConfigured(t *testing.T) {
|
|
be := defaultBE()
|
|
be.respond = func(_ context.Context, _ []backend.Message, _ []backend.Tool, _ backend.GenerationParams) (<-chan backend.StreamEvent, error) {
|
|
return textStream(`execute_code: steps=[{code: "print('hi')"}]`), nil
|
|
}
|
|
|
|
c := newCore(t, be, nil)
|
|
// No tools configured.
|
|
|
|
evs := collectEvents(context.Background(), c, "run something")
|
|
|
|
errEvs := byRole(evs, "error")
|
|
if len(errEvs) != 0 {
|
|
t.Errorf("unexpected error with no tools configured: %v", errEvs)
|
|
}
|
|
}
|