mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-05-25 16:00:35 +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.
67 lines
1.7 KiB
Go
67 lines
1.7 KiB
Go
package routing
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
DefaultAgentID = "main"
|
|
DefaultMainKey = "main"
|
|
DefaultAccountID = "default"
|
|
MaxAgentIDLength = 64
|
|
)
|
|
|
|
var (
|
|
validIDRe = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]{0,63}$`)
|
|
invalidCharsRe = regexp.MustCompile(`[^a-z0-9_-]+`)
|
|
leadingDashRe = regexp.MustCompile(`^-+`)
|
|
trailingDashRe = regexp.MustCompile(`-+$`)
|
|
)
|
|
|
|
// NormalizeAgentID sanitizes an agent ID to [a-z0-9][a-z0-9_-]{0,63}.
|
|
// Invalid characters are collapsed to "-". Leading/trailing dashes stripped.
|
|
// Empty input returns DefaultAgentID ("main").
|
|
func NormalizeAgentID(id string) string {
|
|
trimmed := strings.TrimSpace(id)
|
|
if trimmed == "" {
|
|
return DefaultAgentID
|
|
}
|
|
lower := strings.ToLower(trimmed)
|
|
if validIDRe.MatchString(lower) {
|
|
return lower
|
|
}
|
|
result := invalidCharsRe.ReplaceAllString(lower, "-")
|
|
result = leadingDashRe.ReplaceAllString(result, "")
|
|
result = trailingDashRe.ReplaceAllString(result, "")
|
|
if len(result) > MaxAgentIDLength {
|
|
result = result[:MaxAgentIDLength]
|
|
}
|
|
if result == "" {
|
|
return DefaultAgentID
|
|
}
|
|
return result
|
|
}
|
|
|
|
// NormalizeAccountID sanitizes an account ID. Empty returns DefaultAccountID.
|
|
func NormalizeAccountID(id string) string {
|
|
trimmed := strings.TrimSpace(id)
|
|
if trimmed == "" {
|
|
return DefaultAccountID
|
|
}
|
|
lower := strings.ToLower(trimmed)
|
|
if validIDRe.MatchString(lower) {
|
|
return lower
|
|
}
|
|
result := invalidCharsRe.ReplaceAllString(lower, "-")
|
|
result = leadingDashRe.ReplaceAllString(result, "")
|
|
result = trailingDashRe.ReplaceAllString(result, "")
|
|
if len(result) > MaxAgentIDLength {
|
|
result = result[:MaxAgentIDLength]
|
|
}
|
|
if result == "" {
|
|
return DefaultAccountID
|
|
}
|
|
return result
|
|
}
|