go-ml/agent_ssh.go
Snider eae9ec9b38 refactor: split agent.go (1070 LOC) into 5 focused files
Decompose monolithic agent.go into concern-based files:
- agent_config.go (97 LOC): AgentConfig, Checkpoint, model maps
- agent_execute.go (215 LOC): RunAgentLoop, discovery, scoring dispatch
- agent_eval.go (397 LOC): MLX native + conversion eval, capability/content probes
- agent_influx.go (291 LOC): InfluxDB scoring push, buffer/replay
- agent_ssh.go (102 LOC): SSH/SCP helpers, env utilities

No functional changes. All tests pass.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 03:05:11 +00:00

102 lines
2.5 KiB
Go

package ml
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
// SSHCommand executes a command on M3 via SSH.
func SSHCommand(cfg *AgentConfig, cmd string) (string, error) {
sshArgs := []string{
"-o", "ConnectTimeout=10",
"-o", "BatchMode=yes",
"-o", "StrictHostKeyChecking=no",
"-i", cfg.M3SSHKey,
fmt.Sprintf("%s@%s", cfg.M3User, cfg.M3Host),
cmd,
}
result, err := exec.Command("ssh", sshArgs...).CombinedOutput()
if err != nil {
return "", fmt.Errorf("ssh %q: %w: %s", cmd, err, strings.TrimSpace(string(result)))
}
return string(result), nil
}
// SCPFrom copies a file from M3 to a local path.
func SCPFrom(cfg *AgentConfig, remotePath, localPath string) error {
os.MkdirAll(filepath.Dir(localPath), 0755)
scpArgs := []string{
"-o", "ConnectTimeout=10",
"-o", "BatchMode=yes",
"-o", "StrictHostKeyChecking=no",
"-i", cfg.M3SSHKey,
fmt.Sprintf("%s@%s:%s", cfg.M3User, cfg.M3Host, remotePath),
localPath,
}
result, err := exec.Command("scp", scpArgs...).CombinedOutput()
if err != nil {
return fmt.Errorf("scp %s: %w: %s", remotePath, err, strings.TrimSpace(string(result)))
}
return nil
}
// SCPTo copies a local file to M3.
func SCPTo(cfg *AgentConfig, localPath, remotePath string) error {
scpArgs := []string{
"-o", "ConnectTimeout=10",
"-o", "BatchMode=yes",
"-o", "StrictHostKeyChecking=no",
"-i", cfg.M3SSHKey,
localPath,
fmt.Sprintf("%s@%s:%s", cfg.M3User, cfg.M3Host, remotePath),
}
result, err := exec.Command("scp", scpArgs...).CombinedOutput()
if err != nil {
return fmt.Errorf("scp to %s: %w: %s", remotePath, err, strings.TrimSpace(string(result)))
}
return nil
}
// fileBase returns the last component of a path.
func fileBase(path string) string {
if i := strings.LastIndexAny(path, "/\\"); i >= 0 {
return path[i+1:]
}
return path
}
// EnvOr returns the environment variable value or a fallback.
func EnvOr(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
// IntEnvOr returns the integer environment variable value or a fallback.
func IntEnvOr(key string, fallback int) int {
v := os.Getenv(key)
if v == "" {
return fallback
}
var n int
fmt.Sscanf(v, "%d", &n)
if n == 0 {
return fallback
}
return n
}
// ExpandHome expands ~ to the user's home directory.
func ExpandHome(path string) string {
if strings.HasPrefix(path, "~/") {
home, err := os.UserHomeDir()
if err == nil {
return filepath.Join(home, path[2:])
}
}
return path
}