eggclient

package
v0.149.2 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 42 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ProtectedWriteTargetArg = "protected-write-target"
	OmitBrowserBridgeArg    = "omit-browser-bridge"
)
View Source
const (
	RemoteSessionContractVersion = "v1"
	RemoteSessionTimeout         = 3 * time.Second
)
View Source
const ProviderResumeMetadataFile = "provider.resume"

Variables

View Source
var BrowserProviderResumes = providerResumeRegistry{Active: make(map[string]string)}
View Source
var ErrSessionNameInUse = control.ErrSessionNameInUse

Functions

func AcquireSessionNameLock

func AcquireSessionNameLock(cfg *config.Config) (*os.File, error)

acquireSessionNameLock serializes name assignments across every entry point and process. Hold it through the availability check and durable write; a new egg must also become discoverable before releasing its label claim.

func ActiveProviderResumeConflict

func ActiveProviderResumeConflict(cfg *config.Config, key, exceptSessionID string, alive func(string) bool) bool

func AttachBrowserController

func AttachBrowserController(ctx context.Context, client *egg.Client, sessionID string, options egg.AttachOptions, listener *egg.ToolListener, userID string) (pb.Egg_SessionClient, error)

AttachBrowserController records only confirmed input claims, before any browser input is routed to the replacement stream.

func AttachLocal

func AttachLocal(ctx context.Context, cfg *config.Config, sessionID string) (bool, error)

func AttachLocalIO added in v0.149.0

func AttachLocalIO(ctx context.Context, cfg *config.Config, sessionID string, input io.Reader, output io.Writer, options egg.AttachOptions) (bool, error)

The attachment owns its stream lifetime, not the session process. Detaching or losing this connection cancels only this client and leaves the egg alive.

func AttachLocalOptions

func AttachLocalOptions(ctx context.Context, cfg *config.Config, sessionID string, options egg.AttachOptions) (bool, error)

func AttachStreamIO added in v0.149.0

func AttachStreamIO(ctx context.Context, sessionID string, input io.Reader, output io.Writer, options egg.AttachOptions, open func(context.Context, egg.AttachOptions) (SessionStream, error)) (bool, error)

AttachStreamIO is terminal presentation only; open supplies the authorized API.

func CanAccessSessionArtifact

func CanAccessSessionArtifact(req ws.TunnelRequest, sessionDir string, userPaths []string) bool

canAccessSessionArtifact applies the same current owner-and-workspace policy used by session listings before exposing a persisted audit or chat artifact. Missing legacy metadata fails closed for members; owners and admins retain the historical oversight access.

func CleanEggDir

func CleanEggDir(dir string)

cleanEggDir removes the files in an egg session directory, then the directory itself. If recordings or lifecycle history exist, preserves metadata and data.

func ContainsExactPath

func ContainsExactPath(paths []string, target string) bool

func EffectiveProviderSession

func EffectiveProviderSession(agentName, generatedResumeID string, agentArgs []string) (providerID string, effectiveArgs []string, generatedResume string, err error)

func EffectiveSessionHome

func EffectiveSessionHome(cfg *config.Config, identity EggIdentity) string

func EggPidMatchesSession

func EggPidMatchesSession(pid int, sessionID string) bool

eggPidMatchesSession reports whether pid's command line is the egg runner for sessionID. PIDs are recycled; a stale egg.pid can point at an unrelated process (another user's egg, or any roost process), so a PID whose argv cannot be confirmed is never signaled.

func EnsureSessionNameAvailable

func EnsureSessionNameAvailable(cfg *config.Config, name, exceptID string) error

func ExplainEnforcement

func ExplainEnforcement(need sandbox.NetworkNeed, goos, mode string) string

explainEnforcement reports how the network policy is actually held. macOS Seatbelt allows only the proxy endpoint. Linux keeps CLONE_NEWNET and exposes only inherited proxy/loopback relays, so ignoring HTTPS_PROXY fails closed.

func HumanBytes

func HumanBytes(b int64) string

func HumanDuration

