ui

package
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 27, 2026 License: MIT Imports: 87 Imported by: 0

Documentation

Overview

Package ui implements the bubbletea TUI, SSH helpers, and CUE recipe execution for honey.

Index

Constants

View Source
const (
	StageFallbackDetect        = "fallback_detect"
	StageFallbackDetectFailed  = "fallback_detect_failed"
	StagePresignPutStart       = "presign_put_start"
	StagePresignPut            = "presign_put"
	StagePresignPutFailed      = "presign_put_failed"
	StagePresignGetStart       = "presign_get_start"
	StagePresignGet            = "presign_get"
	StagePresignGetFailed      = "presign_get_failed"
	StagePresignMultipartStart = "presign_multipart_start"
	StagePresignMultipart      = "presign_multipart"
	StagePresignMultipartAbort = "presign_multipart_aborted"
	StagePresignComplete       = "presign_complete"
	StagePresignCompleteFailed = "presign_complete_failed"
	StagePresignCleanup        = "presign_cleanup"
	StagePresignCleanupFailed  = "presign_cleanup_failed"
	StagePresignFallback       = "presign_falling_back_to_agent"
)

Fallback-path stage names. Emitted as the Stage field on AgentTransferEvent

Variables

This section is empty.

Functions

func BuildCueRecipeTranscript added in v0.2.8

func BuildCueRecipeTranscript(history [][]HostExecResult) string

BuildCueRecipeTranscript formats prior CUE step HostExecResult groups for an AI summarizer.

func CanTrueNASTunnel added in v0.3.0

func CanTrueNASTunnel(r hosts.Record) bool

CanTrueNASTunnel reports whether the Tunnel action can run for this TrueNAS row.

func CueHookNotifyRemote added in v0.2.8

func CueHookNotifyRemote(ctx context.Context, recipe cuetry.Recipe, stepNo int, kind cuetry.StepKind, phase, hostName string, notify *cuetry.RecipeNotify, body string)

CueHookNotifyRemote sends notify after a per-host hook; failures are logged only.

func CueStepNotifyAppendSuffix added in v0.2.8

func CueStepNotifyAppendSuffix(ctx context.Context, recipe cuetry.Recipe, stepNo int, kind cuetry.StepKind, notify *cuetry.RecipeNotify, body string) string

CueStepNotifyAppendSuffix sends notify after a successful AI step; returns text to append on missing receivers or send errors.

func CueStepNotifyRemote added in v0.2.8

func CueStepNotifyRemote(ctx context.Context, recipe cuetry.Recipe, stepNo int, kind cuetry.StepKind, notify *cuetry.RecipeNotify, body string)

CueStepNotifyRemote sends notify after a non-AI step; failures are logged only (no change to streamed host rows).

func DefaultLocalFilesRoot added in v0.2.8

func DefaultLocalFilesRoot() string

DefaultLocalFilesRoot returns the configured or home-directory root for local file browser paths.

func DetectTransferTargetRuntime added in v0.2.8

func DetectTransferTargetRuntime(cache *ClientCache, sshUser string, rec hosts.Record) (string, string, string, error)

DetectTransferTargetRuntime runs uname on the host to determine GOOS/GOARCH for agent binaries.

func DialDockerCheck added in v0.3.0

func DialDockerCheck(user string, r hosts.Record) error

DialDockerCheck verifies that a docker record can reach the Engine API (dial + close).

func DialSSHLeafForRecord added in v0.2.7

func DialSSHLeafForRecord(user string, r hosts.Record) (*ssh.Client, func(), error)

DialSSHLeafForRecord returns a leaf *ssh.Client for SSH to hosts.Record.PrimaryIP (same transport as the TUI). Kubernetes pod records are not supported for raw SSH in this helper.

func DialTrueNASUpstream added in v0.3.1

func DialTrueNASUpstream(ctx context.Context, _ string, r hosts.Record, address string) (net.Conn, error)

DialTrueNASUpstream provides an in-memory net.Conn proxied over the API shell.

func FormatCueStepHostResultsForNotify added in v0.2.8

func FormatCueStepHostResultsForNotify(stepNo int, group []HostExecResult) string

FormatCueStepHostResultsForNotify formats one step’s host results for notify bodies (non-AI steps).

func FormatTargetForDryRun

func FormatTargetForDryRun(r hosts.Record) string

FormatTargetForDryRun returns a string describing how the target will be connected to.

func GetExecutor

func GetExecutor(r hosts.Record) hostexec.Executor

GetExecutor returns the appropriate Executor for a host record.

func HostConnectableForTransfer added in v0.2.8

func HostConnectableForTransfer(r hosts.Record) bool

HostConnectableForTransfer reports whether a record can be dialed for SSH, k8s exec, or docker exec.

func HostsForRecipeMeta added in v0.3.0

func HostsForRecipeMeta(jobs []hosts.Record, limit int) []hosts.Record

HostsForRecipeMeta copies up to limit connectable host records for recipe-meta (web re-run).

func IsAgentTransferValidationError added in v0.2.8

func IsAgentTransferValidationError(err error) bool

IsAgentTransferValidationError reports whether err is an AgentTransferValidationError (HTTP 400 class input).

func IsSSHConnTransientError added in v0.2.8

func IsSSHConnTransientError(err error) bool

IsSSHConnTransientError reports whether err is a transport-level failure that often clears after closing the TCP/SSH session and dialing again (stale cache entry, local routing/socket glitch, reset by peer).

