94 lines
2.3 KiB
Go
94 lines
2.3 KiB
Go
// toolsrv — tool execution server.
|
|
//
|
|
// Accepts JSON-RPC 2.0 connections. Executes tool calls in a sandboxed
|
|
// environment. Used both locally (spawned by olliesrv) and remotely
|
|
// (deployed via SSH bootstrap).
|
|
//
|
|
// Usage:
|
|
//
|
|
// toolsrv serve --cwd /path/to/project [--listen /path/to/sock] [--yolo]
|
|
//
|
|
// When --listen is provided, accepts connections on a Unix socket.
|
|
// Otherwise, serves a single session over stdin/stdout (bootstrap mode).
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"path/filepath"
|
|
"syscall"
|
|
|
|
"ollie/env"
|
|
"ollie/toolsrv"
|
|
)
|
|
|
|
var (
|
|
cwd = flag.String("cwd", ".", "working directory for execution")
|
|
listenPath = flag.String("listen", "", "Unix socket path to listen on (default: stdio mode)")
|
|
yolo = flag.Bool("yolo", false, "skip sandbox enforcement")
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 || os.Args[1] != "serve" {
|
|
fmt.Fprintln(os.Stderr, "usage: toolsrv serve --cwd <path> [--listen <socket>]")
|
|
os.Exit(1)
|
|
}
|
|
flag.CommandLine.Parse(os.Args[2:])
|
|
|
|
env.EnsureDefaults()
|
|
|
|
// Prepend our bin dir to PATH so landrun is found (deployed alongside us).
|
|
home, _ := os.UserHomeDir()
|
|
binDir := filepath.Join(home, ".config", "ollie", "bin")
|
|
os.Setenv("PATH", binDir+":"+os.Getenv("PATH"))
|
|
|
|
toolReg, _ := toolsrv.NewRegistry()
|
|
sessionID := os.Getenv("OLLIE_SESSION_ID")
|
|
|
|
var opts []toolsrv.Option
|
|
if *yolo {
|
|
opts = append(opts, toolsrv.WithYolo())
|
|
}
|
|
if toolReg != nil && sessionID != "" {
|
|
opts = append(opts, toolsrv.WithToolRegistry(toolReg, sessionID))
|
|
}
|
|
server := toolsrv.New(*cwd)
|
|
for _, o := range opts {
|
|
o(server)
|
|
}
|
|
|
|
// Wire up environment propagation for late-arriving session IDs.
|
|
server.OnEnvSet = func(key, value string) {
|
|
switch key {
|
|
case "OLLIE_SESSION_ID":
|
|
os.Setenv("OLLIE_SESSION_ID", value)
|
|
if toolReg != nil {
|
|
server.SetToolRegistry(toolReg, value)
|
|
}
|
|
case "OLLIE_UNAME":
|
|
os.Setenv("OLLIE_UNAME", value)
|
|
}
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
sigCh := make(chan os.Signal, 1)
|
|
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
|
go func() {
|
|
<-sigCh
|
|
cancel()
|
|
}()
|
|
|
|
if *listenPath != "" {
|
|
if err := server.ServeSocket(ctx, *listenPath); err != nil {
|
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
} else {
|
|
server.ServeRPC(ctx, os.Stdin, os.Stdout)
|
|
}
|
|
}
|