func HumanDuration(d time.Duration) string

func InstallSharedAgentBinary

func InstallSharedAgentBinary(source, home, agentName string) error

func IsolatedClaudePolicyArgs

func IsolatedClaudePolicyArgs(agentName string, isolated bool) ([]string, error)

Only deployment model policy, and the host's choice to disable Claude's self-updater, cross from the host profile into an isolated session. Pass it to Claude for this launch; never merge it into the user's file.

func KillOrphanEgg

func KillOrphanEgg(cfg *config.Config, sessionID string)

KillOrphanEgg kills an egg session that has no active goroutine managing it. This handles the case where a pty.kill arrives but the session was never reclaimed.

func KillOrphanEggContext added in v0.149.0

func KillOrphanEggContext(ctx context.Context, cfg *config.Config, sessionID string) error

KillOrphanEggContext stops a session over gRPC, falling back to a verified PID or stale metadata cleanup when its control socket is unavailable. The caller must authorize the session before invoking this runtime operation.

func LifecycleProviderHome

func LifecycleProviderHome(cfg *config.Config, recorded string) (string, error)

func LifecycleViewForSession

func LifecycleViewForSession(cfg *config.Config, session LocalSession, after int64, limit int) (egg.SessionView, error)

func LoadConfigForEgg

func LoadConfigForEgg(sessionID string) (*config.Config, error)

loadConfigForEgg rejects unusable socket addresses before config.Load can create state. Runtime callers with an existing config use the same preflight in spawnEgg, so CLI and MCP launches report the same actionable error.

func LoadEggConfigForExplain

func LoadEggConfigForExplain(configPath, cwd string) (*egg.EggConfig, string, error)

loadEggConfigForExplain resolves the same config eggSpawn would use, and reports where it came from. An explicit --config that does not load is an error here, unlike discovery, which is allowed to fall back.

func LoadRoostEggConfig added in v0.148.4

func LoadRoostEggConfig(cwd string, roots, allowedRoots []string, member bool, wingDefault *egg.EggConfig) (*egg.EggConfig, error)

LoadRoostEggConfig discovers only the administrator-configured root's policy, never a policy planted in a writable child directory or an ancestor.

func LoadSpawnEggConfig

func LoadSpawnEggConfig(configPath, cwd string, unsandboxed bool) (*egg.EggConfig, error)

loadSpawnEggConfig is shared by the human CLI and the local MCP server so an LLM gets the same trusted-VM behavior. Unsandboxed mode deliberately ignores discovered policy; combining it with an explicit config is rejected rather than giving a false impression that any of that config is enforced.

func NormalizeUser

func NormalizeUser(email string) string

NormalizeUser converts an email local part to a safe username. Lowercase, alphanumeric + hyphens only. Dots and special chars become hyphens.

func ParseMemFlag

func ParseMemFlag(s string) uint64

parseMemFlag parses a memory string like "2GB" or "512MB" into bytes.

func PrepareBrowserResume

func PrepareBrowserResume(cfg *config.Config, wingCfg *config.WingConfig, start ws.PTYStart, userPaths []string, sharedHost bool) (providerSessionID, cwd string, release func(bool), err error)

func PrepareBrowserTools

func PrepareBrowserTools(cfg *config.Config, sessionID string, tools []*config.ToolConfig, opts *SpawnEggOpts, identities ...EggIdentity) (*egg.ToolListener, error)

PrepareBrowserTools supplies the same tool listener and launch options to fresh browser PTYs and browser forks.

func PrepareIsolatedClaudeConfig

func PrepareIsolatedClaudeConfig(home string, envMap map[string]string) error

func PrepareSharedAgentHome

func PrepareSharedAgentHome(home string, relativeDirs []string) error

func PreserveEggFailure

func PreserveEggFailure(dir string, failure error) (string, error)

Preserve a bounded startup tail before reaping an abandoned child. No environment, credential files or provider transcript is read here.

func PromptSession

func PromptSession(ctx context.Context, cfg *config.Config, session LocalSession, requestID, input string, timeout time.Duration, owner string, verifiedUserIDs ...string) (egg.SessionPromptResult, error)

