From 542834b3e437839af32b03c1233f4595f2767a0e Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:30:42 +0200 Subject: [PATCH] session: remove $OLLIE mount dependency - Wire ReadPlanStep directly from sess.plan (no filesystem read) - Add ListHandlers to ManagerConfig; passed through to AgentCoreConfig - Hoist skillTree in main.go; populate ListHandlers for tools+skills - Add ListHandlers to ManagerConfig --- main.go | 31 +++++++++++++++++++++++++------ session/session.go | 17 +++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/main.go b/main.go index c6359dc..09c7d88 100644 --- a/main.go +++ b/main.go @@ -151,16 +151,19 @@ func cmdMount() { fmt.Fprintf(os.Stderr, "cannot create mount dir: %v\n", err) os.Exit(1) } + network := "unix" + if strings.Contains(addr, ":") { + network = "tcp" + } exe, _ := os.Executable() cmd := exec.Command(filepath.Join(filepath.Dir(exe), "ollie-9p-mount"), - "-u", os.Getenv("USER"), "-net", "unix", "-addr", addr, mnt) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { + "-u", os.Getenv("USER"), "-net", network, "-addr", addr, mnt) + cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true} + if err := cmd.Start(); err != nil { fmt.Fprintf(os.Stderr, "ollie-9p-mount: %v\n", err) os.Exit(1) } - fmt.Printf("mounted %s at %s\n", addr, mnt) + fmt.Printf("mounted %s at %s (pid %d)\n", addr, mnt, cmd.Process.Pid) } func isRunning(sockPath string) bool { @@ -232,8 +235,20 @@ func runServer(sockPath, pidPath string) { agentsDirs := agent.AgentsDirs() sessionsDir := paths.CfgDir() + "/sessions" toolTree := fs.NewTree([]string{execute.ToolsPath()}, fs.Perms[fs.PathTools].FileMode, fs.WithIndex(ToolIndex)) + skillTree := fs.NewSkillTree() transcriptStore := fs.NewTree([]string{transcriptDir}, fs.Perms[fs.PathTranscripts].FileMode, fs.WithReadOnly()) + listTree := func(t *fs.Tree) func() []string { + return func() []string { + entries, _ := t.List() + names := make([]string, 0, len(entries)) + for _, e := range entries { + names = append(names, e.Name()) + } + return names + } + } + mgr := session.NewManager(session.ManagerConfig{ AgentsDir: agentsDirs[0], SessionsDir: sessionsDir, @@ -244,6 +259,10 @@ func runServer(sockPath, pidPath string) { NoMount: *tcpAddr != "", ToolTree: toolTree, InvalidateModels: modelCache.Invalidate, + ListHandlers: map[string]func() []string{ + "tools": listTree(toolTree), + "skills": listTree(skillTree), + }, SaveTranscript: func(data []byte) error { name := time.Now().Format("20060102T150405") + "-chat.md" e, err := transcriptStore.Open(name) @@ -266,7 +285,7 @@ func runServer(sockPath, pidPath string) { ToolTree: toolTree, UtilStore: fs.NewTree([]string{paths.CfgDir() + "/scripts/u"}, fs.Perms[fs.PathUtils].FileMode, fs.WithReadOnly()), PluginStore: fs.NewTree([]string{execute.PluginsPath()}, fs.Perms[fs.PathPlugins].FileMode, fs.WithReadOnly()), - SkillTree: fs.NewSkillTree(), + SkillTree: skillTree, SessionMgr: mgr, TranscriptStore: transcriptStore, TmpStore: fs.NewTree([]string{tmpDir}, fs.Perms[fs.PathTmp].FileMode), diff --git a/session/session.go b/session/session.go index 3fb6daf..25a0a90 100644 --- a/session/session.go +++ b/session/session.go @@ -143,6 +143,9 @@ type ManagerConfig struct { NoMount bool // InvalidateModels clears the model cache, forcing a refresh. InvalidateModels func() + // ListHandlers provides harness-specific list implementations for slash + // commands (/skills, /tools, etc.). Passed through to AgentCoreConfig. + ListHandlers map[string]func() []string } // Manager manages session lifecycle and exposes sessions as a Tree. @@ -581,6 +584,7 @@ func (s *Manager) createSession(args []string) error { } var core agent.Core + var sessPtr *Session var allowTools []string uname := s.nextUname() if s.cfg.NewCore != nil { @@ -639,6 +643,7 @@ func (s *Manager) createSession(args []string) error { rt := agent.BuildRuntime(cfg, newDisp(), cwd, []string{"OLLIE_SESSION_ID=" + sessID, "OLLIE_UNAME=" + uname, "OLLIE=" + execute.MountPath(uname)}) + // sessPtr is set after NewSession; the ReadPlanStep closure captures it. core = agent.NewAgentCore(agent.AgentCoreConfig{ Backend: be, AgentName: agentName, @@ -650,11 +655,23 @@ func (s *Manager) createSession(args []string) error { Runtime: rt, NewDispatcher: newDisp, Log: s.cfg.Sink.NewLogger("core"), + ReadPlanStep: func() string { + if sessPtr == nil { + return "" + } + sessPtr.mu.RLock() + data := make([]byte, len(sessPtr.plan)) + copy(data, sessPtr.plan) + sessPtr.mu.RUnlock() + return agent.NextUncheckedStep(data) + }, + ListHandlers: s.cfg.ListHandlers, }) } ctx, cancel := context.WithCancel(context.Background()) sess := NewSession(sessID, core, ctx, cancel) + sessPtr = sess sess.AllowTools = allowTools s.mu.Lock()