Files
Agent-System-Backend/internal/server/work_checkpoint_eval_budget_test.go
T
weichen 583c074aa4
ci / vet-and-test (pull_request) Successful in 50s
Close U3 review gaps before provider continuation
Why: Missing Usage must stop a paid sequence before a tool terminal is executable; exact attachment names and host-owned choices must also remain reliable.

Evidence: Each reported behavior had a failing regression before its fix. Full Backend vet/Go tests, live-tag budget tests, ten race replays, and six task-owned HTTP/Playwright scenarios passed with the aligned Agent-Native and Agent-Squad pins.

Impact: Evaluation terminal accounting becomes durable before delivery; material fallback matches bounded filenames; ready choices use host options without redundant model fields. No new model calls or budget authorization.

Refs: U3 r0.4 independent review Critical 1 and Important 3-4
2026-10-14 03:57:33 +00:00

530 lines
22 KiB
Go

//go:build live
package server
import (
bruntime "agent-system-backend/internal/runtime"
"agent-system-backend/internal/store"
core "agent-system-core"
"context"
"database/sql"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"sync/atomic"
"testing"
"time"
agentllm "agent-native/runtime/llm"
)
func TestEvaluationStopsAfterMalformedToolTerminal(t *testing.T) {
t.Setenv("WORK_CHECKPOINT_REMAINING_TOKENS", "60000")
for _, tc := range []struct {
name, arguments, trailer string
complete bool
argumentsValid bool
}{
{"invalid-json", `{"findings":`, "data: [DONE]\n\n", true, false},
{"missing-done", `{}`, "", false, true},
} {
t.Run(tc.name, func(t *testing.T) {
var providerCalls atomic.Int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
providerCalls.Add(1)
w.Header().Set("Content-Type", "text/event-stream")
args, _ := json.Marshal(tc.arguments)
fmt.Fprintf(w, "data: {\"choices\":[{\"delta\":{\"tool_calls\":[{\"index\":0,\"id\":\"call_1\",\"function\":{\"name\":\"publish_work_checkpoint\",\"arguments\":%s}}]}}]}\n\n", args)
fmt.Fprint(w, "data: {\"choices\":[{\"delta\":{},\"finish_reason\":\"tool_calls\"}],\"usage\":{\"prompt_tokens\":12,\"completion_tokens\":5,\"total_tokens\":17}}\n\n")
fmt.Fprint(w, tc.trailer)
}))
defer srv.Close()
dir, _ := newEvaluationEventStore(t)
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
var terminal agentllm.Event
for event := range stream(evalTestContext(t), "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
if event.Kind == agentllm.KindMessageEnd {
terminal = event
}
}
if terminal.Kind != agentllm.KindMessageEnd || terminal.Err == nil || terminal.Usage.TotalTokens != 17 ||
terminal.StreamComplete != tc.complete || len(terminal.Message.ToolCalls) != 0 {
t.Fatalf("unsafe provider terminal: %#v", terminal)
}
blocked := false
otherRun := bruntime.WithProviderRunID(context.Background(), t.Name()+"-other-run")
for event := range stream(otherRun, "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
blocked = blocked || event.Kind == agentllm.KindError
}
if !blocked || providerCalls.Load() != 1 {
t.Fatalf("terminal failure allowed another provider call: blocked=%v calls=%d", blocked, providerCalls.Load())
}
raw, err := os.ReadFile(filepath.Join(dir, "provider-records.json"))
if err != nil {
t.Fatal(err)
}
var record struct {
ReportedTokens int `json:"reportedTokens"`
UsageUnknown bool `json:"usageUnknown"`
TerminalFault bool `json:"terminalFault"`
Calls []struct {
ReportedTokens int `json:"reportedTokens"`
OutputCap int `json:"outputCap"`
FinishReason string `json:"finishReason"`
StreamComplete bool `json:"streamComplete"`
ToolArgumentBytes int `json:"toolArgumentBytes"`
ArgumentsValid bool `json:"toolArgumentsValid"`
UsagePresent bool `json:"usagePresent"`
} `json:"calls"`
}
if err = json.Unmarshal(raw, &record); err != nil {
t.Fatal(err)
}
if record.ReportedTokens != 17 || record.UsageUnknown || !record.TerminalFault || len(record.Calls) != 1 ||
record.Calls[0].ReportedTokens != 17 || record.Calls[0].OutputCap != 4000 ||
record.Calls[0].FinishReason != "tool_calls" || record.Calls[0].StreamComplete != tc.complete ||
record.Calls[0].ToolArgumentBytes == 0 || record.Calls[0].ArgumentsValid != tc.argumentsValid ||
!record.Calls[0].UsagePresent {
t.Fatalf("incomplete diagnostic or lost Usage: %+v", record)
}
})
}
}
func TestEvaluationKeepsUsageOnTerminalFailure(t *testing.T) {
t.Setenv("WORK_CHECKPOINT_REMAINING_TOKENS", "60000")
var providerCalls atomic.Int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
providerCalls.Add(1)
w.Header().Set("Content-Type", "text/event-stream")
fmt.Fprint(w, "data: {\"choices\":[{\"delta\":{\"tool_calls\":[{\"index\":0,\"id\":\"call_1\",\"function\":{\"name\":\"publish_work_checkpoint\",\"arguments\":\"{}\"}}]}}],\"usage\":{\"prompt_tokens\":12,\"completion_tokens\":5,\"total_tokens\":17}}\n\n")
fmt.Fprint(w, "data: {not-json}\n\n")
}))
defer srv.Close()
dir, _ := newEvaluationEventStore(t)
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
var terminal agentllm.Event
for ev := range stream(evalTestContext(t), "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
if ev.Kind == agentllm.KindMessageEnd {
terminal = ev
}
}
if terminal.Err == nil || terminal.Usage.TotalTokens != 17 {
t.Fatalf("late stream failure lost returned Usage: %#v", terminal)
}
blocked := false
otherRun := bruntime.WithProviderRunID(context.Background(), t.Name()+"-other-run")
for ev := range stream(otherRun, "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
blocked = blocked || ev.Kind == agentllm.KindError
}
raw, err := os.ReadFile(filepath.Join(dir, "provider-records.json"))
if err != nil {
t.Fatal(err)
}
var record struct {
ReportedTokens int `json:"reportedTokens"`
UsageUnknown bool `json:"usageUnknown"`
TerminalFault bool `json:"terminalFault"`
}
if err = json.Unmarshal(raw, &record); err != nil {
t.Fatal(err)
}
if !blocked || providerCalls.Load() != 1 || record.ReportedTokens != 17 || record.UsageUnknown || !record.TerminalFault {
t.Fatalf("late terminal was retried or Usage lost: blocked=%v calls=%d record=%+v", blocked, providerCalls.Load(), record)
}
}
func TestEvaluationStopsWhenUsageMissing(t *testing.T) {
t.Setenv("WORK_CHECKPOINT_REMAINING_TOKENS", "60000")
var providerCalls atomic.Int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
providerCalls.Add(1)
w.Header().Set("Content-Type", "text/event-stream")
fmt.Fprint(w, "data: {\"choices\":[{\"delta\":{\"content\":\"done\"},\"finish_reason\":\"stop\"}]}\n\ndata: [DONE]\n\n")
}))
defer srv.Close()
dir, _ := newEvaluationEventStore(t)
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
for range stream(evalTestContext(t), "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
}
blocked := false
for ev := range stream(evalTestContext(t), "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
blocked = blocked || ev.Kind == agentllm.KindError
}
if !blocked || providerCalls.Load() != 1 {
t.Fatalf("missing Usage allowed a second paid request: blocked=%v calls=%d", blocked, providerCalls.Load())
}
raw, err := os.ReadFile(filepath.Join(dir, "provider-records.json"))
if err != nil {
t.Fatal(err)
}
var record struct {
UsageUnknown bool `json:"usageUnknown"`
}
if err = json.Unmarshal(raw, &record); err != nil || !record.UsageUnknown {
t.Fatalf("missing Usage was not recorded: %v %+v", err, record)
}
}
func TestEvaluationDoesNotForwardToolTerminalBeforeUsageRecorded(t *testing.T) {
t.Setenv("WORK_CHECKPOINT_REMAINING_TOKENS", "60000")
dir, _ := newEvaluationEventStore(t)
var calls atomic.Int32
release := make(chan struct{})
provider := func(context.Context, string, []agentllm.Message, []agentllm.ToolDecl, agentllm.StreamOptions) <-chan agentllm.Event {
calls.Add(1)
out := make(chan agentllm.Event)
go func() {
defer close(out)
out <- agentllm.Event{Kind: agentllm.KindMessageEnd, Message: agentllm.Message{Role: agentllm.RoleAssistant,
StopReason: agentllm.StopToolCalls, ToolCalls: []agentllm.ToolCall{{ID: "call-1", Name: "publish_work_checkpoint", Arguments: `{}`}}},
FinishReason: "tool_calls", StreamComplete: true}
<-release // keep the provider stream open after its terminal
}()
return out
}
stream := evalProviderStreamWithProvider(provider, dir)
time.AfterFunc(100*time.Millisecond, func() { close(release) })
var terminal agentllm.Event
first := stream(evalTestContext(t), "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000})
for ev := range first {
if ev.Kind == agentllm.KindMessageEnd {
terminal = ev
break
}
}
blocked := false
for ev := range stream(bruntime.WithProviderRunID(context.Background(), t.Name()+"-next"), "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
blocked = blocked || ev.Kind == agentllm.KindError
}
for range first {
}
if terminal.Err == nil || len(terminal.Message.ToolCalls) != 0 || !blocked || calls.Load() != 1 {
t.Fatalf("missing Usage tool terminal escaped stop gate: terminal=%#v blocked=%v providerCalls=%d", terminal, blocked, calls.Load())
}
}
func TestEvaluationStopsWhenProviderRecordUnavailable(t *testing.T) {
t.Setenv("WORK_CHECKPOINT_REMAINING_TOKENS", "60000")
var providerCalls atomic.Int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
providerCalls.Add(1)
w.Header().Set("Content-Type", "text/event-stream")
fmt.Fprint(w, "data: {\"choices\":[{\"delta\":{\"content\":\"done\"},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":1,\"completion_tokens\":1,\"total_tokens\":2}}\n\ndata: [DONE]\n\n")
}))
defer srv.Close()
dir, _ := newEvaluationEventStore(t)
if err := os.Mkdir(filepath.Join(dir, "provider-records.json"), 0700); err != nil {
t.Fatal(err)
}
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
var terminal agentllm.Event
for ev := range stream(evalTestContext(t), "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
if ev.Kind == agentllm.KindMessageEnd {
terminal = ev
}
}
if terminal.Usage.TotalTokens != 2 {
t.Fatalf("control provider Usage missing: %#v", terminal)
}
blocked := false
for ev := range stream(evalTestContext(t), "fixture", nil, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
blocked = blocked || ev.Kind == agentllm.KindError
}
if !blocked || providerCalls.Load() != 1 {
t.Fatalf("missing durable record allowed another request: blocked=%v calls=%d", blocked, providerCalls.Load())
}
}
func TestEvaluationGroupsChangingPromptsByActualRunID(t *testing.T) {
t.Setenv("WORK_CHECKPOINT_REMAINING_TOKENS", "60000")
providerCalls := 0
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
providerCalls++
w.Header().Set("Content-Type", "text/event-stream")
fmt.Fprint(w, "data: {\"choices\":[{\"delta\":{\"content\":\"done\"},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":1,\"completion_tokens\":1,\"total_tokens\":2}}\n\ndata: [DONE]\n\n")
}))
defer srv.Close()
dir, _ := newEvaluationEventStore(t)
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
ctx := bruntime.WithProviderRunID(context.Background(), "same-real-run")
for _, user := range []string{"first prompt", "later prompt changed by runtime"} {
for range stream(ctx, "fixture", []agentllm.Message{{Role: agentllm.RoleSystem, Content: "stable"}, {Role: agentllm.RoleUser, Content: user}}, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
}
}
raw, err := os.ReadFile(filepath.Join(dir, "provider-records.json"))
if err != nil {
t.Fatal(err)
}
var record struct {
ModelRuns int `json:"modelRuns"`
Calls []struct {
RunID string `json:"runId"`
RunKey string `json:"runKey"`
Call int `json:"call"`
} `json:"calls"`
}
if err := json.Unmarshal(raw, &record); err != nil {
t.Fatal(err)
}
if providerCalls != 2 || record.ModelRuns != 1 || len(record.Calls) != 2 || record.Calls[0].RunID != "same-real-run" || record.Calls[1].RunID != "same-real-run" || record.Calls[0].RunKey != record.Calls[1].RunKey || record.Calls[0].Call != 1 || record.Calls[1].Call != 2 {
t.Fatalf("one real run split into evaluator groups: provider=%d record=%+v", providerCalls, record)
}
}
func TestEvaluationRefusesRequestWithoutActualRunID(t *testing.T) {
providerCalls := 0
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { providerCalls++ }))
defer srv.Close()
dir, _ := newEvaluationEventStore(t)
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
rejected := false
for event := range stream(context.Background(), "fixture", []agentllm.Message{{Role: agentllm.RoleUser, Content: "no run identity"}}, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
rejected = rejected || event.Kind == agentllm.KindError
}
if !rejected || providerCalls != 0 {
t.Fatalf("missing run ID reached provider: rejected=%v calls=%d", rejected, providerCalls)
}
}
func evalTestContext(t *testing.T) context.Context {
t.Helper()
return bruntime.WithProviderRunID(context.Background(), t.Name())
}
func TestMechanismSourceExtractionAfterSourceOnce(t *testing.T) {
id := "src_" + strings.Repeat("a", 24)
got := mechanismCheckpointSources("sourceId=" + id + " blockIndex=0\n上线六月。验收条件需要补齐")
if len(got) != 1 || got[0][1] != id || got[0][2] != "0" || !strings.Contains(got[0][3], "上线六月") {
t.Fatalf("inline source unavailable to mechanism fixture: %v", got)
}
}
func TestEvaluationFixtureUsesEffectiveNumericOutputCap(t *testing.T) {
settings := core.EffectiveSettings(evalFixtureSettings())
if got := settings.GetNumber("models.chat.maxOutputTokens", 0); got != 4000 {
t.Fatalf("mechanism output cap is not effective: got %v, want 4000", got)
}
if got := settings.GetNumber("runtime.llmRetries", 2); got != 0 {
t.Fatalf("fixture disabled-retry setting is not effective: got %v, want 0", got)
}
}
func newEvaluationEventStore(t *testing.T) (string, *sql.DB) {
t.Helper()
dir := t.TempDir()
db, err := sql.Open("sqlite", filepath.Join(dir, "agent-system.db"))
if err != nil {
t.Fatal(err)
}
if _, err = db.Exec(`CREATE TABLE events (conversation_id TEXT, run_id TEXT, seq INTEGER, type TEXT, payload TEXT)`); err != nil {
db.Close()
t.Fatal(err)
}
t.Cleanup(func() { db.Close() })
return dir, db
}
func TestExtraA01LimitsActualRunIDs(t *testing.T) {
_, st := newTestServer(t)
p, err := st.CreateProject(store.OwnerDefault, "allowance")
if err != nil {
t.Fatal(err)
}
c, err := st.CreateConversation(store.OwnerDefault, p.ID, "allowance", "")
if err != nil {
t.Fatal(err)
}
for _, kind := range []core.RunKind{core.RunConversation, core.RunSubagent} {
r := core.Run{Owner: c.Owner, ProjectID: p.ID, ConversationID: c.ID, Kind: kind, Status: core.RunRunning}
if err = st.CreateRun(&r); err != nil {
t.Fatal(err)
}
}
calls := 0
guard := limitExtraA01Runs(st, func(context.Context, string, []agentllm.Message, []agentllm.ToolDecl, agentllm.StreamOptions) <-chan agentllm.Event {
calls++
out := make(chan agentllm.Event)
close(out)
return out
})
for range guard(context.Background(), "fixture", nil, nil, agentllm.StreamOptions{}) {
}
if calls != 1 {
t.Fatal("two actual runs were blocked")
}
extra := core.Run{Owner: c.Owner, ProjectID: p.ID, ConversationID: c.ID, Kind: core.RunSubagent, Status: core.RunRunning}
if err = st.CreateRun(&extra); err != nil {
t.Fatal(err)
}
for event := range guard(context.Background(), "fixture", nil, nil, agentllm.StreamOptions{}) {
if event.Err == nil {
t.Fatal("missing allowance error")
}
}
if calls != 1 {
t.Fatal("a third actual run made a paid request")
}
}
func TestFollowupA01UsesNewBoundedAuthorization(t *testing.T) {
for _, tc := range []struct {
label string
tokens int
guard bool
}{
{"", 20000, false},
{"approved-20261013", 20000, true},
{"approved-followup-20261013", 30000, true},
{"approved-r02-20261013", 30000, true},
{"approved-r03-20261013", 30000, true},
{"unapproved", 20000, false},
} {
tokens, guard := evalA01Budget(tc.label)
if tokens != tc.tokens || guard != tc.guard {
t.Fatalf("label %q: got budget=%d guard=%v; want budget=%d guard=%v", tc.label, tokens, guard, tc.tokens, tc.guard)
}
}
}
func TestEvaluationPreservesProductionOutputCap(t *testing.T) {
for _, tc := range []struct{ supplied, want int }{{780, 780}, {5000, 4000}, {0, 4000}} {
t.Run(fmt.Sprint(tc.supplied), func(t *testing.T) {
got := make(chan int, 1)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var body struct {
MaxTokens int `json:"max_tokens"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Error(err)
}
got <- body.MaxTokens
w.Header().Set("Content-Type", "text/event-stream")
fmt.Fprint(w, "data: {\"choices\":[{\"delta\":{\"content\":\"done\"},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":1,\"completion_tokens\":1,\"total_tokens\":2}}\n\ndata: [DONE]\n\n")
}))
defer srv.Close()
dir, _ := newEvaluationEventStore(t)
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
for range stream(evalTestContext(t), "fixture", []agentllm.Message{{Role: agentllm.RoleUser, Content: "check cap"}}, nil, agentllm.StreamOptions{MaxTokens: tc.supplied}) {
}
if actual := <-got; actual != tc.want {
t.Fatalf("evaluation overwrote production cap: got %d want %d", actual, tc.want)
}
})
}
}
func TestEvaluationStopsPaidRequestsAfterRejectedCheckpoint(t *testing.T) {
t.Setenv("WORK_CHECKPOINT_REMAINING_TOKENS", "60000")
providerCalls := 0
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
providerCalls++
w.Header().Set("Content-Type", "text/event-stream")
fmt.Fprint(w, "data: {\"choices\":[{\"delta\":{\"content\":\"done\"},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":1,\"completion_tokens\":1,\"total_tokens\":2}\n\ndata: [DONE]\n\n")
}))
defer srv.Close()
dir, _ := newEvaluationEventStore(t)
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
for _, messages := range [][]agentllm.Message{
{{Role: agentllm.RoleTool, Name: "publish_work_checkpoint", IsError: true, Content: "阶段发现未发布:checkpoint.source: quote not in provided block"}},
{{Role: agentllm.RoleUser, Content: "another request after rejection"}},
} {
rejected := false
for event := range stream(evalTestContext(t), "fixture", messages, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
if event.Kind == agentllm.KindError {
rejected = true
}
}
if !rejected {
t.Fatal("rejected checkpoint did not stop the controlled sample")
}
}
if providerCalls != 0 {
t.Fatalf("%d paid provider calls started after checkpoint rejection", providerCalls)
}
}
func TestEvaluationStopsAcrossRunsAfterPersistedCheckpointRejection(t *testing.T) {
t.Setenv("WORK_CHECKPOINT_REMAINING_TOKENS", "60000")
dir, db := newEvaluationEventStore(t)
_, err := db.Exec(`INSERT INTO events(conversation_id,run_id,seq,type,payload) VALUES(?,?,?,?,?)`, "background", "child", 1, "tool.call", `{"callId":"rejected-call","name":"publish_work_checkpoint"}`)
if err != nil {
t.Fatal(err)
}
_, err = db.Exec(`INSERT INTO events(conversation_id,run_id,seq,type,payload) VALUES(?,?,?,?,?)`, "background", "child", 2, "tool.result", `{"callId":"rejected-call","status":"error","summary":"json: unknown field \"$text\""}`)
if err != nil {
t.Fatal(err)
}
providerCalls := 0
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
providerCalls++
w.Header().Set("Content-Type", "text/event-stream")
fmt.Fprint(w, "data: {\"choices\":[{\"delta\":{\"content\":\"done\"},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":1,\"completion_tokens\":1,\"total_tokens\":2}\n\ndata: [DONE]\n\n")
}))
defer srv.Close()
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
rejected := false
for event := range stream(evalTestContext(t), "fixture", []agentllm.Message{{Role: agentllm.RoleUser, Content: "unrelated foreground history"}}, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
if event.Kind == agentllm.KindError {
rejected = true
}
}
if !rejected || providerCalls != 0 {
t.Fatalf("persisted background rejection allowed foreground provider request: error=%v calls=%d", rejected, providerCalls)
}
}
func TestEvaluationFailsClosedWhenCheckpointEventsUnavailable(t *testing.T) {
providerCalls := 0
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
providerCalls++
}))
defer srv.Close()
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, t.TempDir())
rejected := false
for event := range stream(evalTestContext(t), "fixture", []agentllm.Message{{Role: agentllm.RoleUser, Content: "request without the event store"}}, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
if event.Kind == agentllm.KindError {
rejected = true
}
}
if !rejected || providerCalls != 0 {
t.Fatalf("missing checkpoint event store allowed provider request: error=%v calls=%d", rejected, providerCalls)
}
}
func TestEvaluationMatchesCheckpointRejectionWithinItsRun(t *testing.T) {
for _, tc := range []struct {
name, tool, resultRun string
}{
{"different tool", "read_file", "child"},
{"different run", "publish_work_checkpoint", "other-run"},
} {
t.Run(tc.name, func(t *testing.T) {
dir, db := newEvaluationEventStore(t)
if _, err := db.Exec(`INSERT INTO events(conversation_id,run_id,seq,type,payload) VALUES(?,?,?,?,?)`, "background", "child", 1, "tool.call", fmt.Sprintf(`{"callId":"shared","name":%q}`, tc.tool)); err != nil {
t.Fatal(err)
}
if _, err := db.Exec(`INSERT INTO events(conversation_id,run_id,seq,type,payload) VALUES(?,?,?,?,?)`, "background", tc.resultRun, 2, "tool.result", `{"callId":"shared","status":"error"}`); err != nil {
t.Fatal(err)
}
providerCalls := 0
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
providerCalls++
w.Header().Set("Content-Type", "text/event-stream")
fmt.Fprint(w, "data: {\"choices\":[{\"delta\":{\"content\":\"done\"},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":1,\"completion_tokens\":1,\"total_tokens\":2}\n\ndata: [DONE]\n\n")
}))
defer srv.Close()
stream := evalProviderStream(map[string]any{"baseUrl": srv.URL, "apiKey": "fixture", "model": "fixture"}, dir)
for range stream(evalTestContext(t), "fixture", []agentllm.Message{{Role: agentllm.RoleUser, Content: "unrelated request"}}, nil, agentllm.StreamOptions{MaxTokens: 4000}) {
}
if providerCalls != 1 {
t.Fatalf("unrelated tool error blocked the provider: calls=%d", providerCalls)
}
})
}
}