Why: Allow consumers to download an immutable module revision without nested source checkouts or local path replacements. Evidence: SELF package tests and the prior canonical-path rejection are recorded in the Dev dependency-workspace task card; remote consumption is replayed against the committed candidate. Impact: Change the module identity and its Go imports while preserving API behavior. Existing historical submodule revisions remain buildable. Refs: Versioned dependencies U1/U3; feature/dependency-workspace
107 lines
3.0 KiB
Go
107 lines
3.0 KiB
Go
package runmgr
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/bus"
|
|
"git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/profiles"
|
|
"git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/runtime"
|
|
"git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/settings"
|
|
"git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/store"
|
|
core "git-ssh.u1680832.nyat.app/weichen/Agent-System-Core.git"
|
|
)
|
|
|
|
type captureRunner struct {
|
|
id string
|
|
parts []core.Part
|
|
}
|
|
|
|
func (c *captureRunner) Name() string { return "capture" }
|
|
|
|
func (c *captureRunner) Execute(rc runtime.RunCtx) error {
|
|
if src, ok := rc.(interface{ SubagentID() string }); ok {
|
|
c.id = src.SubagentID()
|
|
}
|
|
return rc.SetAssistantParts(c.parts)
|
|
}
|
|
|
|
func newSpawnEnv(t *testing.T, runner runtime.Runner) (*runCtx, *store.Store) {
|
|
t.Helper()
|
|
c, st := newExecEnv(t)
|
|
c.mgr.profiles = profiles.New(st)
|
|
c.mgr.settings = settings.NewService(st)
|
|
c.mgr.subRunner = runner
|
|
c.mgr.active = map[string]*runHandle{}
|
|
if c.mgr.events == nil {
|
|
c.mgr.events = newEventBuffer(st, bus.New())
|
|
}
|
|
c.run.Kind = core.RunConversation
|
|
c.run.ID = "run_parent"
|
|
c.h = &runHandle{hitlCh: make(chan hitlAnswer, 1)}
|
|
return c, st
|
|
}
|
|
|
|
func TestSubagentCannotSpawnAgain(t *testing.T) {
|
|
c, st := newSpawnEnv(t, &captureRunner{})
|
|
c.run.Kind = core.RunSubagent
|
|
_, err := c.SpawnAgent("agent.sub.explore", "再派一个", "继续", "")
|
|
if err == nil || !strings.Contains(err.Error(), "子代理不能再派发子代理") {
|
|
t.Fatalf("err = %v", err)
|
|
}
|
|
ids, qerr := st.SubagentRunIDs(c.run.ConversationID)
|
|
if qerr != nil {
|
|
t.Fatal(qerr)
|
|
}
|
|
if len(ids) != 0 {
|
|
t.Fatalf("created runs = %v", ids)
|
|
}
|
|
}
|
|
|
|
func TestSubagentSummaryAndHistory(t *testing.T) {
|
|
runner := &captureRunner{parts: []core.Part{
|
|
{Type: core.PartText, Text: "正文很长,超过摘要窗口也要保留工件编号。"},
|
|
{Type: core.PartArtifactRef, Artifact: &core.ArtifactRef{ArtifactID: "art_0123456789ab", Name: "说明.md"}},
|
|
}}
|
|
c, st := newSpawnEnv(t, runner)
|
|
if err := st.AppendMessage(&core.Message{
|
|
ConversationID: c.run.ConversationID,
|
|
Role: core.RoleUser,
|
|
Parts: []core.Part{{Type: core.PartText, Text: "请写说明"}},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
res, err := c.SpawnSubagent("通用", "写说明", "简短")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if runner.id != "agent.sub.general" {
|
|
t.Fatalf("agent = %q", runner.id)
|
|
}
|
|
if !strings.Contains(res.Summary, "工件:art_0123456789ab 说明.md") {
|
|
t.Fatalf("summary = %q", res.Summary)
|
|
}
|
|
if !strings.Contains(res.Text, "正文很长") {
|
|
t.Fatalf("text = %q", res.Text)
|
|
}
|
|
hist := c.History()
|
|
for _, m := range hist {
|
|
if m.RunID != "" {
|
|
t.Fatalf("history kept sub-run message %+v", m)
|
|
}
|
|
if m.Role != core.RoleUser {
|
|
t.Fatalf("history = %+v", hist)
|
|
}
|
|
}
|
|
if len(hist) != 1 {
|
|
t.Fatalf("history len = %d", len(hist))
|
|
}
|
|
all, err := st.ListMessages(c.run.ConversationID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(all) != 2 {
|
|
t.Fatalf("list len = %d", len(all))
|
|
}
|
|
}
|