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
This commit is contained in:
Levi Neely 2026-07-19 18:57:26 +02:00
parent eaa32cd94d
commit 4f8e0c2768
1 changed files with 19 additions and 5 deletions

View File

@ -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)})