func LoadAISystemPromptFromConfigPath added in v0.2.8

func LoadAISystemPromptFromConfigPath(configPath string) string

LoadAISystemPromptFromConfigPath returns defaults.ai_system_prompt from the honey YAML at path, if loadable.

func LoadTransferConfigFromConfigPath added in v0.2.8

func LoadTransferConfigFromConfigPath(configPath string) config.TransferConfigEffective

LoadTransferConfigFromConfigPath returns the effective transfer config from the honey YAML at path. If path is empty or the file fails to load, returns defaults.

func NewPluginPostgresBridge added in v0.3.0

func NewPluginPostgresBridge(h *plugins.HostRunContext) plugins.PostgresBridge

NewPluginPostgresBridge returns a PostgresBridge for one plugin host invocation.

func NewPluginRemoteBridge added in v0.3.0

func NewPluginRemoteBridge(user string, record hosts.Record, cache *ClientCache, recipeDir, runAs string, env map[string]string, allowedPaths map[string]string) plugins.RemoteBridge

NewPluginRemoteBridge returns a RemoteBridge for one plugin host invocation.

func PrintStaticTable added in v0.2.6

func PrintStaticTable(records []hosts.Record) error

PrintStaticTable prints the records as an ASCII table to stdout and exits.

func RemoteCopyLocalToRemote added in v0.2.8

func RemoteCopyLocalToRemote(user string, record hosts.Record, localPath, remotePath string, cache *ClientCache) error

RemoteCopyLocalToRemote uploads a local file to the remote path.

func RemoteCopyRemoteToLocal added in v0.2.8

func RemoteCopyRemoteToLocal(user string, record hosts.Record, remotePath, localPath string, cache *ClientCache) error

RemoteCopyRemoteToLocal downloads a remote file to a local path.

func ResizeFromColsRows added in v0.2.7

func ResizeFromColsRows(cols, rows int) *remotecommand.TerminalSize

ResizeFromColsRows returns a terminal size for k8s remotecommand, or nil if cols or rows are non-positive.

func ResolveAgentTransferSigningHints added in v0.2.8

func ResolveAgentTransferSigningHints(configPath string, cloud AgentCloudBackend, ref *CloudBackendRef) (cloudtransfer.SigningHints, error)

ResolveAgentTransferSigningHints loads honey config when ref is set and fills AWS/GCP signing hints (same semantics as the web files API). configPath is the explicit or resolved honey YAML path.

func ResolveAppDialer added in v0.3.1

func ResolveAppDialer(_ context.Context, user string, rec hosts.Record, _ string) (proxy.Dialer, io.Closer, error)

ResolveAppDialer returns the correct proxy.Dialer and an optional io.Closer for any hosts.Record. It hides all provider-specific connection logic (SSH, K8s exec, TrueNAS shell API, etc.).

func ResolveAppDialerWithCache added in v0.3.1

func ResolveAppDialerWithCache(user string, rec hosts.Record, cache *ClientCache) (proxy.Dialer, io.Closer, error)

ResolveAppDialerWithCache returns an app proxy dialer, borrowing SSH clients from cache when available.

func ResolveLocalPathUnderRoot added in v0.2.8

func ResolveLocalPathUnderRoot(root, requested string) (string, error)

ResolveLocalPathUnderRoot resolves requested against root and ensures the result stays under root.

func RewritePluginConfigTunnelStep added in v0.3.0

func RewritePluginConfigTunnelStep(config []byte, pluginID string, tunnelCoord *RecipeTunnelCoordinator, sshUser string, target hosts.Record, execute bool) ([]byte, error)

RewritePluginConfigTunnelStep sets base_url from a recipe tunnel step endpoint. When pluginID is rclone, tunnel_step or a non-empty base_url is required on execute.

func RunCueRecipeSteps

func RunCueRecipeSteps(ctx context.Context, out io.Writer, recipe cuetry.Recipe, recipeDir string, records []hosts.Record, sshUser string, execute bool, cliEnv map[string]string, configPath string, aiSystemPromptFromCfg string, secretResolver cuetry.SecretResolver, pluginMgr *plugins.Manager, rec *SessionRecorder, obs metrics.Observer) error

RunCueRecipeSteps executes a CUE recipe over a slice of target records without streaming. cliEnv is merged into each command/script step's remote env (overrides recipe env on duplicate keys); nil is treated as empty. configPath is the resolved honey YAML path (may be empty); agent_transfer with cloud_backend_ref requires it. rec, when non-nil, records a batch .hrec.jsonl (plan on dry-run, result rows on execute). Caller must Close(rec).

func RunDockerWebTTY added in v0.3.0

func RunDockerWebTTY(
	ctx context.Context,
	user string,
	r hosts.Record,
	stdin io.Reader,
	stdout io.Writer,
	cols, rows int,
	resizeCh <-chan DockerTerminalSize,
) error

RunDockerWebTTY runs an interactive shell in a container with TTY over stdin/stdout.

func RunK8sPodWebTTY added in v0.2.7

func RunK8sPodWebTTY(
	ctx context.Context,
	r hosts.Record,
	stdin io.Reader,
	stdout, stderr io.Writer,
	cols, rows int,
	resizeCh <-chan *remotecommand.TerminalSize,
) error

RunK8sPodWebTTY runs an interactive shell in a Kubernetes pod with TTY over stdin/stdout/stderr, using the same dial path as the CLI (ephemeral debug container). Resize events are consumed from resizeCh.

