Files
kandev/apps/backend/internal/agent/executor/executor.go
T
José Almeida 99404133d4 feat(backend): add SSH executor runtime
Run agents on any Linux box reachable over SSH: own VPS, homelab, EC2,
shared dev box. One SSH connection per (host, user, identity) shared
across all sessions on that host; each session gets its own remote
agentctl process, remote port, and SSH-tunneled local port. Mirrors the
local ~/.kandev/tasks/<task-dir>/<repo>/ layout on the remote so
multi-session tasks share a worktree and per-session runtime state lives
under the task dir.

Implements ExecutorBackend + RemoteSessionResumer + RemoteStatusProvider
+ Closeable. Host-key trust is explicit: the test endpoint observes a
fingerprint without pinning; the user trusts it in settings; subsequent
connects reject any mismatch. Auth via ssh-agent or IdentityFile only
(passphrase-protected keys must be loaded into ssh-agent). Parses
~/.ssh/config for HostName/Port/User/IdentityFile/ProxyJump inheritance.
agentctl is content-hash-cached on the remote (~/.kandev/bin/agentctl
plus a .sha256 sidecar) and uploaded only when local and remote differ.
Linux/amd64 only in v1, matching Docker's current state; arm64 is
called out as a cross-cutting follow-up.

See docs/specs/ssh-executor/spec.md.
2026-05-17 23:28:50 +01:00

45 lines
1.4 KiB
Go

// Package executor defines the agent executor types shared across lifecycle and policy logic.
package executor
import (
"github.com/kandev/kandev/internal/agentruntime"
"github.com/kandev/kandev/internal/task/models"
)
// Name identifies the execution backend. It aliases agentruntime.Runtime
// so the executor and runtime layers share a single typed vocabulary
// without forcing every existing consumer to switch import paths.
type Name = agentruntime.Runtime
const (
NameUnknown Name = ""
NameDocker = agentruntime.RuntimeDocker
NameStandalone = agentruntime.RuntimeStandalone
NameLocal Name = "local"
NameRemoteDocker = agentruntime.RuntimeRemoteDocker
NameSprites = agentruntime.RuntimeSprites
NameSSH = agentruntime.RuntimeSSH
)
// ExecutorTypeToBackend maps an ExecutorType to its corresponding executor Name.
func ExecutorTypeToBackend(execType models.ExecutorType) Name {
switch execType {
case models.ExecutorTypeLocal:
return NameStandalone
case models.ExecutorTypeWorktree:
return NameStandalone
case models.ExecutorTypeLocalDocker:
return NameDocker
case models.ExecutorTypeRemoteDocker:
return NameRemoteDocker
case models.ExecutorTypeSprites:
return NameSprites
case models.ExecutorTypeSSH:
return NameSSH
case models.ExecutorTypeMockRemote:
return NameStandalone
default:
return NameStandalone
}
}