91 lines
2.3 KiB
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
|
|
}
|