func RunLogTUI added in v0.3.1

func RunLogTUI(ctx context.Context, user string, records []hosts.Record, opts LogOptions, cache *ClientCache) error

RunLogTUI starts the interactive log viewer.

func RunRecordingReplay added in v0.2.8

func RunRecordingReplay(recordDir, baseName string) error

RunRecordingReplay plays one .hrec.jsonl in a nested full-screen Bubble Tea view.

func RunTable

func RunTable(records []hosts.Record, sshUser string, opts RunTableOptions) error

RunTable shows an interactive table and optionally execs ssh. After SSH/Tunnel disconnects, it returns to the UI.

func RunTerminalInteractive added in v0.2.9

func RunTerminalInteractive(user string, r hosts.Record, console string) error

RunTerminalInteractive opens an interactive session (SSH, K8s, Docker, TrueNAS API shell, or Proxmox) on os.Stdin/Stdout.

func RunTrueNASTunnel added in v0.3.0

func RunTrueNASTunnel(ctx context.Context, _ string, r hosts.Record, localFwd string, out io.Writer) error

RunTrueNASTunnel listens locally and forwards each connection through the TrueNAS API shell dial bridge into the guest at remoteHost:remotePort (as seen from inside the guest).

func SSHClientCacheKey added in v0.2.8

func SSHClientCacheKey(user string, r hosts.Record) string

SSHClientCacheKey is the stable cache key for a pooled SSH client for (user, record).

func SetDockerSSHBorrowCache added in v0.3.0

func SetDockerSSHBorrowCache(c *ClientCache)

SetDockerSSHBorrowCache sets the TUI client cache used to reuse SSH for honey-ssh Docker transport.

func StartK8sPortForward added in v0.3.0

func StartK8sPortForward(ctx context.Context, r hosts.Record, localPort, remotePort int) (host string, port int, stop func(), err error)

StartK8sPortForward starts a non-blocking k8s port-forward; returns local listen host/port after readyCh.

func StartTrueNASForward added in v0.3.0

func StartTrueNASForward(ctx context.Context, user string, r hosts.Record, localFwd string) (host string, port int, stop func(), err error)

StartTrueNASForward starts a non-blocking TrueNAS API shell tunnel.

func StreamCueRecipeSteps

func StreamCueRecipeSteps(ctx context.Context, recipe cuetry.Recipe, recipeDir string, records []hosts.Record, sshUser string, cliEnv map[string]string, configPath string, aiSystemPromptFromCfg string, secretResolver cuetry.SecretResolver, pluginMgr *plugins.Manager, execute bool, obs metrics.Observer, out chan<- HostExecResult) error

StreamCueRecipeSteps executes a CUE recipe step-by-step, streaming results. configPath is the resolved honey YAML path (may be empty); agent_transfer steps with cloud_backend_ref require it. aiSystemPromptFromCfg is defaults.ai_system_prompt (already loaded), used only for the terminal ai step.

func StreamLogs added in v0.3.1

func StreamLogs(ctx context.Context, user string, records []hosts.Record, opts LogOptions, cache *ClientCache, out io.Writer) error

StreamLogs streams logs for records to out with stable per-record prefixes.

func StreamSFTPDownloadParallel

func StreamSFTPDownloadParallel(ctx context.Context, user string, jobs []SFTPDownloadJob, maxConc int, out chan<- HostExecResult, cache *ClientCache, retryCfg cuetry.RecipeStepRetry, obs metrics.Observer, attemptMax *atomic.Int32) error

StreamSFTPDownloadParallel downloads files from multiple hosts in parallel.

func StreamSFTPUploadParallel

func StreamSFTPUploadParallel(ctx context.Context, user string, recs []hosts.Record, localAbs, remotePath string, maxConc int, out chan<- HostExecResult, cache *ClientCache, retryCfg cuetry.RecipeStepRetry, obs metrics.Observer, attemptMax *atomic.Int32) error

StreamSFTPUploadParallel uploads the same local file to remotePath on each record (SFTP over DialHoneyClient). Failures on one host do not cancel others.

func StreamSSHParallel

func StreamSSHParallel(ctx context.Context, user string, jobs []hosts.Record, kvTunnel bool, remoteCmd SSHRemoteCmdFunc, maxConc int, out chan<- HostExecResult, cache *ClientCache, recipeKV *RecipeKVCoordinator, recipeScopedKV bool, post SSHPostHostResultFunc, retryCfg cuetry.RecipeStepRetry, obs metrics.Observer, attemptMax *atomic.Int32) error

StreamSSHParallel runs the command on records and streams results to out channel. It does not close the channel itself.

func StreamScriptUploadRunParallel

func StreamScriptUploadRunParallel(ctx context.Context, user string, recs []hosts.Record, localAbs, remotePath string, kvTunnel bool, remoteCmd SSHRemoteCmdFunc, maxConc int, out chan<- HostExecResult, cache *ClientCache, recipeKV *RecipeKVCoordinator, recipeScopedKV bool, post SSHPostHostResultFunc, retryCfg cuetry.RecipeStepRetry, obs metrics.Observer, attemptMax *atomic.Int32) error

StreamScriptUploadRunParallel uploads a script and executes it on multiple hosts in parallel.

func TransferStagingObjectKey added in v0.2.8

func TransferStagingObjectKey(cloud AgentCloudBackend, src, dst hosts.Record) string

