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.
This commit is contained in:
Théo Monnom
2026-08-21 17:57:57 -07:00
parent 67cc9dd9ba
commit 4a9af5cc3d
3 changed files with 10 additions and 121 deletions
-111
View File
@@ -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()
}
@@ -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"
+4 -4
View File
@@ -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,