first commit
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
package status
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/smallnest/pigo/internal/agentcore"
|
||||
"github.com/smallnest/pigo/internal/cli"
|
||||
"github.com/smallnest/pigo/internal/compaction"
|
||||
"github.com/smallnest/pigo/internal/runtime"
|
||||
)
|
||||
|
||||
func TestRunStatus(t *testing.T) {
|
||||
host := newFakeHost()
|
||||
host.live.Model = "test-model"
|
||||
host.live.ProviderName = "test-provider"
|
||||
host.live.BaseURL = "https://api.example.com"
|
||||
host.live.Protocol = "anthropic"
|
||||
host.live.ContextWindow = 128000
|
||||
|
||||
host.agentCtx.Messages = append(host.agentCtx.Messages,
|
||||
agentcore.UserMessage{RoleField: agentcore.RoleUser, Content: agentcore.ContentList{agentcore.NewTextContent("hello")}},
|
||||
)
|
||||
|
||||
var buf bytes.Buffer
|
||||
RunStatus(&buf, host)
|
||||
output := buf.String()
|
||||
|
||||
if !strings.Contains(output, "runtime config:") {
|
||||
t.Error("expected output to contain 'runtime config:'")
|
||||
}
|
||||
if !strings.Contains(output, "model: test-model") {
|
||||
t.Error("expected output to contain 'model: test-model'")
|
||||
}
|
||||
if !strings.Contains(output, "provider: test-provider") {
|
||||
t.Error("expected output to contain 'provider: test-provider'")
|
||||
}
|
||||
if !strings.Contains(output, "base URL: https://api.example.com") {
|
||||
t.Error("expected output to contain 'base URL: https://api.example.com'")
|
||||
}
|
||||
if !strings.Contains(output, "protocol: anthropic") {
|
||||
t.Error("expected output to contain 'protocol: anthropic'")
|
||||
}
|
||||
if !strings.Contains(output, "context window: 128000 tokens") {
|
||||
t.Error("expected output to contain 'context window: 128000 tokens'")
|
||||
}
|
||||
|
||||
if !strings.Contains(output, "context:") {
|
||||
t.Error("expected output to contain 'context:'")
|
||||
}
|
||||
if !strings.Contains(output, "current:") {
|
||||
t.Error("expected output to contain 'current:'")
|
||||
}
|
||||
if !strings.Contains(output, "utilization:") {
|
||||
t.Error("expected output to contain 'utilization:'")
|
||||
}
|
||||
if !strings.Contains(output, "compactions: 0") {
|
||||
t.Error("expected output to contain 'compactions: 0'")
|
||||
}
|
||||
if !strings.Contains(output, "before compact:") {
|
||||
t.Error("expected output to contain 'before compact:'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunStatusWithCompaction(t *testing.T) {
|
||||
host := newFakeHost()
|
||||
host.live.ContextWindow = 128000
|
||||
|
||||
host.agentCtx.Messages = append(host.agentCtx.Messages,
|
||||
agentcore.UserMessage{RoleField: agentcore.RoleUser, Content: agentcore.ContentList{agentcore.NewTextContent("hello")}},
|
||||
agentcore.CompactionMessage{Summary: "compacted history"},
|
||||
agentcore.UserMessage{RoleField: agentcore.RoleUser, Content: agentcore.ContentList{agentcore.NewTextContent("more")}},
|
||||
)
|
||||
|
||||
var buf bytes.Buffer
|
||||
RunStatus(&buf, host)
|
||||
output := buf.String()
|
||||
|
||||
if !strings.Contains(output, "compactions: 1") {
|
||||
t.Error("expected output to contain 'compactions: 1'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunStatusUnknownContextWindow(t *testing.T) {
|
||||
host := newFakeHost()
|
||||
host.live.ContextWindow = 0 // unknown
|
||||
|
||||
var buf bytes.Buffer
|
||||
RunStatus(&buf, host)
|
||||
output := buf.String()
|
||||
|
||||
if !strings.Contains(output, "context window: unknown") {
|
||||
t.Error("expected output to contain 'context window: unknown'")
|
||||
}
|
||||
if !strings.Contains(output, "auto-compaction disabled") {
|
||||
t.Error("expected output to contain 'auto-compaction disabled'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeforeCompactCalculation(t *testing.T) {
|
||||
reserve := compaction.DefaultCompactionSettings.ReserveTokens
|
||||
if reserve != 16384 {
|
||||
t.Errorf("expected reserve tokens to be 16384, got %d", reserve)
|
||||
}
|
||||
|
||||
contextWindow := 128000
|
||||
threshold := contextWindow - reserve
|
||||
if threshold != 128000-16384 {
|
||||
t.Errorf("expected threshold to be 128000-16384=%d, got %d", 128000-16384, threshold)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunStatusEnvAndCreds(t *testing.T) {
|
||||
host := newFakeHost()
|
||||
host.cwd = "/tmp/test-cwd"
|
||||
host.live.ProviderName = "test-provider"
|
||||
host.live.BaseURL = "https://api.example.com"
|
||||
|
||||
host.slash.AddSkill(runtime.SlashCommand{Name: "my-skill", Expand: func(string) string { return "" }})
|
||||
host.slash.AddPlugin(runtime.SlashCommand{Name: "my-plugin", Run: func(string) (string, string) { return "", "" }})
|
||||
|
||||
host.creds.SetOverride("test-provider", "sk-secretkey-wxyz")
|
||||
|
||||
var buf bytes.Buffer
|
||||
RunStatus(&buf, host)
|
||||
output := buf.String()
|
||||
|
||||
if !strings.Contains(output, "project & environment:") {
|
||||
t.Error("expected 'project & environment:' section")
|
||||
}
|
||||
if !strings.Contains(output, "cwd: /tmp/test-cwd") {
|
||||
t.Error("expected 'cwd: /tmp/test-cwd'")
|
||||
}
|
||||
if !strings.Contains(output, "trust: disabled") {
|
||||
t.Error("expected 'trust: disabled' when trust manager is nil")
|
||||
}
|
||||
if !strings.Contains(output, "skills: 1 (my-skill)") {
|
||||
t.Error("expected 'skills: 1 (my-skill)'")
|
||||
}
|
||||
if !strings.Contains(output, "plugins: 1 (my-plugin)") {
|
||||
t.Error("expected 'plugins: 1 (my-plugin)'")
|
||||
}
|
||||
|
||||
if !strings.Contains(output, "credentials & connectivity:") {
|
||||
t.Error("expected 'credentials & connectivity:' section")
|
||||
}
|
||||
if !strings.Contains(output, "api key: set") {
|
||||
t.Error("expected 'api key: set'")
|
||||
}
|
||||
if !strings.Contains(output, "••••wxyz") {
|
||||
t.Error("expected masked key '••••wxyz'")
|
||||
}
|
||||
if strings.Contains(output, "sk-secretkey-wxyz") {
|
||||
t.Error("full API key leaked into /status output")
|
||||
}
|
||||
if !strings.Contains(output, "endpoint: https://api.example.com") {
|
||||
t.Error("expected 'endpoint: https://api.example.com'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunStatusTelemetryNoData(t *testing.T) {
|
||||
host := newFakeHost()
|
||||
// host.telemetry is nil.
|
||||
|
||||
var buf bytes.Buffer
|
||||
RunStatus(&buf, host)
|
||||
output := buf.String()
|
||||
|
||||
if !strings.Contains(output, "telemetry:") {
|
||||
t.Error("expected 'telemetry:' section")
|
||||
}
|
||||
if n := strings.Count(output, "no telemetry yet"); n != 2 {
|
||||
t.Errorf("expected 2 'no telemetry yet' (cumulative + last run), got %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunStatusTelemetryPopulated(t *testing.T) {
|
||||
host := newFakeHost()
|
||||
host.live.ContextWindow = 128000
|
||||
|
||||
holder := cli.NewTelemetryHolder()
|
||||
holder.Fold(agentcore.TelemetryEvent{
|
||||
Turns: 3,
|
||||
TruncationCount: 1,
|
||||
CompactionCount: 0,
|
||||
ContextUtilization: 0.42,
|
||||
ContextTokens: 53760,
|
||||
ContextWindow: 128000,
|
||||
ToolDurationsMs: map[string]agentcore.ToolTiming{
|
||||
"bash": {Count: 2, TotalMs: 150},
|
||||
"read": {Count: 4, TotalMs: 80},
|
||||
},
|
||||
})
|
||||
host.telemetry = holder
|
||||
|
||||
var buf bytes.Buffer
|
||||
RunStatus(&buf, host)
|
||||
output := buf.String()
|
||||
|
||||
if strings.Contains(output, "no telemetry yet") {
|
||||
t.Error("did not expect 'no telemetry yet' when telemetry is populated")
|
||||
}
|
||||
if !strings.Contains(output, "since session start:") {
|
||||
t.Error("expected 'since session start:' cumulative block")
|
||||
}
|
||||
if !strings.Contains(output, "last run:") {
|
||||
t.Error("expected 'last run:' block")
|
||||
}
|
||||
if !strings.Contains(output, "turns: 3") {
|
||||
t.Error("expected 'turns: 3' (last run == cumulative after one run)")
|
||||
}
|
||||
if !strings.Contains(output, "bash") || !strings.Contains(output, "2 calls") || !strings.Contains(output, "150ms") {
|
||||
t.Error("expected bash tool row with '2 calls' / '150ms'")
|
||||
}
|
||||
if !strings.Contains(output, "utilization: 42%") {
|
||||
t.Error("expected 'utilization: 42%'")
|
||||
}
|
||||
|
||||
holder.Fold(agentcore.TelemetryEvent{
|
||||
Turns: 2,
|
||||
TruncationCount: 0,
|
||||
CompactionCount: 1,
|
||||
ContextUtilization: 0.5,
|
||||
ContextTokens: 64000,
|
||||
ContextWindow: 128000,
|
||||
ToolDurationsMs: map[string]agentcore.ToolTiming{
|
||||
"bash": {Count: 1, TotalMs: 40},
|
||||
},
|
||||
})
|
||||
buf.Reset()
|
||||
RunStatus(&buf, host)
|
||||
output = buf.String()
|
||||
if !strings.Contains(output, "turns: 5") {
|
||||
t.Error("expected cumulative 'turns: 5' after two runs")
|
||||
}
|
||||
if !strings.Contains(output, "turns: 2") {
|
||||
t.Error("expected last-run 'turns: 2' after two runs")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaskKey(t *testing.T) {
|
||||
cases := []struct{ in, want string }{
|
||||
{"sk-secretkey-wxyz", "••••wxyz"},
|
||||
{"abcd", "••••"}, // exactly 4 -> masked entirely
|
||||
{"ab", "••"},
|
||||
{"", ""},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := maskKey(c.in); got != c.want {
|
||||
t.Errorf("maskKey(%q) = %q, want %q", c.in, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user