TransferStagingObjectKey builds a unique object key when the caller leaves cloud.Object empty.

func TruncateCueTranscript added in v0.2.8

func TruncateCueTranscript(s string, maxChars int) string

TruncateCueTranscript limits transcript size for LLM input; keeps head and tail with a banner if truncated.

func TunnelLookupKeyForShare added in v0.3.0

func TunnelLookupKeyForShare(shareKey, derivedKey string) string

TunnelLookupKeyForShare returns a stable global pool key from recipe tunnel config.

func WrapRecordingReader added in v0.2.8

func WrapRecordingReader(inner io.Reader, recorder *SessionRecorder, direction string) io.Reader

WrapRecordingReader returns a Reader that tees reads into recorder when non-nil.

func WrapRecordingWriter added in v0.2.8

func WrapRecordingWriter(inner io.Writer, recorder *SessionRecorder, direction string) io.Writer

WrapRecordingWriter returns a Writer that tees writes into recorder when non-nil.

func WriteCueKVTunnelDryLine added in v0.2.8

func WriteCueKVTunnelDryLine(out io.Writer, recipe cuetry.Recipe, stepIdx int, step cuetry.RecipeStep, def *cuetry.RecipeDefaults)

WriteCueKVTunnelDryLine prints one plan line when kv_tunnel is enabled for the step or defaults.

func WriteCueSSHPrivateKeyDryLine added in v0.2.9

func WriteCueSSHPrivateKeyDryLine(out io.Writer, stepIdx int, step cuetry.RecipeStep, def *cuetry.RecipeDefaults)

WriteCueSSHPrivateKeyDryLine prints one plan line when ssh_private_key is set for the step or defaults.

func WriteCueStepHooksDryLines added in v0.2.8

func WriteCueStepHooksDryLines(out io.Writer, stepIdx int, step cuetry.RecipeStep)

WriteCueStepHooksDryLines prints one plan line per configured hook (no secrets).

func WriteCueStepNotifyDryLine added in v0.2.8

func WriteCueStepNotifyDryLine(out io.Writer, step cuetry.RecipeStep)

WriteCueStepNotifyDryLine prints one plan line when notify is enabled (boolean only; no secrets).

func WriteCueStepRetryDryLine added in v0.3.0

func WriteCueStepRetryDryLine(out io.Writer, stepIdx int, cfg cuetry.RecipeStepRetry)

WriteCueStepRetryDryLine prints retry settings when enabled.

Types

type AgentCloudBackend added in v0.2.8

type AgentCloudBackend struct {
	Provider string `json:"provider"`
	Bucket   string `json:"bucket"`
	Prefix   string `json:"prefix,omitempty"`
	Object   string `json:"object,omitempty"`
	Region   string `json:"region,omitempty"`
	Endpoint string `json:"endpoint,omitempty"`
}

AgentCloudBackend describes the cloud object target path for staging.

type AgentTransferEndpoint added in v0.2.8

type AgentTransferEndpoint struct {
	Record hosts.Record `json:"record"`
	Path   string       `json:"path"`
}

AgentTransferEndpoint identifies one source/destination endpoint for transfer.

type AgentTransferEvent added in v0.2.8

type AgentTransferEvent struct {
	Stage     string    `json:"stage"`
	Host      string    `json:"host,omitempty"`
	Success   bool      `json:"success"`
	Message   string    `json:"message,omitempty"`
	Error     string    `json:"error,omitempty"`
	Attempt   int       `json:"attempt,omitempty"`
	Timestamp time.Time `json:"timestamp"`
}

AgentTransferEvent is emitted for each orchestration stage.

func ExecuteAgentCloudTransfer added in v0.2.8

func ExecuteAgentCloudTransfer(job AgentTransferJob, cache *ClientCache) ([]AgentTransferEvent, error)

ExecuteAgentCloudTransfer orchestrates source upload and destination download using ephemeral transfer agents over existing HostClient connections (SSH / k8s pod exec abstraction).

func ExecuteAgentCloudTransferWithEmit added in v0.2.8

func ExecuteAgentCloudTransferWithEmit(job AgentTransferJob, cache *ClientCache, emit func(AgentTransferEvent)) ([]AgentTransferEvent, error)

ExecuteAgentCloudTransferWithEmit runs the transfer and calls emit for each event.

func RunAgentTransferWithFallback added in v0.2.8

func RunAgentTransferWithFallback(
	ctx context.Context,
	cache *ClientCache,
	sshUser, agentOverride, preferredAgentPath, agentBuildCacheDir, agentRemoteDir string,
	src, dst hosts.Record,
	srcPath, dstPath string,
	cloud AgentCloudBackend,
	keepObject bool,
	maxRetries int,
	hints cloudtransfer.SigningHints,
	transferCfg config.TransferConfigEffective,
	emit func(AgentTransferEvent),
) ([]AgentTransferEvent, error)

RunAgentTransferWithFallback runs Build + Execute, transparently retrying via the agent path on fallback-path failure when transferCfg.PresignedRetryWithAgent is true. Returns the combined event timeline across both attempts so the caller always sees the full record.

emit may be nil; when non-nil it receives events as they happen for both attempts (the original fallback-path attempt and the agent-path retry).

type AgentTransferJob added in v0.2.8

