Why: Delayed notices, plugin name collisions and startup recovery exposed stale sources or silently created new attempts; deletion lost search index cleanup. Evidence: Meaningful red regressions and the corrected complete Backend suite passed; production startup was exercised through an isolated subprocess. Impact: Revalidate notices at delivery, retain plugin dispatch, restore index cleanup and complete all service wiring before recovery and public intake. Scope fixture processes and wait for owned transcript writes. Refs: Agent-System-Dev feature-fast-slow-u2-u3-plan; independent review findings 1-3 and startup supplement
98 lines
3.7 KiB
Go
98 lines
3.7 KiB
Go
package runtime
|
|
|
|
import (
|
|
agentllm "agent-native/runtime/llm"
|
|
core "agent-system-core"
|
|
"context"
|
|
"testing"
|
|
)
|
|
|
|
type checkpointRC struct {
|
|
subRC
|
|
checkpoints []core.WorkCheckpointCandidate
|
|
}
|
|
|
|
func (c *checkpointRC) PublishWorkCheckpoint(v core.WorkCheckpointCandidate) error {
|
|
c.checkpoints = append(c.checkpoints, v)
|
|
return nil
|
|
}
|
|
func checkpointJSON() string {
|
|
return `{"checkpointId":"cp1","phaseId":"reading","focus":"核对决定","findings":[{"findingKey":"date","text":"日期有差异","kind":"material_record","sources":[{"sourceId":"s1","blockIndex":0,"quote":"上线六月"}]}]}`
|
|
}
|
|
func TestWorkCheckpointUsesLocalSinkAndNoExtraModelCall(t *testing.T) {
|
|
rc := &checkpointRC{subRC: subRC{fakeRunCtx: fakeRunCtx{ctx: context.Background(), prof: subProfile()}, id: materialSubagentID}}
|
|
calls := 0
|
|
base := scriptStream([][]agentllm.Event{textDeltaTurn("", toolCall("publish_work_checkpoint", checkpointJSON())), textDeltaTurn("完成")}, nil)
|
|
r := &SubLLMRunner{Stream: func(ctx context.Context, m string, msgs []agentllm.Message, decls []agentllm.ToolDecl, opts agentllm.StreamOptions) <-chan agentllm.Event {
|
|
calls++
|
|
found := false
|
|
for _, d := range decls {
|
|
if d.Name == "publish_work_checkpoint" {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("material checkpoint tool missing")
|
|
}
|
|
return base(ctx, m, msgs, decls, opts)
|
|
}}
|
|
if e := r.Execute(rc); e != nil {
|
|
t.Fatal(e)
|
|
}
|
|
if len(rc.checkpoints) != 1 || rc.toolRuns != 0 || calls != 2 {
|
|
t.Fatal("checkpoint wasn't local / extra summary call", len(rc.checkpoints), rc.toolRuns, calls)
|
|
}
|
|
}
|
|
func TestWorkCheckpointPolicyAndStrictArguments(t *testing.T) {
|
|
rc := &checkpointRC{subRC: subRC{fakeRunCtx: fakeRunCtx{ctx: context.Background(), prof: subProfile()}, id: materialSubagentID}}
|
|
for _, policy := range []core.ToolPolicy{{Deny: []string{"publish_work_checkpoint"}}, {Confirm: []string{"publish_work_checkpoint"}}} {
|
|
rc.prof.Tools = policy
|
|
for _, d := range subagentDecls(rc, materialSubagentSpec()) {
|
|
if d.Name == "publish_work_checkpoint" {
|
|
t.Fatal("policy bypass")
|
|
}
|
|
}
|
|
}
|
|
rc.prof.Tools = core.ToolPolicy{}
|
|
st := &subRun{rc: rc, localCheckpoint: checkpointEnabled(rc)}
|
|
res := st.runTool("publish_work_checkpoint", `{"checkpointId":"cp1","taskId":"forged"}`)
|
|
if !res.IsError || len(rc.checkpoints) != 0 {
|
|
t.Fatal("foreign scope accepted", res)
|
|
}
|
|
}
|
|
|
|
func TestWorkCheckpointFailureDoesNotFailMainTask(t *testing.T) {
|
|
rc := &checkpointRC{subRC: subRC{fakeRunCtx: fakeRunCtx{ctx: context.Background(), prof: subProfile()}, id: materialSubagentID}}
|
|
r := &SubLLMRunner{Stream: scriptStream([][]agentllm.Event{textDeltaTurn("", toolCall(workCheckpointTool, `{"checkpointId":"bad","taskId":"forged"}`)), textDeltaTurn("保留最终结果")}, nil)}
|
|
if e := r.Execute(rc); e != nil {
|
|
t.Fatal(e)
|
|
}
|
|
if len(rc.checkpoints) != 0 {
|
|
t.Fatal("bad candidate published")
|
|
}
|
|
found := false
|
|
for _, p := range rc.assistant {
|
|
if p.Text == "保留最终结果" {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatal("main result lost")
|
|
}
|
|
}
|
|
func TestWorkCheckpointMaterialRespectsProfileTurnBudget(t *testing.T) {
|
|
one := 1
|
|
rc := &checkpointRC{subRC: subRC{fakeRunCtx: fakeRunCtx{ctx: context.Background(), prof: subProfile()}, id: materialSubagentID}}
|
|
rc.prof.Budget.MaxTurns = &one
|
|
calls := 0
|
|
base := scriptStream([][]agentllm.Event{textDeltaTurn("", toolCall(workCheckpointTool, checkpointJSON())), textDeltaTurn("must not run")}, nil)
|
|
r := &SubLLMRunner{Stream: func(ctx context.Context, m string, msgs []agentllm.Message, decls []agentllm.ToolDecl, opts agentllm.StreamOptions) <-chan agentllm.Event {
|
|
calls++
|
|
return base(ctx, m, msgs, decls, opts)
|
|
}}
|
|
_ = r.Execute(rc)
|
|
if calls != 1 {
|
|
t.Fatal("child ignored profile budget", calls)
|
|
}
|
|
}
|