Files
picoclaw/pkg/session/allocator.go
T

98 lines
2.5 KiB
Go

package session
import (
"fmt"
"strings"
"github.com/sipeed/picoclaw/pkg/routing"
)
// Allocation contains the concrete session keys selected for a routed turn.
// The current implementation intentionally preserves the legacy session-key
// layout while moving key construction out of the router.
type Allocation struct {
Scope SessionScope
SessionKey string
MainSessionKey string
}
// AllocationInput contains the routing result and peer context needed to
// derive the session keys for a turn.
type AllocationInput struct {
AgentID string
Channel string
AccountID string
Peer *routing.RoutePeer
SessionPolicy routing.SessionPolicy
}
// AllocateRouteSession maps a route decision onto the current legacy
// agent-scoped session-key format.
func AllocateRouteSession(input AllocationInput) Allocation {
scope := buildSessionScope(input)
sessionKey := strings.ToLower(routing.BuildAgentPeerSessionKey(routing.SessionKeyParams{
AgentID: input.AgentID,
Channel: input.Channel,
AccountID: input.AccountID,
Peer: input.Peer,
DMScope: input.SessionPolicy.DMScope,
IdentityLinks: input.SessionPolicy.IdentityLinks,
}))
mainSessionKey := strings.ToLower(routing.BuildAgentMainSessionKey(input.AgentID))
return Allocation{
Scope: scope,
SessionKey: sessionKey,
MainSessionKey: mainSessionKey,
}
}
func buildSessionScope(input AllocationInput) SessionScope {
scope := SessionScope{
Version: ScopeVersionV1,
AgentID: routing.NormalizeAgentID(input.AgentID),
Channel: strings.ToLower(strings.TrimSpace(input.Channel)),
Account: routing.NormalizeAccountID(input.AccountID),
}
peer := input.Peer
if peer == nil {
peer = &routing.RoutePeer{Kind: "direct"}
}
peerKind := strings.ToLower(strings.TrimSpace(peer.Kind))
if peerKind == "" {
peerKind = "direct"
}
switch peerKind {
case "direct":
if input.SessionPolicy.DMScope == routing.DMScopeMain {
return scope
}
peerID := routing.CanonicalSessionPeerID(
input.Channel,
peer.ID,
input.SessionPolicy.DMScope,
input.SessionPolicy.IdentityLinks,
)
if peerID == "" {
return scope
}
scope.Dimensions = []string{"sender"}
scope.Values = map[string]string{
"sender": peerID,
}
default:
peerID := strings.ToLower(strings.TrimSpace(peer.ID))
if peerID == "" {
peerID = "unknown"
}
scope.Dimensions = []string{"chat"}
scope.Values = map[string]string{
"chat": fmt.Sprintf("%s:%s", peerKind, peerID),
}
}
return scope
}