func ProtectContextSecret added in v0.148.4

func ProtectContextSecret(policy *egg.EggConfig, c *config.ContextConfig, cwd, home string) (*egg.EggConfig, []string, error)

ProtectContextSecret adds host-owned deny rules after caller policy resolution. Interactive and headless launches must both use this guard.

func ProtectedWriteTargetArgs

func ProtectedWriteTargetArgs(targets []string) ([]string, error)

protectedWriteTargetArgs encodes protected targets for the internal egg run child. The --flag=value form keeps values beginning with "-" intact, and StringArray (not StringSlice) keeps commas literal.

func ProviderResumeKey

func ProviderResumeKey(home, agent, providerSessionID string) string

func ReadAliveEggPID

func ReadAliveEggPID(dir string) (int, bool)

func ReadEggCrashInfo

func ReadEggCrashInfo(dir string) string

readEggCrashInfo reads the last lines of an egg's log looking for panic/crash info.

func ReadEggEnvironment

func ReadEggEnvironment(path string, entries []string, required bool) (map[string]string, error)

func ReadEggMeta

func ReadEggMeta(dir string) (agent, cwd string)

readEggMeta reads agent/cwd from an egg's meta file.

func ReadEggMetaValues

func ReadEggMetaValues(dir string) map[string]string

func ReadEggOwner

func ReadEggOwner(dir string) string

readEggOwner reads the creator user ID from an egg's owner file.

func ReadEggOwnerEmail

func ReadEggOwnerEmail(dir string) string

readEggOwnerEmail reads the creator email from an egg's owner file (line 2).

func ReadRunTurnResult added in v0.149.0

func ReadRunTurnResult(ctx context.Context, cfg *config.Config, session LocalSession, runID string) (egg.RunTurnResult, error)

func ReadSessionLifecycleView

func ReadSessionLifecycleView(ctx context.Context, cfg *config.Config, ref string, after int64, limit int) (egg.SessionView, error)

func ReadSessionName

func ReadSessionName(dir string) string

func ReadSessionPrincipal

func ReadSessionPrincipal(dir string) string

func ReapDeadEggs

func ReapDeadEggs(cfg *config.Config)

reapDeadEggs removes egg directories for dead processes on startup.

func RejectSharedHostRootMount

func RejectSharedHostRootMount(mounts []sandbox.Mount) error

func RenderPolicy

func RenderPolicy(w io.Writer, p ExplainedPolicy) error

func ReserveRunTurn added in v0.149.0

func ReserveRunTurn(ctx context.Context, cfg *config.Config, session LocalSession, request egg.RunTurnRequest) (egg.RunTurnResult, error)

func ResizeEgg

func ResizeEgg(cfg *config.Config, sessionID string, rows, cols uint32) (result error)

func RunTurnStatus added in v0.149.0

func RunTurnStatus(ctx context.Context, cfg *config.Config, session LocalSession, runID string) (egg.RunTurnResult, error)

func SessionForkStatus

func SessionForkStatus(cfg *config.Config, dir, agent, cwd string) (bool, string)

func SessionIsolationLabel

func SessionIsolationLabel(cfg *egg.EggConfig) string

func SessionLifecycleSummary

func SessionLifecycleSummary(ctx context.Context, cfg *config.Config, id string) map[string]any

func SessionResumeStatus

func SessionResumeStatus(sessionDir, agent, cwd string) (bool, string)

func SetupAPIKeyHelper

func SetupAPIKeyHelper(agentName string, envMap map[string]string, effectiveHome string) error

setupAPIKeyHelper moves ANTHROPIC_API_KEY out of the environment and into a stable file + apiKeyHelper setting. This prevents the key from entering the agent's env and avoids the v0.128.0 race where per-session paths in settings.json went stale.

func SortedRemoteNames

func SortedRemoteNames(remotes map[string]config.Remote) []string

func SpawnEgg

