agent: separate uname (principal) from session ID
Session identity is now a numeric UID (starting at 10000) assigned at creation and never changed. Session names can be renamed freely without affecting the 9P identity. - AgentCoreConfig.Uname carries the principal - pushSessionEnv sets OLLIE_UNAME on the execute server - startMount gated by WithMount() option (not env var) - Close() uses context timeout to avoid hanging on fusermount
This commit is contained in:
parent
e20f9a7a06
commit
1e96d4c7f4
|
|
@ -235,6 +235,7 @@ type AgentCoreConfig struct {
|
||||||
AgentsDir string
|
AgentsDir string
|
||||||
SessionsDir string
|
SessionsDir string
|
||||||
SessionID string
|
SessionID string
|
||||||
|
Uname string // immutable user principal for 9P identity
|
||||||
CWD string // working directory for tool execution and system prompt
|
CWD string // working directory for tool execution and system prompt
|
||||||
Session *Session
|
Session *Session
|
||||||
Env AgentEnv
|
Env AgentEnv
|
||||||
|
|
@ -257,6 +258,7 @@ type agent struct {
|
||||||
agentsDir string
|
agentsDir string
|
||||||
sessionsDir string
|
sessionsDir string
|
||||||
sessionID string
|
sessionID string
|
||||||
|
uname string
|
||||||
dispatcher tools.Dispatcher
|
dispatcher tools.Dispatcher
|
||||||
newDispatcher func() tools.Dispatcher
|
newDispatcher func() tools.Dispatcher
|
||||||
newBackend func(string) (backend.Backend, error)
|
newBackend func(string) (backend.Backend, error)
|
||||||
|
|
@ -311,6 +313,9 @@ func (s *agent) pushSessionEnv() {
|
||||||
if srv, ok := s.dispatcher.GetServer("execute"); ok {
|
if srv, ok := s.dispatcher.GetServer("execute"); ok {
|
||||||
if es, ok := srv.(tools.EnvSetter); ok {
|
if es, ok := srv.(tools.EnvSetter); ok {
|
||||||
es.SetEnv("OLLIE_SESSION_ID", s.sessionID)
|
es.SetEnv("OLLIE_SESSION_ID", s.sessionID)
|
||||||
|
if s.uname != "" {
|
||||||
|
es.SetEnv("OLLIE_UNAME", s.uname)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -416,6 +421,7 @@ func NewAgentCore(cfg AgentCoreConfig) Core {
|
||||||
agentsDir: cfg.AgentsDir,
|
agentsDir: cfg.AgentsDir,
|
||||||
sessionsDir: cfg.SessionsDir,
|
sessionsDir: cfg.SessionsDir,
|
||||||
sessionID: cfg.SessionID,
|
sessionID: cfg.SessionID,
|
||||||
|
uname: cfg.Uname,
|
||||||
cwd: paths.ExpandHome(cfg.CWD),
|
cwd: paths.ExpandHome(cfg.CWD),
|
||||||
startupMessages: cfg.Env.Messages,
|
startupMessages: cfg.Env.Messages,
|
||||||
dispatcher: cfg.Env.dispatcher,
|
dispatcher: cfg.Env.dispatcher,
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,9 @@ type Server struct {
|
||||||
lockDir string
|
lockDir string
|
||||||
|
|
||||||
// mountProc is the ollie-9p-mount subprocess for this session's FUSE proxy.
|
// mountProc is the ollie-9p-mount subprocess for this session's FUSE proxy.
|
||||||
mountProc *os.Process
|
mountProc *os.Process
|
||||||
mountPath string
|
mountPath string
|
||||||
|
mountEnabled bool
|
||||||
|
|
||||||
// Strict rejects inline {code} steps; only {tool} steps are allowed.
|
// Strict rejects inline {code} steps; only {tool} steps are allowed.
|
||||||
Strict bool
|
Strict bool
|
||||||
|
|
@ -75,6 +76,9 @@ func WithStrict() Option { return func(s *Server) { s.Strict = true } }
|
||||||
// WithYolo skips the landrun sandbox.
|
// WithYolo skips the landrun sandbox.
|
||||||
func WithYolo() Option { return func(s *Server) { s.Yolo = true } }
|
func WithYolo() Option { return func(s *Server) { s.Yolo = true } }
|
||||||
|
|
||||||
|
// WithMount enables per-session FUSE mount for 9P identity.
|
||||||
|
func WithMount() Option { return func(s *Server) { s.mountEnabled = true } }
|
||||||
|
|
||||||
// WithAllowExecutors restricts which executors are available.
|
// WithAllowExecutors restricts which executors are available.
|
||||||
func WithAllowExecutors(names []string) Option {
|
func WithAllowExecutors(names []string) Option {
|
||||||
return func(s *Server) {
|
return func(s *Server) {
|
||||||
|
|
@ -362,7 +366,8 @@ func (e *Server) SetEnv(key, value string) {
|
||||||
e.envExtra = make(map[string]string)
|
e.envExtra = make(map[string]string)
|
||||||
}
|
}
|
||||||
e.envExtra[key] = value
|
e.envExtra[key] = value
|
||||||
if key == "OLLIE_SESSION_ID" && value != "" {
|
// Start mount once we have the principal.
|
||||||
|
if key == "OLLIE_UNAME" && value != "" {
|
||||||
e.startMount(value)
|
e.startMount(value)
|
||||||
}
|
}
|
||||||
e.envMu.Unlock()
|
e.envMu.Unlock()
|
||||||
|
|
@ -370,9 +375,12 @@ func (e *Server) SetEnv(key, value string) {
|
||||||
|
|
||||||
// startMount launches ollie-9p-mount for this session. Must be called with envMu held.
|
// startMount launches ollie-9p-mount for this session. Must be called with envMu held.
|
||||||
func (e *Server) startMount(sessionID string) {
|
func (e *Server) startMount(sessionID string) {
|
||||||
|
if !e.mountEnabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
bin, err := exec.LookPath("ollie-9p-mount")
|
bin, err := exec.LookPath("ollie-9p-mount")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return // binary not installed; skip silently
|
return
|
||||||
}
|
}
|
||||||
mnt := filepath.Join(os.TempDir(), "ollie-mount-"+sessionID)
|
mnt := filepath.Join(os.TempDir(), "ollie-mount-"+sessionID)
|
||||||
os.MkdirAll(mnt, 0755) //nolint:errcheck
|
os.MkdirAll(mnt, 0755) //nolint:errcheck
|
||||||
|
|
@ -404,9 +412,11 @@ func (e *Server) Close() {
|
||||||
e.mountPath = ""
|
e.mountPath = ""
|
||||||
e.envMu.Unlock()
|
e.envMu.Unlock()
|
||||||
if proc != nil {
|
if proc != nil {
|
||||||
exec.Command("fusermount", "-u", mnt).Run() //nolint:errcheck
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||||
syscall.Kill(proc.Pid, syscall.SIGKILL) //nolint:errcheck
|
exec.CommandContext(ctx, "fusermount", "-u", mnt).Run() //nolint:errcheck
|
||||||
os.Remove(mnt) //nolint:errcheck
|
cancel()
|
||||||
|
syscall.Kill(proc.Pid, syscall.SIGKILL) //nolint:errcheck
|
||||||
|
os.Remove(mnt) //nolint:errcheck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Reference in New Issue