ollie/fs/newroot.go

91 lines
2.3 KiB
Go

package fs
import (
"context"
"os/user"
"ollie/bypass"
"ollie/fsedsl"
olog "ollie/log"
"ollie/session"
)
// Config carries all runtime dependencies for the filesystem tree.
// It is the single input to NewRoot.
type Config struct {
Ctx context.Context
Log *olog.Logger
Sink *olog.Sink
AgentsDir string
SessionsDir string
Yolo bool
ModelCache *ModelCache
BypassBroker *bypass.Broker
Shutdown func()
Invalidate func()
}
// NewRoot creates the complete 9P filesystem tree from the spec.
// It validates, resolves ownership inheritance, wires handlers,
// populates root state, and returns the ready-to-serve *Tree.
func NewRoot(cfg Config) *Tree {
// Resolve root ownership from the current system user.
u, err := user.Current()
treeSpecUID = "ollie"
treeSpecGID = "agent"
if err == nil && u != nil {
treeSpecUID = u.Username
}
treeSpec.UID = treeSpecUID // root node: owner is system user
treeSpec.GID = treeSpecGID // root node: group is "agent"
// Initialize session package
session.Init(session.InitConfig{
Ctx: cfg.Ctx,
Log: cfg.Log,
Sink: cfg.Sink,
AgentsDir: cfg.AgentsDir,
SessionsDir: cfg.SessionsDir,
Yolo: cfg.Yolo,
})
// Initialize root state (before tree build so closures capture the pointer).
rs := &RootState{
Cfg: cfg,
SessionNodes: make(map[string]*SessionNode),
}
// Build the root context with all available deps.
ctx := HandlerCtx{
Context: cfg.Ctx, // per-operation cancellation deadline
Root: nil, // set after tree is built
RootState: rs,
Log: cfg.Log,
Models: cfg.ModelCache,
Bypass: cfg.BypassBroker,
Shutdown: cfg.Shutdown,
Invalidate: cfg.Invalidate,
}
// Build the tree from the spec.
tree := fsedsl.BuildTree(treeSpec, ctx)
ctx.Root = tree
tree.Data = rs
// Restore persisted sessions from disk.
for _, r := range session.RestoreAllSessions() {
node := rs.GetOrCreateNode(r.Session)
for _, ra := range r.Agents {
al := NewAgentLog(ra.Remote)
node.SetAgentLog(ra.ID, al)
replayMessagesToLog(al, ra.Messages)
// Wire up the event handler so agent events flow to the AgentLog
if ag := r.Session.FindAgent(ra.ID); ag != nil {
wireAgentEvents(r.Session.ID, ag, al)
}
}
}
return tree
}