func SpawnEgg(cfg *config.Config, sessionID, agentName string, eggCfg *egg.EggConfig, rows, cols uint32, cwd string, debug, vte, trace bool, identity EggIdentity, idleTimeout time.Duration, opts ...SpawnEggOpts) (*egg.Client, error)

spawnEgg starts a per-session egg child process and returns a connected client.

func StopRunTurn added in v0.149.0

func StopRunTurn(ctx context.Context, cfg *config.Config, session LocalSession, runID string) (egg.RunTurnResult, error)

func SubmitRunTurn added in v0.149.0

func SubmitRunTurn(ctx context.Context, cfg *config.Config, session LocalSession, request egg.RunTurnRequest) (egg.RunTurnResult, error)

func UserHash

func UserHash(stableIdentity string) string

userHash returns the first 12 hex chars of the SHA256 of a stable identity. Org/shared-host callers deliberately pass the authenticated user ID, not an email address: two distinct Wingthing accounts must not silently share agent credentials merely because an identity provider reports the same email.

func ValidProviderSessionID

func ValidProviderSessionID(id string) bool

func ValidateAgentArgs

func ValidateAgentArgs(args []string) error

spawnEggOpts holds optional parameters for spawnEgg. validateAgentArgs checks caller-supplied argv before any process is spawned. Empty and whitespace arguments are valid literal argv entries: providers use them to disable tools and setting sources. Only NUL cannot cross exec argv.

func ValidateLifecycleWait

func ValidateLifecycleWait(state string) error

func ValidateSessionID

func ValidateSessionID(sessionID string) error

func ValidateSessionName

func ValidateSessionName(name string) error

func ValidateSharedHostWorkspacePaths

func ValidateSharedHostWorkspacePaths(cfg *config.Config, allowedPaths []string) ([]string, error)

func WaitRunTurn added in v0.149.0

func WaitRunTurn(ctx context.Context, cfg *config.Config, session LocalSession, runID string) (egg.RunTurnResult, error)

func WaitSessionLifecycle

func WaitSessionLifecycle(ctx context.Context, cfg *config.Config, session LocalSession, after int64, state string) (egg.SessionView, bool, error)

func WriteEggOwner

func WriteEggOwner(dir, userID, email string) error

func WritePolicyJSON

func WritePolicyJSON(w io.Writer, p ExplainedPolicy) error

func WriteSessionName

func WriteSessionName(dir, name string) error

func WriteSessionPrincipal

func WriteSessionPrincipal(dir, principal string) error

Types

type AttachInputFilter

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

func (*AttachInputFilter) Filter

func (f *AttachInputFilter) Filter(input []byte) ([]byte, bool)

filter returns bytes for the egg and whether the local client should detach. The prefix may arrive in a separate read from the following key.

type ConversationLink struct {
	ConversationID       string `json:"conversation_id,omitempty"`
	RootConversationID   string `json:"root_conversation_id,omitempty"`
	ParentConversationID string `json:"parent_conversation_id,omitempty"`
	ConversationRole     string `json:"conversation_role,omitempty"`
}
func SessionConversationLink(cfg *config.Config, session string) ConversationLink

type EggIdentity

type EggIdentity struct {
	UserID       string   // relay user ID
	Email        string   // authenticated email (e.g. from Google OAuth)
	DisplayName  string   // human-readable name (Google full name, GitHub login)
	OrgWing      bool     // true if this is an org wing — all users get per-user isolation
	SharedHost   bool     // true when several owners use one OS account through a roost
	AllowedPaths []string // canonical host roots this owner may reach on a shared host
	SealedFS     bool     // replace caller filesystem rules with the shared-host allowlist jail
}

EggIdentity holds the authenticated user's identity for per-session env injection. Zero value means no identity (local egg, no authenticated user).

func BrowserEggIdentity

func BrowserEggIdentity(wc *config.WingConfig, start ws.PTYStart, home string, sharedHost bool) EggIdentity

func PrepareBrowserLaunch

func PrepareBrowserLaunch(wc *config.WingConfig, start *ws.PTYStart, home string, sharedHost bool, wingDefault *egg.EggConfig) (*egg.EggConfig, EggIdentity, error)

