From 4f8e0c276845ac7865c63a2c0903cbdcda6b42e9 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sun, 19 Jul 2026 18:57:26 +0200 Subject: [PATCH] session: wire remote= config for split-brain execution When creating a session with remote=user@host, the session manager uses remote.Decl() instead of execute.Decl() for the tool dispatcher. This forwards all tool calls over SSH to an ollie-remote process on the target host. Usage: printf "cwd=/path\nremote=user@host\n" > \$OLLIE/s/new --- session/session.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/session/session.go b/session/session.go index 474ffae..76905f8 100644 --- a/session/session.go +++ b/session/session.go @@ -18,6 +18,7 @@ import ( "ollie/pkg/config" olog "ollie/pkg/log" "ollie/pkg/paths" + "ollie/pkg/remote" "ollie/pkg/tools" "ollie/pkg/tools/execute" "olliesrv/fs" @@ -528,7 +529,7 @@ func (s *Manager) openEntry(name string) (fs.File, error) { return &fs.FileConfig{ StatFn: func() (os.FileInfo, error) { return &fs.SyntheticFileInfo{Name_: "new", Mode_: fs.Perms[fs.PathSessions].Files["new"]}, nil }, ReadFn: func() ([]byte, error) { - return []byte("name=\ncwd=\nbackend=\nmodel=\nagent=\nmaxTokens=\nmaxCompletionTokens=\ntemperature=\ntopP=\ntopK=\nminP=\ntopA=\nfrequencyPenalty=\npresencePenalty=\nrepetitionPenalty=\nreasoning=\nreasoningEffort=\nincludeReasoning=\nresponseFormat=\nstop=\nverbosity=\n"), nil + return []byte("name=\ncwd=\nremote=\nbackend=\nmodel=\nagent=\nmaxTokens=\nmaxCompletionTokens=\ntemperature=\ntopP=\ntopK=\nminP=\ntopA=\nfrequencyPenalty=\npresencePenalty=\nrepetitionPenalty=\nreasoning=\nreasoningEffort=\nincludeReasoning=\nresponseFormat=\nstop=\nverbosity=\n"), nil }, WriteFn: func(data []byte) error { _, err := s.CreateSession(strings.Fields(strings.TrimSpace(string(data)))) @@ -897,6 +898,7 @@ func (s *Manager) CreateSession(args []string) (string, error) { modelOverride := "" agentName := "default" cwd := "" + remoteTarget := "" for _, arg := range args { k, v, ok := strings.Cut(arg, "=") if !ok { @@ -916,8 +918,10 @@ func (s *Manager) CreateSession(args []string) (string, error) { agentName = v case "cwd": cwd = v + case "remote": + remoteTarget = v default: - return "", fmt.Errorf("unknown option %q (valid: name, backend, model, agent, cwd)", k) + return "", fmt.Errorf("unknown option %q (valid: name, backend, model, agent, cwd, remote)", k) } } if agentName == "default" { @@ -995,9 +999,19 @@ func (s *Manager) CreateSession(args []string) (string, error) { if cfg != nil && len(cfg.AllowTools) > 0 { execOpts = append(execOpts, execute.WithAllowTools(cfg.AllowTools)) } - newDisp := tools.NewDispatcherFunc(map[string]func() tools.Server{ - "execute": execute.Decl(cwd, execOpts...), - }) + var newDisp func() tools.Dispatcher + if remoteTarget != "" { + newDisp = tools.NewDispatcherFunc(map[string]func() tools.Server{ + "execute": remote.Decl(remote.Config{ + SSHTarget: remoteTarget, + CWD: cwd, + }), + }) + } else { + newDisp = tools.NewDispatcherFunc(map[string]func() tools.Server{ + "execute": execute.Decl(cwd, execOpts...), + }) + } rt := agent.BuildRuntime(cfg, newDisp(), cwd, []string{"OLLIE_SESSION_ID=" + sessID, "OLLIE_UNAME=" + uname, "OLLIE=" + MountPathFor(uname)})