type AgentTransferJob struct {
	SSHUser                 string                `json:"ssh_user"`
	ResolvedSourceUser      string                `json:"resolved_source_user"`
	ResolvedDestUser        string                `json:"resolved_dest_user"`
	AgentLocalPath          string                `json:"agent_local_path"`
	SourceAgentLocalPath    string                `json:"source_agent_local_path,omitempty"`
	DestAgentLocalPath      string                `json:"dest_agent_local_path,omitempty"`
	AgentRemoteDir          string                `json:"agent_remote_dir,omitempty"`
	Source                  AgentTransferEndpoint `json:"source"`
	Destination             AgentTransferEndpoint `json:"destination"`
	Cloud                   AgentCloudBackend     `json:"cloud"`
	CredentialProvider      string                `json:"credential_provider,omitempty"`
	CredentialEnv           map[string]string     `json:"credential_env,omitempty"`
	CredentialExpiresAtUnix int64                 `json:"credential_expires_at_unix,omitempty"`
	KeepObject              bool                  `json:"keep_object,omitempty"`
	MaxRetries              int                   `json:"max_retries,omitempty"`
	// FallbackPlan is non-nil when the curl-based presigned-URL transport should be
	// used instead of the staged-agent path. See docs/superpowers/specs/2026-05-12-presigned-url-transfer-path-design.md.
	FallbackPlan          *presign.Plan `json:"-"`
	FallbackCapabilitySrc string        `json:"-"`
	FallbackCapabilityDst string        `json:"-"`
	// RetryWithAgentOnCurlFailure controls whether a fallback-path failure transparently
	// retries via the agent path.
	RetryWithAgentOnCurlFailure bool `json:"retry_with_agent_on_curl_failure,omitempty"`
}

AgentTransferJob describes one A->cloud->B transfer orchestration request.

func BuildAgentTransferJob added in v0.2.8

func BuildAgentTransferJob(
	ctx context.Context,
	cache *ClientCache,
	sshUser, agentOverride, preferredAgentPath, agentBuildCacheDir, agentRemoteDir string,
	src, dst hosts.Record,
	srcPath, dstPath string,
	cloud AgentCloudBackend,
	keepObject bool,
	maxRetries int,
	hints cloudtransfer.SigningHints,
	transferCfg config.TransferConfigEffective,
) (AgentTransferJob, error)

BuildAgentTransferJob wires cloud credentials, per-target agent binaries, and staging object key. preferredAgentPath is used when agentOverride is empty (e.g. web server default binary); agentBuildCacheDir overrides the directory for cross-compiled agents (empty uses HONEY_TRANSFER_AGENT_CACHE or os temp).

transferCfg controls whether the fallback-path (presigned-URL) transport is attempted before falling back to staging the transfer-agent binary. When transferCfg.ForceAgentPath is true, the curl branch is bypassed.

type AgentTransferValidationError added in v0.2.8

type AgentTransferValidationError struct {
	// contains filtered or unexported fields
}

AgentTransferValidationError indicates user/input issues (HTTP 400).

func (*AgentTransferValidationError) Error added in v0.2.8

type AppDialerTransport added in v0.3.1

type AppDialerTransport string

AppDialerTransport describes the transport used to reach an app upstream.

const (
	// AppDialerTransportSSH means the upstream is reached through a regular SSH client.
	AppDialerTransportSSH AppDialerTransport = "ssh"
	// AppDialerTransportInMemory means the upstream is reached through a provider-native tunnel.
	AppDialerTransportInMemory AppDialerTransport = "in-memory"
)

func TransportForAppDialer added in v0.3.1

func TransportForAppDialer(rec hosts.Record) AppDialerTransport

TransportForAppDialer returns the transport family used for a record's app upstream connection.

type ClientCache

type ClientCache struct {
	// contains filtered or unexported fields
}

ClientCache maintains a pool of open HostClient connections for reuse across steps.

func NewClientCache

func NewClientCache() *ClientCache

NewClientCache creates a new initialized ClientCache.

func (*ClientCache) AcquireLease added in v0.3.1

func (c *ClientCache) AcquireLease(user string, r hosts.Record) (*ClientLease, error)

AcquireLease returns a cached client and tracks a lightweight borrow for app proxy sessions.

func (*ClientCache) CloseAll

func (c *ClientCache) CloseAll()

CloseAll closes all cached connections and clears the cache.

func (*ClientCache) Evict added in v0.2.8

func (c *ClientCache) Evict(user string, r hosts.Record)

Evict removes the cached client for this host (if any) and closes it so the next GetOrDial establishes a fresh connection.

func (*ClientCache) GetOrDial

func (c *ClientCache) GetOrDial(user string, r hosts.Record) (HostClient, error)

GetOrDial returns an existing connection or dials a new one and stores it.

type ClientLease added in v0.3.1

type ClientLease struct {
	// contains filtered or unexported fields
}

ClientLease is a borrowed cached host connection. Close releases the borrow without directly closing the shared underlying connection.

func (*ClientLease) Close added in v0.3.1

func (l *ClientLease) Close() error

Close releases the lease. The cached connection remains available until eviction or CloseAll.

func (*ClientLease) HostClient added in v0.3.1

func (l *ClientLease) HostClient() HostClient

HostClient returns the borrowed client.

type CloudBackendRef added in v0.2.8

type CloudBackendRef struct {
	Kind  string `json:"kind"`
	Name  string `json:"name,omitempty"`
	Index *int   `json:"index,omitempty"`
}

CloudBackendRef selects a backend entry from honey YAML for agent-transfer signing hints.