PrepareBrowserLaunch is shared by fresh PTYs and browser forks. Configured roots, rather than writable subdirectories, determine browser launch policy.

func PrepareMCPLaunch added in v0.149.0

func PrepareMCPLaunch(wc *config.WingConfig, start *ws.PTYStart, home string, sharedHost bool, wingDefault *egg.EggConfig) (*egg.EggConfig, EggIdentity, error)

PrepareMCPLaunch permits existing subdirectories within the caller's paths, while retaining the covering configured root's sandbox policy.

type ExplainedHole

type ExplainedHole struct {
	Kind   string `json:"kind"`
	Value  string `json:"value"`
	Agent  string `json:"agent"`
	Reason string `json:"reason"`
}

type ExplainedPolicy

type ExplainedPolicy struct {
	Agent        string           `json:"agent"`
	ConfigSource string           `json:"config_source"`
	Isolation    string           `json:"isolation"`
	NetworkNeed  string           `json:"network_need"`
	Enforcement  string           `json:"enforcement"`
	Domains      []string         `json:"domains"`
	LocalPorts   []int            `json:"local_ports"`
	Mode         string           `json:"mode"`
	Mounts       []explainedMount `json:"mounts"`
	Deny         []string         `json:"deny"`
	DenyWrite    []string         `json:"deny_write"`
	Drilled      []ExplainedHole  `json:"drilled"`
	Derived      []ExplainedHole  `json:"derived"`
	Suppressed   []ExplainedHole  `json:"suppressed"`
}

explainedPolicy is the wire shape of `wt egg explain`. The sandbox is egg.yaml plus holes drilled automatically for the agent, and until now nothing could report what that added up to. These field names are an API contract.

func ExplainPolicy

func ExplainPolicy(cfg *egg.EggConfig, agentName, home, source string) ExplainedPolicy

func ExplainPolicyWithProvider

func ExplainPolicyWithProvider(cfg *egg.EggConfig, agentName, home, source, providerURL string) (ExplainedPolicy, error)

type LocalSession

type LocalSession struct {
	ConversationLink
	ID           string `json:"id"`
	Name         string `json:"name,omitempty"`
	Principal    string `json:"principal,omitempty"`
	Kind         string `json:"kind"`
	Agent        string `json:"agent,omitempty"`
	Status       string `json:"status"`
	Command      string `json:"command,omitempty"`
	CWD          string `json:"cwd,omitempty"`
	Isolation    string `json:"isolation,omitempty"`
	PID          int    `json:"pid"`
	Readers      int32  `json:"readers"`
	WriterID     string `json:"writer_id,omitempty"`
	WriterOwner  string `json:"writer_owner,omitempty"`
	InputEpoch   uint64 `json:"input_epoch,omitempty"`
	UptimeSecs   int64  `json:"uptime_seconds"`
	IdleSecs     int64  `json:"idle_seconds"`
	BufferBytes  int64  `json:"buffer_bytes"`
	TotalWritten int64  `json:"total_written"`
}

func DiscoverActiveSessions

func DiscoverActiveSessions(ctx context.Context, cfg *config.Config) ([]LocalSession, error)

func DiscoverSessionRefs

func DiscoverSessionRefs(cfg *config.Config) ([]LocalSession, error)

discoverSessionRefs reads only process and metadata files. Resolution stays fast even with many sessions; status RPCs are reserved for list displays.

func OpenLocalEgg

func OpenLocalEgg(ctx context.Context, cfg *config.Config, ref string) (LocalSession, *egg.Client, error)

func QueryRemoteSessions

func QueryRemoteSessions(localVersion string, ctx context.Context, name string, remote config.Remote, streams remotepkg.IO) ([]LocalSession, error)

func ReadSessionSnapshot

func ReadSessionSnapshot(ctx context.Context, cfg *config.Config, ref string) (LocalSession, []byte, error)

func ResolveActiveSession

func ResolveActiveSession(ctx context.Context, cfg *config.Config, ref string) (LocalSession, error)

