56 lines
1.7 KiB
Go
56 lines
1.7 KiB
Go
package toolsrv
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// Addr describes how to reach a tool server.
|
|
type Addr struct {
|
|
// Network is the transport: "local", "ssh", or (future) "unix".
|
|
Network string
|
|
// Host is the SSH target (user@host or user@host:port). Empty for local.
|
|
Host string
|
|
// CWD is the working directory on the target.
|
|
CWD string
|
|
}
|
|
|
|
// LocalAddr returns an Addr for an in-process tool server.
|
|
func LocalAddr(cwd string) Addr {
|
|
return Addr{Network: "local", CWD: cwd}
|
|
}
|
|
|
|
// SSHAddr returns an Addr for a remote tool server over SSH.
|
|
func SSHAddr(host, cwd string) Addr {
|
|
return Addr{Network: "ssh", Host: host, CWD: cwd}
|
|
}
|
|
|
|
// Dial connects to a tool server at the given address.
|
|
// Options (WithStrict, WithBuiltins, etc.) are applied to local servers.
|
|
//
|
|
// TODO: Unify local and remote behind a single protocol. Local execution
|
|
// should eventually go through a Unix socket (same JSON-RPC as remote),
|
|
// making the agent always a client. The elevation broker already proves
|
|
// this pattern. Benefits: process isolation, shared tool server across
|
|
// sessions, independent lifecycle. Transport becomes the only difference:
|
|
// - Network "local" → unix socket to co-located toolsrv process
|
|
// - Network "ssh" → SSH tunnel to remote toolsrv process
|
|
// - Network "unix" → pre-existing unix socket
|
|
func Dial(ctx context.Context, addr Addr, opts ...Option) (Runner, error) {
|
|
switch addr.Network {
|
|
case "", "local":
|
|
srv := New(addr.CWD)
|
|
for _, o := range opts {
|
|
o(srv)
|
|
}
|
|
return srv, nil
|
|
case "ssh":
|
|
return RemoteDial(ctx, RemoteConfig{
|
|
SSHTarget: addr.Host,
|
|
CWD: addr.CWD,
|
|
})
|
|
default:
|
|
return nil, fmt.Errorf("toolsrv.Dial: unsupported network %q", addr.Network)
|
|
}
|
|
}
|