olliesrv: add -strict and -yolo flags

-strict: only tool steps allowed, inline code rejected.
-yolo: skip landrun sandbox for execute_code.
This commit is contained in:
Logan Neely 2026-05-07 22:27:27 +02:00
parent 9bfccebff6
commit 88ea073135
4 changed files with 57 additions and 3 deletions

View File

@ -123,6 +123,21 @@ The server listens on a Unix socket in the Plan 9 namespace (`$NAMESPACE/ollie`)
`olliesrv mount` is for remote instances: it calls `9pfuse <addr> <mnt>` and defaults the mountpoint to `$HOME/mnt/<addr>`.
### Flags
| Flag | Effect |
|------|--------|
| `-strict` | Only `{tool}` steps are allowed in `execute_code`; inline `{code}` steps are rejected. |
| `-yolo` | Skip the landrun sandbox for all `execute_code` execution. |
| `-tcp <addr>` | Also listen on a TCP address (e.g. `:564`). |
| `-mount <path>` | Override the FUSE mount path. |
```sh
olliesrv start -strict # tools only, sandboxed
olliesrv start -yolo # arbitrary code, no sandbox
olliesrv start -strict -yolo # tools only, no sandbox
```
## Sessions
### Create

17
main.go
View File

@ -20,6 +20,8 @@ const serviceName = "ollie"
var mountPath = flag.String("mount", "", "FUSE mount path (default: $HOME/mnt/ollie)")
var tcpAddr = flag.String("tcp", "", "also listen on TCP address (e.g. :564)")
var strict = flag.Bool("strict", false, "only allow tool steps; reject inline code")
var yolo = flag.Bool("yolo", false, "skip landrun sandbox for execute_code")
func main() {
if len(os.Args) < 2 {
@ -115,6 +117,12 @@ func daemonize(pidPath string) {
if *tcpAddr != "" {
args = append(args, "-tcp", *tcpAddr)
}
if *strict {
args = append(args, "-strict")
}
if *yolo {
args = append(args, "-yolo")
}
cmd := exec.Command(exe, args...)
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
if err := cmd.Start(); err != nil {
@ -152,7 +160,14 @@ func runServer(sockPath, pidPath string) {
os.WriteFile(pidPath, []byte(fmt.Sprintf("%d", os.Getpid())), 0644) //nolint:errcheck
sink := olog.NewSink(os.Stdout, os.Stderr, olog.ParseLevel(os.Getenv("OLLIE_LOG"), olog.LevelWarn))
srv := New(sink)
var srvOpts []ServerOption
if *strict {
srvOpts = append(srvOpts, WithStrict())
}
if *yolo {
srvOpts = append(srvOpts, WithYolo())
}
srv := New(sink, srvOpts...)
listener, err := net.Listen("unix", sockPath)
if err != nil {

View File

@ -226,10 +226,18 @@ type Server struct {
sessionStore *SessionStore
transcriptStore Store
tmpStore Store
strict bool
yolo bool
}
// ServerOption configures the 9P server.
type ServerOption func(*Server)
func WithStrict() ServerOption { return func(s *Server) { s.strict = true } }
func WithYolo() ServerOption { return func(s *Server) { s.yolo = true } }
// New creates a new Server.
func New(sink *olog.Sink) *Server {
func New(sink *olog.Sink, opts ...ServerOption) *Server {
memDir := defaultMemDir()
os.MkdirAll(memDir, 0755) //nolint:errcheck
transcriptDir := defaultTranscriptDir()
@ -252,11 +260,16 @@ func New(sink *olog.Sink) *Server {
transcriptStore: NewFlatDirStore(transcriptDir, 0444),
tmpStore: NewFlatDirStore(tmpDir, 0600),
}
for _, o := range opts {
o(s)
}
s.sessionStore = store.NewSessionStore(store.SessionStoreConfig{
AgentsDir: agentsDir,
SessionsDir: sessionsDir,
Log: s.log,
Sink: s.sink,
Strict: s.strict,
Yolo: s.yolo,
SaveTranscript: func(data []byte) error {
name := time.Now().Format("20060102T150405") + "-chat.md"
return storeWrite(s.transcriptStore, name, data)

View File

@ -110,6 +110,10 @@ type SessionStoreConfig struct {
// NewCore, if non-nil, replaces the default backend.New + agent.NewAgentCore
// path. It receives the session ID, agent name, and cwd, and returns a Core.
NewCore func(sessionID, agentName, cwd string) (agent.Core, error)
// Strict rejects inline code steps; only tool steps are allowed.
Strict bool
// Yolo skips the landrun sandbox.
Yolo bool
}
// SessionStore implements Store for session management.
@ -371,8 +375,15 @@ func (s *SessionStore) createSession(args []string) error {
cfg := LoadAgentConfig(s.cfg.AgentsDir, agentName, nil)
var execOpts []execute.Option
if s.cfg.Strict {
execOpts = append(execOpts, execute.WithStrict())
}
if s.cfg.Yolo {
execOpts = append(execOpts, execute.WithYolo())
}
newDisp := tools.NewDispatcherFunc(map[string]func() tools.Server{
"execute": execute.Decl(cwd),
"execute": execute.Decl(cwd, execOpts...),
})
env := agent.BuildAgentEnv(cfg, newDisp(), cwd)