From 4a9af5cc3df7a97af4ff595661b9002825a4c993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Fri, 21 Aug 2026 17:57:57 -0700 Subject: [PATCH] agent endpoints: drop the sidecar cmd, make the conformance client test infra - remove cmd/agent-endpoint-client: the Python SDK has landed, so the manual sidecar for non-SDK workers is no longer needed. - move pkg/agent/endpoint/client to pkg/agent/endpoint/conformance (package conformance) so it reads as the test harness it is, not a product client SDK; only the acceptance suite drives it. --- cmd/agent-endpoint-client/main.go | 111 ------------------ .../client.go => conformance/worker.go} | 12 +- pkg/service/agentendpoint_test.go | 8 +- 3 files changed, 10 insertions(+), 121 deletions(-) delete mode 100644 cmd/agent-endpoint-client/main.go rename pkg/agent/endpoint/{client/client.go => conformance/worker.go} (98%) diff --git a/cmd/agent-endpoint-client/main.go b/cmd/agent-endpoint-client/main.go deleted file mode 100644 index 8755a212e..000000000 --- a/cmd/agent-endpoint-client/main.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2026 LiveKit, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// agent-endpoint-client is the reference sidecar for the agent HTTP endpoints -// data plane: it registers a manifest against a livekit-server and bridges -// tunnel streams to any local HTTP server, standing in for the SDK's tunnel -// client until it lands. -// -// Example, against a dev server: -// -// livekit-server --dev & -// python app.py # any local HTTP server on :8080 -// agent-endpoint-client -url ws://localhost:7880/agent -api-key devkey \ -// -api-secret secret -deployment production -target 127.0.0.1:8080 \ -// -route "GET /json" -route "public GET /sse" -// curl http://localhost:7880/agents/production/json -package main - -import ( - "context" - "flag" - "fmt" - "os" - "os/signal" - "strings" - "syscall" - - "github.com/livekit/protocol/livekit" - "github.com/livekit/protocol/logger" - - "github.com/livekit/livekit-server/pkg/agent/endpoint/client" -) - -type routeFlags []string - -func (r *routeFlags) String() string { return strings.Join(*r, ",") } -func (r *routeFlags) Set(v string) error { *r = append(*r, v); return nil } - -func main() { - var ( - url = flag.String("url", "ws://localhost:7880/agent", "livekit-server /agent URL") - apiKey = flag.String("api-key", "devkey", "API key") - apiSecret = flag.String("api-secret", "secret", "API secret") - agentName = flag.String("agent-name", "endpoint-sidecar", "agent name") - deployment = flag.String("deployment", "", "deployment name (empty = default)") - target = flag.String("target", "127.0.0.1:8080", "local HTTP server to bridge into") - routes routeFlags - ) - flag.Var(&routes, "route", `route to expose, e.g. "GET /json", "public POST /sms", repeatable`) - flag.Parse() - - if len(routes) == 0 { - fmt.Fprintln(os.Stderr, "at least one -route is required") - os.Exit(1) - } - - var endpoints []*livekit.AgentHttp_AgentEndpoint - for _, r := range routes { - parts := strings.Fields(r) - public := false - if len(parts) > 0 && parts[0] == "public" { - public = true - parts = parts[1:] - } - if len(parts) != 2 { - fmt.Fprintf(os.Stderr, "invalid -route %q, want \"[public] METHOD /path\"\n", r) - os.Exit(1) - } - endpoints = append(endpoints, &livekit.AgentHttp_AgentEndpoint{ - Path: parts[1], - Methods: []string{strings.ToUpper(parts[0])}, - Public: public, - }) - } - - logger.InitFromConfig(&logger.Config{Level: "info"}, "agent-endpoint-client") - - w := client.New(client.Config{ - ServerURL: *url, - APIKey: *apiKey, - APISecret: *apiSecret, - AgentName: *agentName, - Deployment: *deployment, - Endpoints: endpoints, - TargetAddr: *target, - Logger: logger.GetLogger(), - }) - - ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) - defer cancel() - - if err := w.Start(ctx); err != nil { - fmt.Fprintln(os.Stderr, "start failed:", err) - os.Exit(1) - } - logger.Infow("endpoint sidecar attached", "workerID", w.WorkerID(), "routes", len(endpoints)) - - <-ctx.Done() - w.Close() -} diff --git a/pkg/agent/endpoint/client/client.go b/pkg/agent/endpoint/conformance/worker.go similarity index 98% rename from pkg/agent/endpoint/client/client.go rename to pkg/agent/endpoint/conformance/worker.go index 9d2dee2a5..e81cb72b9 100644 --- a/pkg/agent/endpoint/client/client.go +++ b/pkg/agent/endpoint/conformance/worker.go @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package client is the reference worker-side implementation of the agent HTTP -// endpoints data plane: it registers a manifest over the control connection, -// attaches the fixed wire pool, and bridges each stream to a local HTTP server. -// It doubles as the protocol conformance harness and as a manual sidecar for -// non-SDK workers. -package client +// Package conformance is a reference worker-side implementation of the agent +// HTTP endpoints data plane, used as test infrastructure: it registers a +// manifest over the control connection, attaches the fixed wire pool, and +// bridges each stream to a local HTTP server. The acceptance suite drives it to +// exercise the server end to end in Go, without a Python SDK worker. +package conformance import ( "context" diff --git a/pkg/service/agentendpoint_test.go b/pkg/service/agentendpoint_test.go index c6d11f2c5..f691c87b3 100644 --- a/pkg/service/agentendpoint_test.go +++ b/pkg/service/agentendpoint_test.go @@ -35,7 +35,7 @@ import ( "github.com/livekit/livekit-server/pkg/agent" "github.com/livekit/livekit-server/pkg/agent/endpoint" - "github.com/livekit/livekit-server/pkg/agent/endpoint/client" + "github.com/livekit/livekit-server/pkg/agent/endpoint/conformance" "github.com/livekit/livekit-server/pkg/config" "github.com/livekit/livekit-server/pkg/routing" "github.com/livekit/livekit-server/pkg/service" @@ -90,8 +90,8 @@ func (s *endpointStack) wsURL() string { return "ws" + strings.TrimPrefix(s.ts.URL, "http") + "/agent" } -func (s *endpointStack) startWorker(target string, deployment string, endpoints []*livekit.AgentHttp_AgentEndpoint) *client.Worker { - w := client.New(client.Config{ +func (s *endpointStack) startWorker(target string, deployment string, endpoints []*livekit.AgentHttp_AgentEndpoint) *conformance.Worker { + w := conformance.New(conformance.Config{ ServerURL: s.wsURL(), APIKey: testKey, APISecret: testSecret, @@ -366,7 +366,7 @@ func TestAgentEndpointsRetrySafety(t *testing.T) { deadTarget := "127.0.0.1:1" // nothing listens eps := []*livekit.AgentHttp_AgentEndpoint{httpEP("/json", []string{"GET"}, true)} - broken := client.New(client.Config{ + broken := conformance.New(conformance.Config{ ServerURL: stack.wsURL(), APIKey: testKey, APISecret: testSecret, AgentName: "test-agent", Deployment: "production", Endpoints: eps, TargetAddr: deadTarget,