Documentation
¶
Overview ¶
Package supervisor spawns and tracks per-thread `codex app-server` subprocesses inside the codex-app-gateway pod.
Index ¶
- type ChildHandle
- type ConfigBuilder
- type IdleReaper
- type Key
- type SpawnConfig
- type Supervisor
- func (s *Supervisor) EnsureSubprocess(ctx context.Context, key Key, build ConfigBuilder) (*ChildHandle, error)
- func (s *Supervisor) LookupWorkspaceForLoopbackToken(token string) (string, bool)
- func (s *Supervisor) Shutdown(ctx context.Context, key Key) error
- func (s *Supervisor) ShutdownAll(ctx context.Context)
- func (s *Supervisor) Touch(key Key)
- type SupervisorConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ChildHandle ¶
type ChildHandle struct {
WSURL string // ws://127.0.0.1:PORT
HTTPURL string // http://127.0.0.1:PORT (for /readyz, /healthz)
CodexHome string
// contains filtered or unexported fields
}
ChildHandle is what spawnCodexAppServer returns.
func (*ChildHandle) Done ¶
func (h *ChildHandle) Done() <-chan struct{}
Done returns a channel closed after the subprocess exits. Useful for callers that want to be notified of unexpected termination.
func (*ChildHandle) IsAlive ¶
func (h *ChildHandle) IsAlive() bool
IsAlive reports whether the subprocess is still running. Cheap; suitable for calling on every EnsureSubprocess hit.
type ConfigBuilder ¶
type ConfigBuilder func(loopbackToken string) (SpawnConfig, error)
ConfigBuilder produces a fresh SpawnConfig at spawn time. Receives the per-spawn loopback token so the builder can embed it in config.toml's env block. Allowed to hit the network; errors propagate.
type IdleReaper ¶
type IdleReaper struct {
// contains filtered or unexported fields
}
IdleReaper periodically scans the Supervisor and shuts down entries idle for longer than idleAfter.
func NewIdleReaper ¶
func NewIdleReaper(sup *Supervisor, interval, idleAfter time.Duration, logger *slog.Logger) *IdleReaper
func (*IdleReaper) Run ¶
func (r *IdleReaper) Run(ctx context.Context)
Run blocks until ctx is done, ticking every interval and shutting down idle entries.
type Key ¶
type Key struct {
WorkspaceID string
}
Key identifies one workspace's codex app-server subprocess. The codex-app-server process internally manages multiple threads via its own JSON-RPC protocol; the gateway does not see thread IDs.
type SpawnConfig ¶ added in v0.50.7
type SpawnConfig struct {
Config codexhome.ConfigInput
Env []string
}
SpawnConfig is what a ConfigBuilder returns: the per-thread CODEX_HOME config.toml input plus per-spawn process env vars (e.g. a workspace- scoped LLM API key fetched from agentserver at spawn time). The env list is concatenated with SupervisorConfig.ExtraEnv when launching.
LoopbackToken (if set by Supervisor.EnsureSubprocess after the builder runs) is the 32-byte hex token env-mcp uses to authenticate against the app-gateway's loopback /internal/connected endpoint. The builder cannot set it itself because it is allocated at spawn time and stored in the entry; pass-through happens in EnsureSubprocess so callers writing config.toml see it.
type Supervisor ¶
type Supervisor struct {
// contains filtered or unexported fields
}
Supervisor owns the in-memory (workspace, thread) → subprocess map.
func NewSupervisor ¶
func NewSupervisor(cfg SupervisorConfig) *Supervisor
func (*Supervisor) EnsureSubprocess ¶
func (s *Supervisor) EnsureSubprocess(ctx context.Context, key Key, build ConfigBuilder) (*ChildHandle, error)
EnsureSubprocess returns a live ChildHandle for key, spawning one if necessary. Concurrent EnsureSubprocess calls for the same key see the same handle (one-spawn-per-key invariant; loser of the race discards their spawn). If a cached entry's subprocess has crashed, it is evicted and a fresh subprocess is spawned.
func (*Supervisor) LookupWorkspaceForLoopbackToken ¶ added in v0.51.0
func (s *Supervisor) LookupWorkspaceForLoopbackToken(token string) (string, bool)
LookupWorkspaceForLoopbackToken constant-time-compares the supplied token against every live child's loopback token and returns the matching workspace_id. Linear scan is fine: # live subprocesses ≤ workspaces, typically <100.
func (*Supervisor) Shutdown ¶
func (s *Supervisor) Shutdown(ctx context.Context, key Key) error
Shutdown terminates the subprocess for key, uploads its CODEX_HOME to S3, and drops the in-memory entry. Safe on missing keys.
func (*Supervisor) ShutdownAll ¶
func (s *Supervisor) ShutdownAll(ctx context.Context)
ShutdownAll shuts down every active subprocess.
func (*Supervisor) Touch ¶
func (s *Supervisor) Touch(key Key)
Touch bumps the last-active timestamp for a key. Callers must invoke it on every proxied frame (see proxy.RunProxy's onFrame callback) so the IdleReaper sees fresh activity for the duration of an active session, not just at connect/disconnect.
type SupervisorConfig ¶
type SupervisorConfig struct {
CodexBin string
HomeMgr *codexhome.Manager
Store codexhome.ObjectStore
ExtraEnv []string // forwarded to every spawned subprocess
Logger *slog.Logger // defaults to slog.Default() if nil
}
SupervisorConfig holds the static dependencies.