mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
272536a11a
Implement per-agent workspace/model/session isolation with 7-level priority routing cascade (peer > parent_peer > guild > team > account > channel > default). Backward compatible - empty agents.list creates implicit "main" agent from defaults. Core components: - routing/agent_id.go: ID normalization with pre-compiled regex - routing/session_key.go: 4 DM scope modes with identity links - routing/route.go: RouteResolver with priority-based binding matcher - agent/instance.go: Per-agent state (workspace, sessions, tools, model) - agent/registry.go: Agent lifecycle, route resolution, subagent ACL Integration: - config.go: AgentModelConfig (flexible JSON), bindings, session config - loop.go: Complete rewrite for multi-agent dispatch - Channel adapters: peer_kind/peer_id metadata (telegram, discord, slack) - spawn.go: Subagent allowlist enforcement per agent Validated end-to-end with Discord channel-based bindings, default fallback routing, and per-agent session persistence.
87 lines
2.2 KiB
Go
87 lines
2.2 KiB
Go
package routing
|
|
|
|
import "testing"
|
|
|
|
func TestNormalizeAgentID_Empty(t *testing.T) {
|
|
if got := NormalizeAgentID(""); got != DefaultAgentID {
|
|
t.Errorf("NormalizeAgentID('') = %q, want %q", got, DefaultAgentID)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeAgentID_Whitespace(t *testing.T) {
|
|
if got := NormalizeAgentID(" "); got != DefaultAgentID {
|
|
t.Errorf("NormalizeAgentID(' ') = %q, want %q", got, DefaultAgentID)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeAgentID_Valid(t *testing.T) {
|
|
tests := []struct {
|
|
input, want string
|
|
}{
|
|
{"main", "main"},
|
|
{"Main", "main"},
|
|
{"SALES", "sales"},
|
|
{"support-bot", "support-bot"},
|
|
{"agent_1", "agent_1"},
|
|
{"a", "a"},
|
|
{"0test", "0test"},
|
|
}
|
|
for _, tt := range tests {
|
|
if got := NormalizeAgentID(tt.input); got != tt.want {
|
|
t.Errorf("NormalizeAgentID(%q) = %q, want %q", tt.input, got, tt.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNormalizeAgentID_InvalidChars(t *testing.T) {
|
|
tests := []struct {
|
|
input, want string
|
|
}{
|
|
{"Hello World", "hello-world"},
|
|
{"agent@123", "agent-123"},
|
|
{"foo.bar.baz", "foo-bar-baz"},
|
|
{"--leading", "leading"},
|
|
{"--both--", "both"},
|
|
}
|
|
for _, tt := range tests {
|
|
if got := NormalizeAgentID(tt.input); got != tt.want {
|
|
t.Errorf("NormalizeAgentID(%q) = %q, want %q", tt.input, got, tt.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNormalizeAgentID_AllInvalid(t *testing.T) {
|
|
if got := NormalizeAgentID("@@@"); got != DefaultAgentID {
|
|
t.Errorf("NormalizeAgentID('@@@') = %q, want %q", got, DefaultAgentID)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeAgentID_TruncatesAt64(t *testing.T) {
|
|
long := ""
|
|
for i := 0; i < 100; i++ {
|
|
long += "a"
|
|
}
|
|
got := NormalizeAgentID(long)
|
|
if len(got) > MaxAgentIDLength {
|
|
t.Errorf("length = %d, want <= %d", len(got), MaxAgentIDLength)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeAccountID_Empty(t *testing.T) {
|
|
if got := NormalizeAccountID(""); got != DefaultAccountID {
|
|
t.Errorf("NormalizeAccountID('') = %q, want %q", got, DefaultAccountID)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeAccountID_Valid(t *testing.T) {
|
|
if got := NormalizeAccountID("MyBot"); got != "mybot" {
|
|
t.Errorf("NormalizeAccountID('MyBot') = %q, want 'mybot'", got)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeAccountID_InvalidChars(t *testing.T) {
|
|
if got := NormalizeAccountID("bot@home"); got != "bot-home" {
|
|
t.Errorf("NormalizeAccountID('bot@home') = %q, want 'bot-home'", got)
|
|
}
|
|
}
|