Extract sling.go into logical components following the established <cmd>_<feature>.go pattern used elsewhere (crew_helpers.go, etc.): - sling.go (465 lines): command definition + main runSling() - sling_helpers.go (370): bead/tmux/agent utilities - sling_formula.go (270): formula handling + wisp parsing - sling_dog.go (158): dog dispatch logic - sling_batch.go (154): batch slinging to rigs - sling_convoy.go (125): auto-convoy creation - sling_target.go (86): target resolution functions No functional changes - pure code organization refactor. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/steveyegge/gastown/internal/session"
|
|
"github.com/steveyegge/gastown/internal/tmux"
|
|
)
|
|
|
|
// resolveTargetAgent converts a target spec to agent ID, pane, and hook root.
|
|
func resolveTargetAgent(target string) (agentID string, pane string, hookRoot string, err error) {
|
|
// First resolve to session name
|
|
sessionName, err := resolveRoleToSession(target)
|
|
if err != nil {
|
|
return "", "", "", err
|
|
}
|
|
|
|
// Convert session name to agent ID format (this doesn't require tmux)
|
|
agentID = sessionToAgentID(sessionName)
|
|
|
|
// Get the pane for that session
|
|
pane, err = getSessionPane(sessionName)
|
|
if err != nil {
|
|
return "", "", "", fmt.Errorf("getting pane for %s: %w", sessionName, err)
|
|
}
|
|
|
|
// Get the target's working directory for hook storage
|
|
t := tmux.NewTmux()
|
|
hookRoot, err = t.GetPaneWorkDir(sessionName)
|
|
if err != nil {
|
|
return "", "", "", fmt.Errorf("getting working dir for %s: %w", sessionName, err)
|
|
}
|
|
|
|
return agentID, pane, hookRoot, nil
|
|
}
|
|
|
|
// sessionToAgentID converts a session name to agent ID format.
|
|
// Uses session.ParseSessionName for consistent parsing across the codebase.
|
|
func sessionToAgentID(sessionName string) string {
|
|
identity, err := session.ParseSessionName(sessionName)
|
|
if err != nil {
|
|
// Fallback for unparseable sessions
|
|
return sessionName
|
|
}
|
|
return identity.Address()
|
|
}
|
|
|
|
// resolveSelfTarget determines agent identity, pane, and hook root for slinging to self.
|
|
func resolveSelfTarget() (agentID string, pane string, hookRoot string, err error) {
|
|
roleInfo, err := GetRole()
|
|
if err != nil {
|
|
return "", "", "", fmt.Errorf("detecting role: %w", err)
|
|
}
|
|
|
|
// Build agent identity from role
|
|
// Town-level agents use trailing slash to match addressToIdentity() normalization
|
|
switch roleInfo.Role {
|
|
case RoleMayor:
|
|
agentID = "mayor/"
|
|
case RoleDeacon:
|
|
agentID = "deacon/"
|
|
case RoleWitness:
|
|
agentID = fmt.Sprintf("%s/witness", roleInfo.Rig)
|
|
case RoleRefinery:
|
|
agentID = fmt.Sprintf("%s/refinery", roleInfo.Rig)
|
|
case RolePolecat:
|
|
agentID = fmt.Sprintf("%s/polecats/%s", roleInfo.Rig, roleInfo.Polecat)
|
|
case RoleCrew:
|
|
agentID = fmt.Sprintf("%s/crew/%s", roleInfo.Rig, roleInfo.Polecat)
|
|
default:
|
|
return "", "", "", fmt.Errorf("cannot determine agent identity (role: %s)", roleInfo.Role)
|
|
}
|
|
|
|
pane = os.Getenv("TMUX_PANE")
|
|
hookRoot = roleInfo.Home
|
|
if hookRoot == "" {
|
|
// Fallback to git root if home not determined
|
|
hookRoot, err = detectCloneRoot()
|
|
if err != nil {
|
|
return "", "", "", fmt.Errorf("detecting clone root: %w", err)
|
|
}
|
|
}
|
|
|
|
return agentID, pane, hookRoot, nil
|
|
}
|