func ResolveLifecycleSession

func ResolveLifecycleSession(cfg *config.Config, ref string) (LocalSession, error)

Lifecycle reads include archived sessions. Terminal input/attachment retains its existing live-only resolution. Exact IDs take precedence, then active labels, without constructing a path from a caller-supplied string.

func ResolveOwnedActiveSession

func ResolveOwnedActiveSession(ctx context.Context, cfg *config.Config, ref string, owns func(LocalSession) bool) (LocalSession, error)

func ResolveOwnedLifecycleSession

func ResolveOwnedLifecycleSession(cfg *config.Config, ref string, owns func(LocalSession) bool) (LocalSession, error)

func SendSessionInput

func SendSessionInput(ctx context.Context, cfg *config.Config, ref string, input []byte, enter bool, verifiedUserIDs ...string) (LocalSession, error)

func WaitForSessionText

func WaitForSessionText(ctx context.Context, cfg *config.Config, ref, needle string) (LocalSession, error)

type MachineSession

type MachineSession struct {
	LocalSession
	Machine string `json:"machine"`
	Error   string `json:"error,omitempty"`
}

func DiscoverMachineSessions

func DiscoverMachineSessions(localVersion string, ctx context.Context, cfg *config.Config, streams remotepkg.IO) ([]MachineSession, error)

type RemoteSessionInventory

type RemoteSessionInventory struct {
	Version         string         `json:"version"`
	ContractVersion string         `json:"contract_version"`
	Sessions        []LocalSession `json:"sessions"`
}

Only the internal inventory response is versioned. Public session ps --json remains an array, with machine and error fields added to its rows.

type SessionForkPlan

type SessionForkPlan struct {
	SessionID    string
	Source       LocalSession
	Config       *egg.EggConfig
	Identity     EggIdentity
	Options      SpawnEggOpts
	Conversation *store.Conversation
}

type SessionForkResult

type SessionForkResult struct {
	ConversationLink
	Session       string `json:"session"`
	SourceSession string `json:"source_session"`
	Label         string `json:"label"`
	Agent         string `json:"agent"`
	CWD           string `json:"cwd"`
}

func ForkSession

func ForkSession(ctx context.Context, cfg *config.Config, sourceRef, label string, scope SessionForkScope) (*SessionForkResult, error)

ForkSession creates a distinct execution and logical sibling. All adapters use this owner/path check and the existing name, provider, and spawn locks.

type SessionForkScope

type SessionForkScope struct {
	Principal         string
	Identity          EggIdentity
	AllowedPaths      []string
	EnforcePathBounds bool
	TraceFromConfig   bool
	IdleTimeout       time.Duration
	Admit             func(func() error) error
	CheckSpawn        func() error // recheck capacity under the session-name lock
	Tools             []*config.ToolConfig
	LoadConfig        func(string) (*egg.EggConfig, error)
	Prepare           func(*SessionForkPlan) error
	Spawn             func(*SessionForkPlan) error
}

type SessionStream added in v0.149.0

type SessionStream interface {
	Send(*pb.SessionMsg) error
	Recv() (*pb.SessionMsg, error)
}

SessionStream is shared by direct egg RPC and authenticated wing streaming.

type SpawnEggOpts

type SpawnEggOpts struct {
	ForkSession bool

	ResumeSessionID        string
	ResumeSourceSessionID  string
	ProviderReserved       bool
	ToolNames              []string
	ToolSocketPath         string
	Label                  string
	Kind                   string
	Command                []string
	AgentArgs              []string
	InitialRun             *egg.RunTurnRequest
	Principal              string
	PreserveEmptyAgentArgs bool
	// ProtectedWriteTargets are host-owned paths the child's final sandbox
	// policy must keep unwritable. Empty preserves ordinary launches.
	ProtectedWriteTargets []string
	// OmitBrowserBridge launches without the optional browser-open bridge.
	// False preserves ordinary launches.
	OmitBrowserBridge bool
	// contains filtered or unexported fields
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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