Documentation
¶
Index ¶
- Constants
- Variables
- func AgentSourceLocal() bool
- func Cleanup(unique string)
- func CleanupAll()
- func CopyFile(src, dst string) error
- func Download(ctx context.Context, p *resources.Agent) error
- func DownloadURL(p *resources.Agent) string
- func Downloaded(ctx context.Context, p *resources.Agent) (bool, error)
- func FindLocalLatest(ctx context.Context, agent *resources.Agent) error
- func MoveFile(src, dst string) error
- func PinToLatestRelease(ctx context.Context, agent *resources.Agent) error
- func PlatformSuffix() string
- func ResolveLatest(ctx context.Context, agent *resources.Agent) error
- func ValidURL(s string) bool
- type AgentConn
- type AgentStore
- type GithubSource
- type LoadOption
- type NixStore
- type OCIStore
- type ProcessInfo
Constants ¶
const AgentSourceEnv = "CODEFLY_AGENT_SOURCE"
AgentSourceEnv selects where "latest" agent versions are resolved from.
- "" or "remote" (default): GitHub releases first, fall back to local.
- "local": scan ~/.codefly/agents/ only, never call GitHub.
Set via the CLI's `--local-agents` persistent flag or by exporting CODEFLY_AGENT_SOURCE=local. Useful for offline work and for agent development where the local build is the source of truth.
const DefaultDialTimeout = 10 * time.Second
DefaultDialTimeout is how long Load waits for the gRPC connection to become ready after dialing.
const DefaultStartupTimeout = 30 * time.Second
DefaultStartupTimeout is how long Load waits for the agent to print its handshake line before giving up.
Variables ¶
var ( // ErrAgentNil is returned by Load when called with a nil agent ref. // Programmer error — should never reach the user. ErrAgentNil = errors.New("agent: nil reference") // ErrAgentBinaryNotFound is returned when the agent binary cannot be // resolved via local cache, NixStore, OCIStore, or GitHub. // Remediation: `codefly agent build`, set AGENT_NIX_FLAKE / // AGENT_REGISTRY, or check publisher/name/version in the agent ref. ErrAgentBinaryNotFound = errors.New("agent: binary not found") // ErrAgentSpawn is returned when exec.Cmd.Start fails. Almost always // a permissions issue (binary not executable) or kernel exec failure. ErrAgentSpawn = errors.New("agent: spawn failed") // ErrAgentHandshakeTimeout is returned when the agent process did // not print its VERSION|PORT handshake within startupTimeout. // Remediation: check the agent's stderr (via AgentConn.StderrTail // after Close, or pass a logWriter) for the panic / startup error. ErrAgentHandshakeTimeout = errors.New("agent: handshake timeout") // ErrAgentHandshakeMalformed is returned when the agent emitted a // first stdout line that doesn't parse as VERSION|PORT. ErrAgentHandshakeMalformed = errors.New("agent: handshake malformed") // ErrAgentVersionMismatch fires when the agent advertises a protocol // version this loader doesn't speak. Remediation: rebuild agent // against current core, or upgrade core. ErrAgentVersionMismatch = errors.New("agent: protocol version mismatch") // ErrAgentDialTimeout is returned when the gRPC connection to the // spawned agent didn't reach Ready within dialTimeout. The agent is // listening on the announced port but isn't accepting connections — // usually a server misconfiguration or a TLS mismatch. ErrAgentDialTimeout = errors.New("agent: gRPC dial timeout") )
Sentinel errors for agent loading failures. Callers (CLI, MCP server, daemon) should switch on these via errors.Is to pick the right user message and remediation.
Each is wrapped on the way out — the underlying error chain still carries the original cause + stderr tail for diagnostics. errors.Is matches through the chain.
var ( // store cannot be reached (network down, registry refusing). ErrStoreUnavailable = errors.New("store: unavailable") // ErrStoreArtifactMissing is returned by Pull when the agent ref // resolves to nothing in the store. Distinct from ErrStoreUnavailable // to let callers retry-with-backoff vs fail-fast appropriately. ErrStoreArtifactMissing = errors.New("store: artifact missing") )
Sentinels for the AgentStore implementations.
Functions ¶
func AgentSourceLocal ¶ added in v0.1.155
func AgentSourceLocal() bool
AgentSourceLocal returns true when the agent loader should bypass GitHub and resolve versions exclusively from the local agent directory. See AgentSourceEnv.
func Cleanup ¶
func Cleanup(unique string)
Cleanup kills an agent process by its unique key and removes it from the active map.
func CleanupAll ¶ added in v0.1.155
func CleanupAll()
CleanupAll closes every active agent connection. Call this during graceful daemon shutdown.
func CopyFile ¶ added in v0.1.132
CopyFile copies a file from src to dst. If dst does not exist, it is created with permissions copied from src.
func DownloadURL ¶
func Downloaded ¶ added in v0.0.90
func FindLocalLatest ¶ added in v0.1.155
FindLocalLatest scans the local agent directory for installed binaries matching the agent name and returns the highest semver version found. This is the preferred resolution path for locally-built agents (via "codefly agent build") that have no GitHub release.
func MoveFile ¶ added in v0.1.132
MoveFile attempts to rename the file, and if it fails due to an invalid cross-device link, it falls back to copying the file and then removing the original file.
func PinToLatestRelease ¶
PinToLatestRelease queries GitHub for the latest release tag and updates the agent's version. Falls back to FindLocalLatest if GitHub is unreachable or has no releases for this agent.
When CODEFLY_AGENT_SOURCE=local (or --local-agents on the CLI), GitHub is skipped entirely and resolution goes straight to the local filesystem scan. This makes "version: latest" work offline and lets agent developers iterate on locally-built binaries without needing to cut a GitHub release.
func PlatformSuffix ¶ added in v0.1.155
func PlatformSuffix() string
PlatformSuffix returns the OS/arch suffix for the current platform. Used when pushing platform-specific agent binaries.
func ResolveLatest ¶ added in v0.1.155
ResolveLatest resolves agent.Version when it is "latest". Strategy:
- If CODEFLY_AGENT_SOURCE=local: scan the local agent dir only.
- Otherwise: try FindLocalLatest first; if it succeeds, use it. This makes locally-built agents (via `codefly agent build`) take precedence over any GitHub release, which is the intent of running `codefly` from a dev checkout.
- Fall back to PinToLatestRelease (GitHub → local fallback).
No-op when agent.Version is already a concrete semver.
Types ¶
type AgentConn ¶ added in v0.1.155
type AgentConn struct {
// contains filtered or unexported fields
}
AgentConn is a connection to a running agent process. It owns the gRPC connection and the child process.
func Load ¶
Load spawns an agent binary, reads the gRPC port from its stdout, and establishes a gRPC connection. The agent binary is downloaded if not already present.
func (*AgentConn) Close ¶ added in v0.1.155
func (c *AgentConn) Close()
Close shuts down the gRPC connection, asks the agent to exit gracefully (SIGTERM) so it can reap its child processes (user binaries, Docker containers) via its agents.Serve signal handler, then falls back to SIGKILL if the agent is unresponsive.
The previous implementation jumped straight to SIGKILL, which won the race against the agent's own SIGTERM handler and orphaned every child process as a PPID=1 zombie — exactly what the agent's signal handler was written to prevent.
cmd.Wait must only be called once — the reaper owns it. We observe completion via the `done` channel the reaper closes.
func (*AgentConn) GRPCConn ¶ added in v0.1.155
func (c *AgentConn) GRPCConn() *grpc.ClientConn
GRPCConn returns the shared gRPC connection to the agent.
func (*AgentConn) ProcessInfo ¶ added in v0.1.155
func (c *AgentConn) ProcessInfo() *ProcessInfo
ProcessInfo returns the agent's process metadata.
func (*AgentConn) StderrTail ¶ added in v0.1.155
StderrTail returns the last captured bytes from the agent's stderr. Useful for diagnostics after a crash or handshake failure.
type AgentStore ¶ added in v0.1.155
type AgentStore interface {
// Pull downloads an agent binary and returns the local file path.
// The binary is cached locally — subsequent calls for the same name+version
// return the cached path without re-downloading.
Pull(ctx context.Context, agent *resources.Agent) (binaryPath string, err error)
// Available checks if an agent exists in the store without downloading it.
Available(ctx context.Context, agent *resources.Agent) (bool, error)
}
AgentStore provides a mechanism to pull agent binaries from a remote registry. Implementations: OCIStore (OCI-compliant registries), HTTPStore (simple HTTP), NixStore (content-addressed via Nix flakes).
type GithubSource ¶
type LoadOption ¶ added in v0.1.155
type LoadOption func(*loadConfig)
LoadOption configures optional behaviour of Load.
func WithDialTimeout ¶ added in v0.1.155
func WithDialTimeout(d time.Duration) LoadOption
WithDialTimeout overrides the default time Load waits for the gRPC connection to become ready.
func WithLogWriter ¶ added in v0.1.155
func WithLogWriter(w io.Writer) LoadOption
WithLogWriter tees the agent's stderr to w in real time, in addition to buffering in the ring buffer. Useful for debug mode where the gateway wants to surface agent logs.
func WithStartupTimeout ¶ added in v0.1.155
func WithStartupTimeout(d time.Duration) LoadOption
WithStartupTimeout overrides the default time Load waits for the agent handshake.
func WithWorkDir ¶ added in v0.1.155
func WithWorkDir(dir string) LoadOption
WithWorkDir sets the working directory for the agent process and exports CODEFLY_AGENT_WORKDIR so the agent can resolve file paths.
type NixStore ¶ added in v0.1.155
type NixStore struct {
// contains filtered or unexported fields
}
NixStore pulls agent binaries by realizing a Nix flake output.
Motivation: OCI/HTTP stores cache by `{publisher}/{name}:{version}` — a mutable tag in a registry. Nix outputs are content-addressed, so the same flake ref always yields the same store path; cache invalidation is automatic and cross-platform selection is handled by Nix itself (no PlatformSuffix hand-waving).
Layout convention: the configured flake must expose agents at `packages.${system}.agents-{kind}-{name}-{version}`. The build output must be either:
- a file that is the agent binary, or
- a directory containing `bin/service-{name}` (the nixpkgs convention for a package built from a Go module).
Configure via env:
AGENT_NIX_FLAKE=github:codefly-dev/codefly # ref AGENT_NIX_FLAKE=github:codefly-dev/codefly/v0.5 # ref pinned to a tag AGENT_NIX_FLAKE=/path/to/local/flake # local checkout
If unset, NewNixStoreFromEnv returns nil.
func NewNixStore ¶ added in v0.1.155
NewNixStore creates a NixStore for an explicit flake ref.
func NewNixStoreFromEnv ¶ added in v0.1.155
NewNixStoreFromEnv creates a NixStore from AGENT_NIX_FLAKE. Returns nil if unset or if `nix` is not on PATH.
func (*NixStore) Available ¶ added in v0.1.155
Available asks nix to evaluate the attribute without building it. Cheap compared to Pull: just flake eval, no derivation realization.
type OCIStore ¶ added in v0.1.155
type OCIStore struct {
// contains filtered or unexported fields
}
OCIStore pulls agent binaries from an OCI-compliant registry. Agent binaries are stored as single-layer OCI artifacts.
Registry layout:
{registry}/agents/{publisher}/{name}:{version}
└── single layer: service-{name} (the binary, for current OS/arch)
Push example:
oras push localhost:5111/agents/codefly.dev/go-generic:0.0.1 \ service-go-generic:application/octet-stream
The store uses the OCI distribution spec via plain HTTP calls (no oras CLI needed). For simplicity, we use the Docker Registry HTTP API V2.
func NewOCIStore ¶ added in v0.1.155
NewOCIStore creates a store backed by an OCI registry. The registry should be the base URL without scheme (e.g., "localhost:5111"). Use "http" scheme for local k3d registries, "https" for production.
func NewOCIStoreFromEnv ¶ added in v0.1.155
NewOCIStoreFromEnv creates an OCIStore from the AGENT_REGISTRY env var. Returns nil if AGENT_REGISTRY is not set.
Format: AGENT_REGISTRY=localhost:5111 (local k3d)
AGENT_REGISTRY=ghcr.io/codefly-dev (production)
type ProcessInfo ¶ added in v0.0.67
type ProcessInfo struct {
PID int
}
ProcessInfo carries metadata about the spawned agent process.