Harden worker federation and operator UI
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"net"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -82,6 +83,97 @@ func TestStartAgentPassesEmptyHarnessArgs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartAgentAttachesTwoSameHarnessSessionsWithDistinctNames(t *testing.T) {
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = ln.Close() })
|
||||
starts := make(chan Request, 2)
|
||||
go func() {
|
||||
for i := 0; i < 4; i++ {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var req Request
|
||||
if json.NewDecoder(bufio.NewReader(conn)).Decode(&req) == nil {
|
||||
switch req.Method {
|
||||
case "agent.start":
|
||||
starts <- req
|
||||
_ = json.NewEncoder(conn).Encode(Response{ID: req.ID, Result: json.RawMessage(`{}`)})
|
||||
case "pane.get":
|
||||
_ = json.NewEncoder(conn).Encode(Response{ID: req.ID, Result: json.RawMessage(`{"type":"pane_info","pane":{"agent":"opencode","agent_status":"idle"}}`)})
|
||||
}
|
||||
}
|
||||
_ = conn.Close()
|
||||
}
|
||||
}()
|
||||
c := &Client{Path: ln.Addr().String(), panes: map[string]string{"/one": "w1:p1", "/two": "w2:p1"}, dial: func() (net.Conn, error) {
|
||||
return net.Dial("tcp", ln.Addr().String())
|
||||
}}
|
||||
first, err := c.StartAgent(context.Background(), "", "/one", "", "opencode", "first-task")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
second, err := c.StartAgent(context.Background(), "", "/two", "", "opencode", "second-task")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if first.AgentName == second.AgentName || first.AgentName == "" || second.AgentName == "" {
|
||||
t.Fatalf("agent names must be distinct and persisted: %+v / %+v", first, second)
|
||||
}
|
||||
for _, want := range []string{first.AgentName, second.AgentName} {
|
||||
req := <-starts
|
||||
params, _ := json.Marshal(req.Params)
|
||||
var got struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
_ = json.Unmarshal(params, &got)
|
||||
if got.Name != want {
|
||||
t.Fatalf("agent.start name = %q, want %q", got.Name, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartAgentRejectsSuccessWithoutAttachment(t *testing.T) {
|
||||
oldWindow, oldPoll := agentAttachWindow, agentAttachPoll
|
||||
agentAttachWindow, agentAttachPoll = 25*time.Millisecond, time.Millisecond
|
||||
t.Cleanup(func() { agentAttachWindow, agentAttachPoll = oldWindow, oldPoll })
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = ln.Close() })
|
||||
go func() {
|
||||
for {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
var req Request
|
||||
if json.NewDecoder(bufio.NewReader(conn)).Decode(&req) != nil {
|
||||
return
|
||||
}
|
||||
result := json.RawMessage(`{"type":"pane_info","pane":{"agent_status":"unknown"}}`)
|
||||
if req.Method == "agent.start" {
|
||||
result = json.RawMessage(`{}`)
|
||||
}
|
||||
_ = json.NewEncoder(conn).Encode(Response{ID: req.ID, Result: result})
|
||||
}()
|
||||
}
|
||||
}()
|
||||
c := &Client{Path: ln.Addr().String(), panes: map[string]string{"/worktree": "w1:p1"}, dial: func() (net.Conn, error) {
|
||||
return net.Dial("tcp", ln.Addr().String())
|
||||
}}
|
||||
_, err = c.StartAgent(context.Background(), "", "/worktree", "", "opencode", "silent-noop")
|
||||
if err == nil || !strings.Contains(err.Error(), "no agent attached") {
|
||||
t.Fatalf("StartAgent error = %v, want explicit missing attachment", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentNameIsBoundedAndValid(t *testing.T) {
|
||||
got := agentName("OpenCode", "TASK With spaces / and symbols !!! 0123456789")
|
||||
if len(got) > 32 || !regexp.MustCompile(`^[a-z0-9_-]+$`).MatchString(got) {
|
||||
|
||||
Reference in New Issue
Block a user