142 lines
4.0 KiB
Go
142 lines
4.0 KiB
Go
// Tests for the /goal command's pure helpers: goalFollowUpDecision's branch
|
|
// logic (terminal states, token budget, turn cap, no-progress guard),
|
|
// parseGoalObjective / parseTokenBudget flag parsing, and goalTurnActivity's
|
|
// token/tool accounting.
|
|
package goal
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/smallnest/pigo/internal/agentcore"
|
|
"github.com/smallnest/pigo/internal/agenttool"
|
|
)
|
|
|
|
func TestGoalFollowUpDecision(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
snap agenttool.GoalSnapshot
|
|
wantCont bool
|
|
wantTerm agenttool.GoalStatus
|
|
}{
|
|
{
|
|
name: "active continues",
|
|
snap: agenttool.GoalSnapshot{Status: agenttool.GoalActive, Iterations: 1},
|
|
wantCont: true,
|
|
wantTerm: agenttool.GoalIdle,
|
|
},
|
|
{
|
|
name: "complete stops",
|
|
snap: agenttool.GoalSnapshot{Status: agenttool.GoalComplete},
|
|
wantCont: false,
|
|
wantTerm: agenttool.GoalIdle,
|
|
},
|
|
{
|
|
name: "blocked stops",
|
|
snap: agenttool.GoalSnapshot{Status: agenttool.GoalBlocked},
|
|
wantCont: false,
|
|
wantTerm: agenttool.GoalIdle,
|
|
},
|
|
{
|
|
name: "budget exhausted",
|
|
snap: agenttool.GoalSnapshot{Status: agenttool.GoalActive, TokenBudget: 100, TokensUsed: 100},
|
|
wantCont: false,
|
|
wantTerm: agenttool.GoalBudgetLimited,
|
|
},
|
|
{
|
|
name: "budget under limit continues",
|
|
snap: agenttool.GoalSnapshot{Status: agenttool.GoalActive, TokenBudget: 100, TokensUsed: 50},
|
|
wantCont: true,
|
|
wantTerm: agenttool.GoalIdle,
|
|
},
|
|
{
|
|
name: "turn cap",
|
|
snap: agenttool.GoalSnapshot{Status: agenttool.GoalActive, Iterations: goalMaxAutomaticTurns},
|
|
wantCont: false,
|
|
wantTerm: agenttool.GoalPaused,
|
|
},
|
|
{
|
|
name: "no progress guard",
|
|
snap: agenttool.GoalSnapshot{Status: agenttool.GoalActive, NoProgress: goalMaxNoProgress},
|
|
wantCont: false,
|
|
wantTerm: agenttool.GoalPaused,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
cont, term := goalFollowUpDecision(tt.snap)
|
|
if cont != tt.wantCont {
|
|
t.Errorf("cont = %v, want %v", cont, tt.wantCont)
|
|
}
|
|
if term != tt.wantTerm {
|
|
t.Errorf("terminal = %q, want %q", term, tt.wantTerm)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseGoalObjective(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args string
|
|
wantObj string
|
|
wantBud int
|
|
wantErr bool
|
|
}{
|
|
{name: "no flag", args: "create hello.txt", wantObj: "create hello.txt", wantBud: 0},
|
|
{name: "tokens k", args: "--tokens 100k build the thing", wantObj: "build the thing", wantBud: 100000},
|
|
{name: "tokens m", args: "--tokens 1m do it", wantObj: "do it", wantBud: 1000000},
|
|
{name: "tokens bare", args: "--tokens 5000 go", wantObj: "go", wantBud: 5000},
|
|
{name: "flag only no objective", args: "--tokens 50k", wantObj: "", wantBud: 50000},
|
|
{name: "bad value", args: "--tokens abc do it", wantErr: true},
|
|
{name: "zero value", args: "--tokens 0 do it", wantErr: true},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
obj, bud, err := parseGoalObjective(tt.args)
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Fatalf("expected error, got obj=%q bud=%d", obj, bud)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if obj != tt.wantObj {
|
|
t.Errorf("objective = %q, want %q", obj, tt.wantObj)
|
|
}
|
|
if bud != tt.wantBud {
|
|
t.Errorf("budget = %d, want %d", bud, tt.wantBud)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGoalTurnActivity(t *testing.T) {
|
|
tail := []agentcore.AgentMessage{
|
|
agentcore.AssistantMessage{
|
|
RoleField: agentcore.RoleAssistant,
|
|
Usage: &agentcore.Usage{OutputTokens: 40},
|
|
},
|
|
agentcore.AssistantMessage{
|
|
RoleField: agentcore.RoleAssistant,
|
|
Usage: &agentcore.Usage{OutputTokens: 60},
|
|
},
|
|
}
|
|
tokens, hadTool := goalTurnActivity(tail)
|
|
if tokens != 100 {
|
|
t.Errorf("tokens = %d, want 100", tokens)
|
|
}
|
|
if hadTool {
|
|
t.Error("hadTool = true, want false (no tool calls or results)")
|
|
}
|
|
|
|
withTool := []agentcore.AgentMessage{
|
|
agentcore.ToolResultMessage{ToolName: "bash"},
|
|
}
|
|
_, hadTool = goalTurnActivity(withTool)
|
|
if !hadTool {
|
|
t.Error("hadTool = false, want true (tool result present)")
|
|
}
|
|
}
|