Explains that autonomous roles (polecat, witness, refinery, deacon) get automatic mail injection on startup since they operate without human prompting. Non-autonomous roles (mayor, crew) skip this. Closes: gt-pawy3
102 lines
2.8 KiB
Go
102 lines
2.8 KiB
Go
// Package runtime provides helpers for runtime-specific integration.
|
|
package runtime
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/steveyegge/gastown/internal/claude"
|
|
"github.com/steveyegge/gastown/internal/config"
|
|
"github.com/steveyegge/gastown/internal/opencode"
|
|
"github.com/steveyegge/gastown/internal/tmux"
|
|
)
|
|
|
|
// EnsureSettingsForRole installs runtime hook settings when supported.
|
|
func EnsureSettingsForRole(workDir, role string, rc *config.RuntimeConfig) error {
|
|
if rc == nil {
|
|
rc = config.DefaultRuntimeConfig()
|
|
}
|
|
|
|
if rc.Hooks == nil {
|
|
return nil
|
|
}
|
|
|
|
switch rc.Hooks.Provider {
|
|
case "claude":
|
|
return claude.EnsureSettingsForRoleAt(workDir, role, rc.Hooks.Dir, rc.Hooks.SettingsFile)
|
|
case "opencode":
|
|
return opencode.EnsurePluginAt(workDir, rc.Hooks.Dir, rc.Hooks.SettingsFile)
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// SessionIDFromEnv returns the runtime session ID, if present.
|
|
// It checks GT_SESSION_ID_ENV first, then falls back to CLAUDE_SESSION_ID.
|
|
func SessionIDFromEnv() string {
|
|
if envName := os.Getenv("GT_SESSION_ID_ENV"); envName != "" {
|
|
if sessionID := os.Getenv(envName); sessionID != "" {
|
|
return sessionID
|
|
}
|
|
}
|
|
return os.Getenv("CLAUDE_SESSION_ID")
|
|
}
|
|
|
|
// SleepForReadyDelay sleeps for the runtime's configured readiness delay.
|
|
func SleepForReadyDelay(rc *config.RuntimeConfig) {
|
|
if rc == nil || rc.Tmux == nil {
|
|
return
|
|
}
|
|
if rc.Tmux.ReadyDelayMs <= 0 {
|
|
return
|
|
}
|
|
time.Sleep(time.Duration(rc.Tmux.ReadyDelayMs) * time.Millisecond)
|
|
}
|
|
|
|
// StartupFallbackCommands returns commands that approximate Claude hooks when hooks are unavailable.
|
|
func StartupFallbackCommands(role string, rc *config.RuntimeConfig) []string {
|
|
if rc == nil {
|
|
rc = config.DefaultRuntimeConfig()
|
|
}
|
|
if rc.Hooks != nil && rc.Hooks.Provider != "" && rc.Hooks.Provider != "none" {
|
|
return nil
|
|
}
|
|
|
|
role = strings.ToLower(role)
|
|
command := "gt prime"
|
|
if isAutonomousRole(role) {
|
|
command += " && gt mail check --inject"
|
|
}
|
|
command += " && gt nudge deacon session-started"
|
|
|
|
return []string{command}
|
|
}
|
|
|
|
// RunStartupFallback sends the startup fallback commands via tmux.
|
|
func RunStartupFallback(t *tmux.Tmux, sessionID, role string, rc *config.RuntimeConfig) error {
|
|
commands := StartupFallbackCommands(role, rc)
|
|
for _, cmd := range commands {
|
|
if err := t.NudgeSession(sessionID, cmd); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// isAutonomousRole returns true if the given role should automatically
|
|
// inject mail check on startup. Autonomous roles (polecat, witness,
|
|
// refinery, deacon) operate without human prompting and need mail injection
|
|
// to receive work assignments.
|
|
//
|
|
// Non-autonomous roles (mayor, crew) are human-guided and should not
|
|
// have automatic mail injection to avoid confusion.
|
|
func isAutonomousRole(role string) bool {
|
|
switch role {
|
|
case "polecat", "witness", "refinery", "deacon":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|