refactor(development): move gastown patches to separate files
All checks were successful
CI / check (push) Successful in 3m37s
All checks were successful
CI / check (push) Successful in 3m37s
Replace inline postPatch substituteInPlace calls with proper unified diff patch files, following the pattern established by beads. This improves maintainability: - Each patch is in its own file with clear naming - Patches use proper unified diff format - Easier to review, update, and track individual fixes - Default.nix is cleaner (237 lines of substituteInPlace -> 15 lines) Patches included: - gastown-fix-validate-recipient.patch - gastown-fix-agent-bead-address-title.patch - gastown-fix-agent-bead-rig-prefix.patch - gastown-fix-role-home-paths.patch - gastown-fix-town-root-detection.patch - gastown-fix-copydir-symlinks.patch - gastown-statusline-optimization.patch Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,251 +41,24 @@ let
|
|||||||
];
|
];
|
||||||
|
|
||||||
# Bug fixes not yet merged upstream
|
# Bug fixes not yet merged upstream
|
||||||
postPatch = ''
|
# Each patch is stored in a separate file for clarity and maintainability
|
||||||
|
patches = [
|
||||||
# Fix validateRecipient bug: normalize addresses before comparison
|
# Fix validateRecipient bug: normalize addresses before comparison
|
||||||
# See: https://github.com/steveyegge/gastown/issues/TBD
|
./gastown-fix-validate-recipient.patch
|
||||||
substituteInPlace internal/mail/router.go \
|
|
||||||
--replace-fail \
|
|
||||||
'if agentBeadToAddress(agent) == identity {' \
|
|
||||||
'if AddressToIdentity(agentBeadToAddress(agent)) == AddressToIdentity(identity) {'
|
|
||||||
|
|
||||||
# Fix agentBeadToAddress to use title field for hq- prefixed beads
|
# Fix agentBeadToAddress to use title field for hq- prefixed beads
|
||||||
# Title should contain the address (e.g., "java/crew/americano")
|
./gastown-fix-agent-bead-address-title.patch
|
||||||
substituteInPlace internal/mail/router.go \
|
|
||||||
--replace-fail \
|
|
||||||
'return parseAgentAddressFromDescription(bead.Description)' \
|
|
||||||
'if bead.Title != "" && strings.Contains(bead.Title, "/") { return bead.Title }; return parseAgentAddressFromDescription(bead.Description)'
|
|
||||||
|
|
||||||
# Fix agentBeadToAddress to handle rig-specific prefixes (j-, sc-, etc.)
|
# Fix agentBeadToAddress to handle rig-specific prefixes (j-, sc-, etc.)
|
||||||
# Bead IDs like j-java-crew-americano should map to java/crew/americano
|
./gastown-fix-agent-bead-rig-prefix.patch
|
||||||
substituteInPlace internal/mail/router.go \
|
|
||||||
--replace-fail \
|
|
||||||
'// Handle gt- prefixed IDs (legacy format)
|
|
||||||
if !strings.HasPrefix(id, "gt-") {
|
|
||||||
return "" // Not a valid agent bead ID
|
|
||||||
}' \
|
|
||||||
'// Handle rig-specific prefixes: <prefix>-<rig>-<role>-<name>
|
|
||||||
// Examples: j-java-crew-americano -> java/crew/americano
|
|
||||||
idParts := strings.Split(id, "-")
|
|
||||||
if len(idParts) >= 3 {
|
|
||||||
for i, part := range idParts {
|
|
||||||
if part == "crew" || part == "polecat" || part == "polecats" {
|
|
||||||
if i >= 1 && i < len(idParts)-1 {
|
|
||||||
rig := idParts[i-1]
|
|
||||||
name := strings.Join(idParts[i+1:], "-")
|
|
||||||
return rig + "/" + part + "/" + name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if part == "witness" || part == "refinery" {
|
|
||||||
if i >= 1 {
|
|
||||||
return idParts[i-1] + "/" + part
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle gt- prefixed IDs (legacy format)
|
|
||||||
if !strings.HasPrefix(id, "gt-") {
|
|
||||||
return "" // Not a valid agent bead ID
|
|
||||||
}'
|
|
||||||
|
|
||||||
# Fix crew/polecat home paths: remove incorrect /rig suffix
|
# Fix crew/polecat home paths: remove incorrect /rig suffix
|
||||||
substituteInPlace internal/cmd/role.go \
|
./gastown-fix-role-home-paths.patch
|
||||||
--replace-fail \
|
|
||||||
'return filepath.Join(townRoot, rig, "polecats", polecat, "rig")' \
|
|
||||||
'return filepath.Join(townRoot, rig, "polecats", polecat)' \
|
|
||||||
--replace-fail \
|
|
||||||
'return filepath.Join(townRoot, rig, "crew", polecat, "rig")' \
|
|
||||||
'return filepath.Join(townRoot, rig, "crew", polecat)'
|
|
||||||
|
|
||||||
# Fix town root detection: don't map to Mayor (causes spurious mismatch warnings)
|
# Fix town root detection: don't map to Mayor (causes spurious mismatch warnings)
|
||||||
substituteInPlace internal/cmd/prime.go \
|
./gastown-fix-town-root-detection.patch
|
||||||
--replace-fail \
|
|
||||||
'if relPath == "." || relPath == "" {
|
|
||||||
ctx.Role = RoleMayor
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
if len(parts) >= 1 && parts[0] == "mayor" {' \
|
|
||||||
'if relPath == "." || relPath == "" {
|
|
||||||
return ctx // RoleUnknown - town root is shared space
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for mayor role: mayor/ or mayor/rig/
|
|
||||||
if len(parts) >= 1 && parts[0] == "mayor" {'
|
|
||||||
|
|
||||||
# Fix copyDir to handle symlinks (broken symlinks cause "no such file" errors)
|
# Fix copyDir to handle symlinks (broken symlinks cause "no such file" errors)
|
||||||
# See: https://github.com/steveyegge/gastown/issues/TBD
|
./gastown-fix-copydir-symlinks.patch
|
||||||
substituteInPlace internal/git/git.go \
|
|
||||||
--replace-fail \
|
|
||||||
'if entry.IsDir() {' \
|
|
||||||
'// Handle symlinks (recreate them, do not follow)
|
|
||||||
if entry.Type()&os.ModeSymlink != 0 {
|
|
||||||
linkTarget, err := os.Readlink(srcPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := os.Symlink(linkTarget, destPath); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if entry.IsDir() {'
|
|
||||||
|
|
||||||
# Statusline optimization: skip detached sessions and cache results
|
# Statusline optimization: skip detached sessions and cache results
|
||||||
# Reduces Dolt CPU from ~70% to ~20% by avoiding beads queries for sessions nobody is watching
|
# Reduces Dolt CPU from ~70% to ~20% by avoiding beads queries for sessions nobody is watching
|
||||||
# See: https://github.com/steveyegge/gastown/issues/TBD
|
./gastown-statusline-optimization.patch
|
||||||
substituteInPlace internal/cmd/statusline.go \
|
];
|
||||||
--replace-fail \
|
|
||||||
'"strings"' \
|
|
||||||
'"strings"
|
|
||||||
"time"' \
|
|
||||||
--replace-fail \
|
|
||||||
'var (
|
|
||||||
statusLineSession string
|
|
||||||
)' \
|
|
||||||
'// statusLineCacheTTL is how long cached status output remains valid.
|
|
||||||
const statusLineCacheTTL = 10 * time.Second
|
|
||||||
|
|
||||||
// statusLineCachePath returns the cache file path for a session.
|
|
||||||
func statusLineCachePath(session string) string {
|
|
||||||
return filepath.Join(os.TempDir(), fmt.Sprintf("gt-status-%s", session))
|
|
||||||
}
|
|
||||||
|
|
||||||
// getStatusLineCache returns cached status if fresh, empty string otherwise.
|
|
||||||
func getStatusLineCache(session string) string {
|
|
||||||
path := statusLineCachePath(session)
|
|
||||||
info, err := os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if time.Since(info.ModTime()) > statusLineCacheTTL {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
data, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setStatusLineCache writes status to cache file.
|
|
||||||
func setStatusLineCache(session, status string) {
|
|
||||||
path := statusLineCachePath(session)
|
|
||||||
_ = os.WriteFile(path, []byte(status), 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
statusLineSession string
|
|
||||||
)' \
|
|
||||||
--replace-fail \
|
|
||||||
'func runStatusLine(cmd *cobra.Command, args []string) error {
|
|
||||||
t := tmux.NewTmux()
|
|
||||||
|
|
||||||
// Get session environment' \
|
|
||||||
'func runStatusLine(cmd *cobra.Command, args []string) error {
|
|
||||||
t := tmux.NewTmux()
|
|
||||||
|
|
||||||
// Optimization: skip expensive beads queries for detached sessions
|
|
||||||
if statusLineSession != "" {
|
|
||||||
if !t.IsSessionAttached(statusLineSession) {
|
|
||||||
fmt.Print("○ |")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Check cache for attached sessions too
|
|
||||||
if cached := getStatusLineCache(statusLineSession); cached != "" {
|
|
||||||
fmt.Print(cached)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get session environment' \
|
|
||||||
--replace-fail \
|
|
||||||
' // Output
|
|
||||||
if len(parts) > 0 {
|
|
||||||
fmt.Print(strings.Join(parts, " | ") + " |")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func runMayorStatusLine(t *tmux.Tmux) error {' \
|
|
||||||
' // Output
|
|
||||||
if len(parts) > 0 {
|
|
||||||
output := strings.Join(parts, " | ") + " |"
|
|
||||||
if statusLineSession != "" {
|
|
||||||
setStatusLineCache(statusLineSession, output)
|
|
||||||
}
|
|
||||||
fmt.Print(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func runMayorStatusLine(t *tmux.Tmux) error {' \
|
|
||||||
--replace-fail \
|
|
||||||
'fmt.Print(strings.Join(parts, " | ") + " |")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// runDeaconStatusLine outputs status for the deacon session.' \
|
|
||||||
'output := strings.Join(parts, " | ") + " |"
|
|
||||||
if statusLineSession != "" {
|
|
||||||
setStatusLineCache(statusLineSession, output)
|
|
||||||
}
|
|
||||||
fmt.Print(output)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// runDeaconStatusLine outputs status for the deacon session.' \
|
|
||||||
--replace-fail \
|
|
||||||
'fmt.Print(strings.Join(parts, " | ") + " |")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// runWitnessStatusLine outputs status for a witness session.
|
|
||||||
// Shows: crew count, hook or mail preview' \
|
|
||||||
'output := strings.Join(parts, " | ") + " |"
|
|
||||||
if statusLineSession != "" {
|
|
||||||
setStatusLineCache(statusLineSession, output)
|
|
||||||
}
|
|
||||||
fmt.Print(output)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// runWitnessStatusLine outputs status for a witness session.
|
|
||||||
// Shows: crew count, hook or mail preview' \
|
|
||||||
--replace-fail \
|
|
||||||
'fmt.Print(strings.Join(parts, " | ") + " |")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// runRefineryStatusLine outputs status for a refinery session.' \
|
|
||||||
'output := strings.Join(parts, " | ") + " |"
|
|
||||||
if statusLineSession != "" {
|
|
||||||
setStatusLineCache(statusLineSession, output)
|
|
||||||
}
|
|
||||||
fmt.Print(output)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// runRefineryStatusLine outputs status for a refinery session.' \
|
|
||||||
--replace-fail \
|
|
||||||
'fmt.Print(strings.Join(parts, " | ") + " |")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// isSessionWorking detects' \
|
|
||||||
'output := strings.Join(parts, " | ") + " |"
|
|
||||||
if statusLineSession != "" {
|
|
||||||
setStatusLineCache(statusLineSession, output)
|
|
||||||
}
|
|
||||||
fmt.Print(output)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// isSessionWorking detects'
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
description = "Gas Town - multi-agent workspace manager by Steve Yegge";
|
description = "Gas Town - multi-agent workspace manager by Steve Yegge";
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
diff --git a/internal/mail/router.go b/internal/mail/router.go
|
||||||
|
index 0000000..1111111 100644
|
||||||
|
--- a/internal/mail/router.go
|
||||||
|
+++ b/internal/mail/router.go
|
||||||
|
@@ -326,7 +326,11 @@ func agentBeadToAddress(bead *agentBead) string {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to parsing description for role_type and rig
|
||||||
|
- return parseAgentAddressFromDescription(bead.Description)
|
||||||
|
+ if bead.Title != "" && strings.Contains(bead.Title, "/") {
|
||||||
|
+ return bead.Title
|
||||||
|
+ }
|
||||||
|
+ return parseAgentAddressFromDescription(bead.Description)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle gt- prefixed IDs (legacy format)
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
diff --git a/internal/mail/router.go b/internal/mail/router.go
|
||||||
|
index 0000000..1111111 100644
|
||||||
|
--- a/internal/mail/router.go
|
||||||
|
+++ b/internal/mail/router.go
|
||||||
|
@@ -330,8 +330,28 @@ func agentBeadToAddress(bead *agentBead) string {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle gt- prefixed IDs (legacy format)
|
||||||
|
- if !strings.HasPrefix(id, "gt-") {
|
||||||
|
- return "" // Not a valid agent bead ID
|
||||||
|
+ // Handle rig-specific prefixes: <prefix>-<rig>-<role>-<name>
|
||||||
|
+ // Examples: j-java-crew-americano -> java/crew/americano
|
||||||
|
+ idParts := strings.Split(id, "-")
|
||||||
|
+ if len(idParts) >= 3 {
|
||||||
|
+ for i, part := range idParts {
|
||||||
|
+ if part == "crew" || part == "polecat" || part == "polecats" {
|
||||||
|
+ if i >= 1 && i < len(idParts)-1 {
|
||||||
|
+ rig := idParts[i-1]
|
||||||
|
+ name := strings.Join(idParts[i+1:], "-")
|
||||||
|
+ return rig + "/" + part + "/" + name
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if part == "witness" || part == "refinery" {
|
||||||
|
+ if i >= 1 {
|
||||||
|
+ return idParts[i-1] + "/" + part
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Handle gt- prefixed IDs (legacy format)
|
||||||
|
+ if !strings.HasPrefix(id, "gt-") {
|
||||||
|
+ return "" // Not a valid agent bead ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip prefix
|
||||||
25
home/roles/development/gastown-fix-copydir-symlinks.patch
Normal file
25
home/roles/development/gastown-fix-copydir-symlinks.patch
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
diff --git a/internal/git/git.go b/internal/git/git.go
|
||||||
|
index 0000000..1111111 100644
|
||||||
|
--- a/internal/git/git.go
|
||||||
|
+++ b/internal/git/git.go
|
||||||
|
@@ -73,7 +73,18 @@ func copyDir(src, dest string) error {
|
||||||
|
srcPath := filepath.Join(src, entry.Name())
|
||||||
|
destPath := filepath.Join(dest, entry.Name())
|
||||||
|
|
||||||
|
- if entry.IsDir() {
|
||||||
|
+ // Handle symlinks (recreate them, do not follow)
|
||||||
|
+ if entry.Type()&os.ModeSymlink != 0 {
|
||||||
|
+ linkTarget, err := os.Readlink(srcPath)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return err
|
||||||
|
+ }
|
||||||
|
+ if err := os.Symlink(linkTarget, destPath); err != nil {
|
||||||
|
+ return err
|
||||||
|
+ }
|
||||||
|
+ continue
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if entry.IsDir() {
|
||||||
|
if err := copyDir(srcPath, destPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
19
home/roles/development/gastown-fix-role-home-paths.patch
Normal file
19
home/roles/development/gastown-fix-role-home-paths.patch
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
diff --git a/internal/cmd/role.go b/internal/cmd/role.go
|
||||||
|
index 0000000..1111111 100644
|
||||||
|
--- a/internal/cmd/role.go
|
||||||
|
+++ b/internal/cmd/role.go
|
||||||
|
@@ -326,11 +326,11 @@ func getRoleHome(role Role, rig, polecat, townRoot string) string {
|
||||||
|
if rig == "" || polecat == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
- return filepath.Join(townRoot, rig, "polecats", polecat, "rig")
|
||||||
|
+ return filepath.Join(townRoot, rig, "polecats", polecat)
|
||||||
|
case RoleCrew:
|
||||||
|
if rig == "" || polecat == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
- return filepath.Join(townRoot, rig, "crew", polecat, "rig")
|
||||||
|
+ return filepath.Join(townRoot, rig, "crew", polecat)
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
19
home/roles/development/gastown-fix-town-root-detection.patch
Normal file
19
home/roles/development/gastown-fix-town-root-detection.patch
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
diff --git a/internal/cmd/prime.go b/internal/cmd/prime.go
|
||||||
|
index 0000000..1111111 100644
|
||||||
|
--- a/internal/cmd/prime.go
|
||||||
|
+++ b/internal/cmd/prime.go
|
||||||
|
@@ -276,12 +276,12 @@ func detectRole(cwd, townRoot string) RoleInfo {
|
||||||
|
|
||||||
|
// Check for mayor role
|
||||||
|
// At town root, or in mayor/ or mayor/rig/
|
||||||
|
if relPath == "." || relPath == "" {
|
||||||
|
- ctx.Role = RoleMayor
|
||||||
|
- return ctx
|
||||||
|
+ return ctx // RoleUnknown - town root is shared space
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // Check for mayor role: mayor/ or mayor/rig/
|
||||||
|
if len(parts) >= 1 && parts[0] == "mayor" {
|
||||||
|
ctx.Role = RoleMayor
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
13
home/roles/development/gastown-fix-validate-recipient.patch
Normal file
13
home/roles/development/gastown-fix-validate-recipient.patch
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
diff --git a/internal/mail/router.go b/internal/mail/router.go
|
||||||
|
index b864c069..4b6a045b 100644
|
||||||
|
--- a/internal/mail/router.go
|
||||||
|
+++ b/internal/mail/router.go
|
||||||
|
@@ -646,7 +646,7 @@ func (r *Router) validateRecipient(identity string) error {
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, agent := range agents {
|
||||||
|
- if agentBeadToAddress(agent) == identity {
|
||||||
|
+ if AddressToIdentity(agentBeadToAddress(agent)) == AddressToIdentity(identity) {
|
||||||
|
return nil // Found matching agent
|
||||||
|
}
|
||||||
|
}
|
||||||
136
home/roles/development/gastown-statusline-optimization.patch
Normal file
136
home/roles/development/gastown-statusline-optimization.patch
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
diff --git a/internal/cmd/statusline.go b/internal/cmd/statusline.go
|
||||||
|
index 0000000..1111111 100644
|
||||||
|
--- a/internal/cmd/statusline.go
|
||||||
|
+++ b/internal/cmd/statusline.go
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
+ "time"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/steveyegge/gastown/internal/beads"
|
||||||
|
@@ -15,6 +16,43 @@ import (
|
||||||
|
"github.com/steveyegge/gastown/internal/workspace"
|
||||||
|
)
|
||||||
|
|
||||||
|
+// statusLineCacheTTL is how long cached status output remains valid.
|
||||||
|
+const statusLineCacheTTL = 10 * time.Second
|
||||||
|
+
|
||||||
|
+// statusLineCachePath returns the cache file path for a session.
|
||||||
|
+func statusLineCachePath(session string) string {
|
||||||
|
+ return filepath.Join(os.TempDir(), fmt.Sprintf("gt-status-%s", session))
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// getStatusLineCache returns cached status if fresh, empty string otherwise.
|
||||||
|
+func getStatusLineCache(session string) string {
|
||||||
|
+ path := statusLineCachePath(session)
|
||||||
|
+ info, err := os.Stat(path)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return ""
|
||||||
|
+ }
|
||||||
|
+ if time.Since(info.ModTime()) > statusLineCacheTTL {
|
||||||
|
+ return ""
|
||||||
|
+ }
|
||||||
|
+ data, err := os.ReadFile(path)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return ""
|
||||||
|
+ }
|
||||||
|
+ return string(data)
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// setStatusLineCache writes status to cache file.
|
||||||
|
+func setStatusLineCache(session, status string) {
|
||||||
|
+ path := statusLineCachePath(session)
|
||||||
|
+ _ = os.WriteFile(path, []byte(status), 0644)
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
var (
|
||||||
|
statusLineSession string
|
||||||
|
)
|
||||||
|
@@ -32,6 +70,20 @@ func init() {
|
||||||
|
func runStatusLine(cmd *cobra.Command, args []string) error {
|
||||||
|
t := tmux.NewTmux()
|
||||||
|
|
||||||
|
+ // Optimization: skip expensive beads queries for detached sessions
|
||||||
|
+ if statusLineSession != "" {
|
||||||
|
+ if !t.IsSessionAttached(statusLineSession) {
|
||||||
|
+ fmt.Print("○ |")
|
||||||
|
+ return nil
|
||||||
|
+ }
|
||||||
|
+ // Check cache for attached sessions too
|
||||||
|
+ if cached := getStatusLineCache(statusLineSession); cached != "" {
|
||||||
|
+ fmt.Print(cached)
|
||||||
|
+ return nil
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// Get session environment
|
||||||
|
var rigName, polecat, crew, issue, role string
|
||||||
|
|
||||||
|
@@ -149,7 +201,12 @@ func runWorkerStatusLine(t *tmux.Tmux, session, rigName, polecat, crew, issue st
|
||||||
|
|
||||||
|
// Output
|
||||||
|
if len(parts) > 0 {
|
||||||
|
- fmt.Print(strings.Join(parts, " | ") + " |")
|
||||||
|
+ output := strings.Join(parts, " | ") + " |"
|
||||||
|
+ if statusLineSession != "" {
|
||||||
|
+ setStatusLineCache(statusLineSession, output)
|
||||||
|
+ }
|
||||||
|
+ fmt.Print(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
@@ -389,7 +446,12 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- fmt.Print(strings.Join(parts, " | ") + " |")
|
||||||
|
+ output := strings.Join(parts, " | ") + " |"
|
||||||
|
+ if statusLineSession != "" {
|
||||||
|
+ setStatusLineCache(statusLineSession, output)
|
||||||
|
+ }
|
||||||
|
+ fmt.Print(output)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -458,7 +520,12 @@ func runDeaconStatusLine(t *tmux.Tmux) error {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- fmt.Print(strings.Join(parts, " | ") + " |")
|
||||||
|
+ output := strings.Join(parts, " | ") + " |"
|
||||||
|
+ if statusLineSession != "" {
|
||||||
|
+ setStatusLineCache(statusLineSession, output)
|
||||||
|
+ }
|
||||||
|
+ fmt.Print(output)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -526,7 +593,12 @@ func runWitnessStatusLine(t *tmux.Tmux, rigName string) error {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- fmt.Print(strings.Join(parts, " | ") + " |")
|
||||||
|
+ output := strings.Join(parts, " | ") + " |"
|
||||||
|
+ if statusLineSession != "" {
|
||||||
|
+ setStatusLineCache(statusLineSession, output)
|
||||||
|
+ }
|
||||||
|
+ fmt.Print(output)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -617,7 +689,12 @@ func runRefineryStatusLine(t *tmux.Tmux, rigName string) error {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- fmt.Print(strings.Join(parts, " | ") + " |")
|
||||||
|
+ output := strings.Join(parts, " | ") + " |"
|
||||||
|
+ if statusLineSession != "" {
|
||||||
|
+ setStatusLineCache(statusLineSession, output)
|
||||||
|
+ }
|
||||||
|
+ fmt.Print(output)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user