type DockerTerminalSize added in v0.3.0

type DockerTerminalSize struct {
	Cols int
	Rows int
}

DockerTerminalSize is a cols/rows pair for docker exec resize.

type Executor

type Executor = hostexec.Executor

Executor aliases the shared executor interface.

type GlobalTunnelPool added in v0.3.0

type GlobalTunnelPool struct {
	// contains filtered or unexported fields
}

GlobalTunnelPool caches active tunnels keyed by share_key or derived spec hash.

func DefaultGlobalTunnelPool added in v0.3.0

func DefaultGlobalTunnelPool() *GlobalTunnelPool

DefaultGlobalTunnelPool returns the process-wide tunnel pool.

func NewGlobalTunnelPool added in v0.3.0

func NewGlobalTunnelPool(ttl time.Duration) *GlobalTunnelPool

NewGlobalTunnelPool creates a pool with the given idle TTL (0 = default 30m).

func (*GlobalTunnelPool) Acquire added in v0.3.0

func (p *GlobalTunnelPool) Acquire(ctx context.Context, key string, factory func(context.Context) (TunnelEndpoint, func(), error)) (TunnelEndpoint, func(), error)

Acquire returns an endpoint, creating via factory on miss. release() decrements refcount.

func (*GlobalTunnelPool) Close added in v0.3.0

func (p *GlobalTunnelPool) Close()

Close stops all entries and the sweeper.

type HostClient

type HostClient = hostexec.HostClient

HostClient aliases the shared execution interface (see internal/hostexec).

type HostExecResult

type HostExecResult struct {
	Name     string
	IP       string
	Provider string
	Success  bool
	Skipped  bool // when CEL was false; no SSH/SFTP ran
	ExitCode int
	Output   string
	ErrMsg   string // transport / spawn failure (not remote stderr)

	// HookPhase / HookOutput are set when a CUE step hook ran after the main result (command/script only).
	HookPhase  string // "on_success" or "on_failure"
	HookOutput string // captured stdout+stderr from the hook (local or remote)
}

HostExecResult is the outcome of one non-interactive ssh run.

func ExecuteSFTPDownloadParallel

func ExecuteSFTPDownloadParallel(user string, jobs []SFTPDownloadJob, maxConc int) ([]HostExecResult, error)

ExecuteSFTPDownloadParallel runs each download job (possibly different local paths per host) in parallel.

func ExecuteSFTPUploadParallel

func ExecuteSFTPUploadParallel(user string, recs []hosts.Record, localAbs, remotePath string, maxConc int) ([]HostExecResult, error)

ExecuteSFTPUploadParallel executes an SFTP upload in parallel across multiple hosts and returns results synchronously.

func ExecuteSSHParallel

func ExecuteSSHParallel(user string, recs []hosts.Record, remoteCmdFunc func(hosts.Record) string, maxConc int) ([]HostExecResult, error)

ExecuteSSHParallel runs the same remote shell command on every record that has PrimaryIP set. Failures on individual hosts do not cancel others. It uses DialHoneyClient (golang.org/x/crypto/ssh + ~/.ssh/config) with known_hosts verification.

func ExecuteScriptUploadRunParallel

func ExecuteScriptUploadRunParallel(user string, recs []hosts.Record, localAbs, remotePath, remoteCmd string, maxConc int) ([]HostExecResult, error)

ExecuteScriptUploadRunParallel uploads localAbs to remotePath on each host over SFTP, then runs remoteCmd on the same SSH connection (one session per host per step).

func RunOneSFTPUploadWithProgress added in v0.2.8

func RunOneSFTPUploadWithProgress(user string, r hosts.Record, localAbs, remotePath string, cache *ClientCache, onProgress func(written, total int64)) HostExecResult

RunOneSFTPUploadWithProgress uploads one local file to remotePath on r, like runOneSFTPUpload. onProgress is optional; it receives cumulative bytes written toward the remote and the local file size. Live updates are emitted for *sshclient.HoneyClient (SFTP); other executors only report start/end.

func SortHostExecForUI

func SortHostExecForUI(s []HostExecResult) []HostExecResult

SortHostExecForUI orders failures first, then host name (case-insensitive).

type HostExecRetryOutcome added in v0.3.0

type HostExecRetryOutcome struct {
	Result              HostExecResult
	Attempts            int
	LastAttemptDuration time.Duration
}

HostExecRetryOutcome is the result of runHostExecWithRetry.

type LocalFileEntry added in v0.2.8

type LocalFileEntry struct {
	Name       string    `json:"name"`
	Path       string    `json:"path"`
	IsDir      bool      `json:"is_dir"`
	Size       int64     `json:"size"`
	Mode       string    `json:"mode"`
	ModifiedAt time.Time `json:"modified_at"`
}

LocalFileEntry mirrors RemoteFileEntry for local directories.

func ListLocalDirUnderRoot added in v0.2.8

func ListLocalDirUnderRoot(root, requested string) (string, []LocalFileEntry, error)

ListLocalDirUnderRoot lists a directory under the resolved root path.

type LogOptions added in v0.3.1

type LogOptions struct {
	Target         string
	Source         string
	Follow         bool
	Tail           int64
	Since          time.Duration
	Timestamps     bool
	Container      string
	Unit           string
	Command        string
	RunAs          string
	MaxConcurrency int
	Grep           string
	Labels         []string
	Highlight      bool
}

LogOptions controls distributed log streaming.

