Files
gastown/internal/cmd/sling_target.go
gastown/crew/gus cd2de6ec46 refactor(sling): split 1560-line file into 7 focused modules
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>
2026-01-12 03:11:59 -08:00

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
}