mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-04 19:55:09 -04:00
Two field-test findings drive this change: the direct-dial path needed sudo (the profile's WireGuard key is root-owned), and a single flat ANTHROPIC_* export set is wrong for providers that speak other API shapes. Relay the setup request through the daemon instead: a new GetAgentNetworkSetup daemon RPC forwards to management over the engine's existing peer connection, so unprivileged callers get the caller-scoped answer the same way 'netbird status' works — no sudo, and the key never leaves the daemon. The daemon's JSON gateway exposes the RPC for the desktop UI for free. Teach 'agent-network env' the per-provider environment contracts, mirroring Claude Code's LLM-gateway configuration: - anthropic flavor: ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN / ANTHROPIC_MODEL - bedrock_api: CLAUDE_CODE_USE_BEDROCK, ANTHROPIC_BEDROCK_BASE_URL, CLAUDE_CODE_SKIP_BEDROCK_AUTH (the proxy injects AWS credentials) - vertex_ai_api: CLAUDE_CODE_USE_VERTEX, ANTHROPIC_VERTEX_BASE_URL, CLAUDE_CODE_SKIP_VERTEX_AUTH, plus comments for the admin-supplied ANTHROPIC_VERTEX_PROJECT_ID and CLOUD_ML_REGION (the proxy forwards the URL path, so those values must be the operator's real ones) - openai flavor: OPENAI_BASE_URL / OPENAI_API_KEY - anything else: comment lines only — no guessed variables Selection stays explicit: --provider picks by operator label or catalog id and is required when several providers are authorized; --model is validated against the provider's allowed set and required when several models are allowed. Ambiguity renders as shell comments, never as exports. Linear: NET-1399
60 lines
1.9 KiB
Go
60 lines
1.9 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"google.golang.org/grpc/codes"
|
|
gstatus "google.golang.org/grpc/status"
|
|
|
|
"github.com/netbirdio/netbird/client/proto"
|
|
mgmProto "github.com/netbirdio/netbird/shared/management/proto"
|
|
)
|
|
|
|
// GetAgentNetworkSetup relays the peer's Agent Network setup request to the
|
|
// management server over the engine's existing connection. Running through
|
|
// the daemon keeps the WireGuard key inside the daemon — unprivileged CLI
|
|
// callers get a caller-scoped answer without reading the profile config.
|
|
func (s *Server) GetAgentNetworkSetup(ctx context.Context, _ *proto.GetAgentNetworkSetupRequest) (*proto.GetAgentNetworkSetupResponse, error) {
|
|
s.mutex.Lock()
|
|
clientRunning := s.clientRunning
|
|
connectClient := s.connectClient
|
|
s.mutex.Unlock()
|
|
|
|
if !clientRunning || connectClient == nil {
|
|
return nil, gstatus.Errorf(codes.FailedPrecondition, "client is not running, run 'netbird up' first")
|
|
}
|
|
engine := connectClient.Engine()
|
|
if engine == nil {
|
|
return nil, gstatus.Errorf(codes.FailedPrecondition, "engine not initialized")
|
|
}
|
|
|
|
setupCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
|
defer cancel()
|
|
|
|
setup, err := engine.GetAgentNetworkSetup(setupCtx)
|
|
if err != nil {
|
|
return nil, gstatus.Errorf(codes.Internal, "get agent network setup: %v", err)
|
|
}
|
|
|
|
return toDaemonAgentNetworkSetup(setup), nil
|
|
}
|
|
|
|
func toDaemonAgentNetworkSetup(setup *mgmProto.AgentNetworkSetupResponse) *proto.GetAgentNetworkSetupResponse {
|
|
resp := &proto.GetAgentNetworkSetupResponse{
|
|
Configured: setup.Configured,
|
|
Endpoint: setup.Endpoint,
|
|
Providers: make([]*proto.AgentNetworkProvider, 0, len(setup.Providers)),
|
|
}
|
|
for _, p := range setup.Providers {
|
|
resp.Providers = append(resp.Providers, &proto.AgentNetworkProvider{
|
|
Name: p.Name,
|
|
CatalogId: p.CatalogId,
|
|
ApiFlavor: p.ApiFlavor,
|
|
AllModelsAllowed: p.AllModelsAllowed,
|
|
Models: p.Models,
|
|
})
|
|
}
|
|
return resp
|
|
}
|