type LogViewModel added in v0.3.1

type LogViewModel struct {
	// contains filtered or unexported fields
}

LogViewModel is the Bubble Tea model for the log viewer.

func NewLogViewModel added in v0.3.1

func NewLogViewModel(opts LogOptions) *LogViewModel

NewLogViewModel creates a new log view model.

func (*LogViewModel) Init added in v0.3.1

func (m *LogViewModel) Init() tea.Cmd

Init initializes the log view model.

func (*LogViewModel) Update added in v0.3.1

func (m *LogViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update handles messages and updates the log view model.

func (*LogViewModel) View added in v0.3.1

func (m *LogViewModel) View() tea.View

View renders the log viewer UI.

type RecipeKVCoordinator added in v0.2.8

type RecipeKVCoordinator struct {
	// contains filtered or unexported fields
}

RecipeKVCoordinator owns one operator-side stepkv session for a cue-exec run and one forward (SSH remote-forward or k8s exec bridge) per cached client key. The mutex is only held while the per-key placeholder is reserved; the slow handshake runs outside the lock so parallel hosts don't serialize.

func NewRecipeKVCoordinator added in v0.2.8

func NewRecipeKVCoordinator(ttl time.Duration) *RecipeKVCoordinator

NewRecipeKVCoordinator constructs a coordinator; ttl defaults to stepKVTunnelTTL when <= 0.

func (*RecipeKVCoordinator) Close added in v0.2.8

func (c *RecipeKVCoordinator) Close()

Close stops all remote listeners / k8s bridges and closes the stepkv session.

func (*RecipeKVCoordinator) EnsureK8sExecBridgeEnv added in v0.2.8

func (c *RecipeKVCoordinator) EnsureK8sExecBridgeEnv(user string, r hosts.Record, k8c *k8sNativeClient) (map[string]string, error)

EnsureK8sExecBridgeEnv returns HONEY_KV_* for this pod by multiplexing pod loopback HTTP to the shared stepkv session over a long-lived kubectl exec.

func (*RecipeKVCoordinator) EnsureKVTunnelEnv added in v0.2.8

func (c *RecipeKVCoordinator) EnsureKVTunnelEnv(user string, r hosts.Record, hc *sshclient.HoneyClient) (map[string]string, error)

EnsureKVTunnelEnv returns HONEY_KV_* for this host's remote-forward into the shared session.

func (*RecipeKVCoordinator) EnsureSession added in v0.2.9

func (c *RecipeKVCoordinator) EnsureSession() (*stepkv.Session, error)

EnsureSession returns the shared stepkv session, creating it if needed (no SSH forward).

func (*RecipeKVCoordinator) EnsureTrueNASAPIShellBridgeEnv added in v0.3.0

func (c *RecipeKVCoordinator) EnsureTrueNASAPIShellBridgeEnv(ctx context.Context, user string, r hosts.Record, cache *ClientCache) (map[string]string, error)

EnsureTrueNASAPIShellBridgeEnv attaches kv_tunnel for a TrueNAS row into the shared recipe stepkv session.

func (*RecipeKVCoordinator) InvalidateHost added in v0.2.8

func (c *RecipeKVCoordinator) InvalidateHost(user string, r hosts.Record)

InvalidateHost tears down this host's remote-forward or k8s exec bridge only (e.g. after cache evict). The shared stepkv session stays open for other hosts.

type RecipeMeta added in v0.2.8

type RecipeMeta struct {
	RecipePath        string         `json:"recipe_path"`
	HostCount         int            `json:"host_count"`
	RecipeContentHash string         `json:"recipe_content_hash"`
	StartedAt         time.Time      `json:"started_at"`
	Hosts             []hosts.Record `json:"hosts,omitempty"`
}

RecipeMeta describes the recipe that a cue-exec batch is about to run. Recorded into the session file so a later "recent runs" enumeration can attribute the recording to a recipe and detect in-browser edits.

type RecipeTunnelCoordinator added in v0.3.0

type RecipeTunnelCoordinator struct {
	// contains filtered or unexported fields
}

RecipeTunnelCoordinator tracks tunnel endpoints for one cue-exec run and releases pool refs on Close.

func NewRecipeTunnelCoordinator added in v0.3.0

func NewRecipeTunnelCoordinator(pool *GlobalTunnelPool) *RecipeTunnelCoordinator

NewRecipeTunnelCoordinator creates a coordinator backed by the process-wide pool.

func (*RecipeTunnelCoordinator) Acquire added in v0.3.0

func (c *RecipeTunnelCoordinator) Acquire(ctx context.Context, key string, factory func(context.Context) (TunnelEndpoint, func(), error)) (TunnelEndpoint, func(), error)

Acquire obtains or creates a tunnel from the global pool.

func (*RecipeTunnelCoordinator) Close added in v0.3.0

func (c *RecipeTunnelCoordinator) Close()

Close releases all pool references held by this run.

func (*RecipeTunnelCoordinator) Lookup added in v0.3.0

func (c *RecipeTunnelCoordinator) Lookup(stepID, user string, r hosts.Record) (TunnelEndpoint, bool)

Lookup returns the endpoint for a tunnel step id and host.

func (*RecipeTunnelCoordinator) LookupEndpoint added in v0.3.0

func (c *RecipeTunnelCoordinator) LookupEndpoint(stepID, user string, r hosts.Record) (string, int, bool)

LookupEndpoint implements plugins.TunnelCoordinator for postgres DSN rewrite.

func (*RecipeTunnelCoordinator) Register added in v0.3.0

func (c *RecipeTunnelCoordinator) Register(stepID, user string, r hosts.Record, ep TunnelEndpoint, release func())

Register stores an endpoint for tunnel_step lookup and holds the pool release until Close.

type RemoteFileEntry added in v0.2.8

type RemoteFileEntry = hostexec.RemoteFileEntry

RemoteFileEntry aliases remote file metadata for JSON APIs.

func RemoteListDir added in v0.2.8

func RemoteListDir(user string, record hosts.Record, remotePath string, cache *ClientCache) ([]RemoteFileEntry, error)

RemoteListDir lists a directory on the remote host using a cached SSH/k8s client.

type RunTableOptions added in v0.2.8

type RunTableOptions struct {
	RecordDir     string
	RecordEnabled bool
	// Config is the honey YAML already loaded for this session (optional; nil if none / load failed).
	Config *config.File
	// ConfigPath is the resolved honey YAML path (may be empty); CUE agent_transfer steps with cloud_backend_ref need it.
	ConfigPath string
	// ClientCache is an optional shared SSH client cache. If nil, one is created.
	ClientCache *ClientCache
}

RunTableOptions configures optional session recording for the TUI table.

type SFTPDownloadJob

type SFTPDownloadJob struct {
	Record     hosts.Record
	LocalAbs   string
	RemotePath string
}

SFTPDownloadJob is one remote→local file copy for a specific host.

type SSHPostHostResultFunc added in v0.2.8

type SSHPostHostResultFunc func(ctx context.Context, r hosts.Record, res *HostExecResult)

SSHPostHostResultFunc runs after each host's main SSH run and before the result is emitted (e.g. CUE step hooks). It may set res.HookPhase and res.HookOutput. Hook failures must not change the original step success fields.

type SSHRemoteCmdFunc added in v0.2.8

type SSHRemoteCmdFunc func(r hosts.Record, kv map[string]string) string

SSHRemoteCmdFunc builds the remote shell string. kv is nil when kv_tunnel is disabled; otherwise it contains HONEY_KV_URL (reachable from the remote via SSH remote forward) and HONEY_KV_TOKEN for Authorization.

type SessionRecorder added in v0.2.8

type SessionRecorder struct {
	// contains filtered or unexported fields
}

SessionRecorder appends JSONL events to a single .hrec.jsonl file (TTY data, resize, errors, close).

func NewBatchSessionRecorder added in v0.2.8

func NewBatchSessionRecorder(dir, trigger, user string, jobCount int) (*SessionRecorder, error)

NewBatchSessionRecorder creates a recorder for one parallel exec or CUE batch run (one file per invocation).

func NewSessionRecorder added in v0.2.8

func NewSessionRecorder(opts SessionRecorderOptions) (*SessionRecorder, error)

NewSessionRecorder creates a recorder writing to opts.Dir with a timestamped filename.

func (*SessionRecorder) Close added in v0.2.8

func (r *SessionRecorder) Close() error

Close writes a "close" event and closes the underlying file.

func (*SessionRecorder) Path added in v0.2.8

func (r *SessionRecorder) Path() string

Path returns the absolute path of the recording file, or empty if r is nil.

func (*SessionRecorder) RecordData added in v0.2.8

func (r *SessionRecorder) RecordData(direction string, payload []byte)

RecordData writes a base64-encoded payload for the given direction (e.g. in/out).

func (*SessionRecorder) RecordError added in v0.2.8

func (r *SessionRecorder) RecordError(err error)

RecordError records a non-fatal error message on the session.

func (*SessionRecorder) RecordHostExecResult added in v0.2.8

func (r *SessionRecorder) RecordHostExecResult(res HostExecResult)

RecordHostExecResult writes one structured "result" event (parallel exec / batch output).

func (*SessionRecorder) RecordRecipeMeta added in v0.2.8

func (r *SessionRecorder) RecordRecipeMeta(meta RecipeMeta)

RecordRecipeMeta writes one "recipe-meta" structured event into the recording. Safe to call on a nil recorder.

func (*SessionRecorder) RecordResize added in v0.2.8

func (r *SessionRecorder) RecordResize(cols, rows int)

RecordResize records a terminal resize event.

func (*SessionRecorder) RecordingFileBase added in v0.3.0

func (r *SessionRecorder) RecordingFileBase() string

RecordingFileBase returns the recording filename (e.g. 20260102_120000_web-cue-exec_batch_mixed_batch-3.hrec.jsonl).

func (*SessionRecorder) RecordingID added in v0.3.0

func (r *SessionRecorder) RecordingID() string

RecordingID returns the recording id (filename without .hrec.jsonl).

type SessionRecorderOptions added in v0.2.8

type SessionRecorderOptions struct {
	Dir      string
	Trigger  string
	Mode     string
	Provider string
	HostName string
	HostIP   string
	User     string
	// HostSegment, when set, is used for the filename segment instead of HostName/IP (e.g. batch-12).
	HostSegment string
}

SessionRecorderOptions configures filename segments and metadata for a new session recording.

type TunnelEndpoint added in v0.3.0

type TunnelEndpoint struct {
	Host       string
	Port       int
	Mode       string
	TunName    string
	RemoteHost string
	RemotePort int
	ShareKey   string
}

TunnelEndpoint describes an operator-side listen address for a recipe tunnel.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL