Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 214 additions & 0 deletions cmd/lk/dispatch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
package main

import (
"context"
"errors"
"fmt"

"github.com/urfave/cli/v3"

"github.com/livekit/protocol/livekit"
"github.com/livekit/protocol/utils"
lksdk "github.com/livekit/server-sdk-go/v2"
)

var (
DispatchCommands = []*cli.Command{
{
Name: "dispatch",
Usage: "Create, list, and delete agent dispatches",
Category: "Agent",

Commands: []*cli.Command{
{
Name: "list",
Usage: "List all agent dispatches in a room",
Before: createDispatchClient,
Action: listAgentDispatches,
ArgsUsage: "ROOM_NAME",
},
{
Name: "get",
Usage: "Get an agent dispatch by room and ID",
Before: createDispatchClient,
Action: getAgentDispatch,
ArgsUsage: "ROOM_NAME ID",
},
{
Name: "create",
Usage: "Create an agent dispatch",
Before: createDispatchClient,
Action: createAgentDispatch,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "room",
Usage: "room name",
},
&cli.BoolFlag{
Name: "new-room",
Usage: "when set, will generate a unique room name",
},
&cli.StringFlag{
Name: "agent-name",
Usage: "agent to dispatch",
},
&cli.StringFlag{
Name: "metadata",
Usage: "metadata to send to agent",
},
},
},
{
Name: "delete",
Usage: "Delete an agent dispatch",
Before: createDispatchClient,
Action: deleteAgentDispatch,
ArgsUsage: "ROOM_NAME ID",
},
},
},
}

dispatchClient *lksdk.AgentDispatchClient
)

func createDispatchClient(ctx context.Context, cmd *cli.Command) error {
pc, err := loadProjectDetails(cmd)
if err != nil {
return err
}

dispatchClient = lksdk.NewAgentDispatchServiceClient(pc.URL, pc.APIKey, pc.APISecret, withDefaultClientOpts(pc)...)
return nil
}

func getAgentDispatch(ctx context.Context, cmd *cli.Command) error {
if cmd.Args().Len() == 0 {
return cli.ShowSubcommandHelp(cmd)
}
roomName := cmd.Args().First()
if roomName == "" {
return errors.New("room name is required")
}
id := cmd.Args().Get(1)
if id == "" {
return errors.New("dispatch ID is required")
}

return listDispatchAndPrint(cmd, &livekit.ListAgentDispatchRequest{
Room: roomName,
DispatchId: id,
})
}

func listAgentDispatches(ctx context.Context, cmd *cli.Command) error {
if cmd.Args().Len() == 0 {
return cli.ShowSubcommandHelp(cmd)
}
roomName := cmd.Args().First()
if roomName == "" {
return errors.New("room name is required")
}

return listDispatchAndPrint(cmd, &livekit.ListAgentDispatchRequest{
Room: roomName,
})
}

func listDispatchAndPrint(cmd *cli.Command, req *livekit.ListAgentDispatchRequest) error {
if cmd.Args().Len() == 0 {
return cli.ShowSubcommandHelp(cmd)
}
if cmd.Bool("verbose") {
PrintJSON(req)
}
res, err := dispatchClient.ListDispatch(context.Background(), req)
if err != nil {
return err
}
if cmd.Bool("json") {
PrintJSON(res)
} else {
table := CreateTable().
Headers("DispatchID", "Room", "AgentName", "Metadata")
for _, item := range res.AgentDispatches {
if item == nil {
continue
}

table.Row(
item.Id,
item.Room,
item.AgentName,
item.Metadata,
)
}
fmt.Println(table)
}
return nil
}

func createAgentDispatch(ctx context.Context, cmd *cli.Command) error {
req := &livekit.CreateAgentDispatchRequest{
Room: cmd.String("room"),
AgentName: cmd.String("agent-name"),
Metadata: cmd.String("metadata"),
}
if cmd.Bool("new-room") {
req.Room = utils.NewGuid("room-")
}
if req.Room == "" {
_ = cli.ShowSubcommandHelp(cmd)
return errors.New("room or new-room is required")
}
if req.AgentName == "" {
_ = cli.ShowSubcommandHelp(cmd)
return errors.New("agent-name is required")
}
if cmd.Bool("verbose") {
PrintJSON(req)
}

info, err := dispatchClient.CreateDispatch(context.Background(), req)
if err != nil {
return err
}

if cmd.Bool("json") {
PrintJSON(info)
} else {
fmt.Printf("Dispatch created: %v\n", info)
}

return nil
}

func deleteAgentDispatch(ctx context.Context, cmd *cli.Command) error {
if cmd.Args().Len() == 0 {
return cli.ShowSubcommandHelp(cmd)
}

roomName := cmd.Args().First()
if roomName == "" {
return errors.New("room name is required")
}
id := cmd.Args().Get(1)
if id == "" {
return errors.New("dispatch ID is required")
}

info, err := dispatchClient.DeleteDispatch(ctx, &livekit.DeleteAgentDispatchRequest{
Room: roomName,
DispatchId: id,
})
if err != nil {
return err
}

if cmd.Bool("json") {
PrintJSON(info)
} else {
fmt.Printf("Dispatch deleted: %v\n", info)
}
return nil
}
2 changes: 1 addition & 1 deletion cmd/lk/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"time"

"github.com/pion/rtcp"
"github.com/pion/webrtc/v3"
"github.com/pion/webrtc/v4"
"github.com/urfave/cli/v3"

"github.com/livekit/protocol/livekit"
Expand Down
1 change: 1 addition & 0 deletions cmd/lk/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func main() {
app.Commands = append(app.Commands, LoadTestCommands...)
app.Commands = append(app.Commands, ProjectCommands...)
app.Commands = append(app.Commands, SIPCommands...)
app.Commands = append(app.Commands, DispatchCommands...)

// Register cleanup hook for SIGINT, SIGTERM, SIGQUIT
ctx, stop := signal.NotifyContext(
Expand Down
12 changes: 6 additions & 6 deletions cmd/lk/room.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"strings"
"syscall"

"github.com/pion/webrtc/v3"
"github.com/pion/webrtc/v4"
"github.com/urfave/cli/v3"
"google.golang.org/protobuf/encoding/protojson"

Expand Down Expand Up @@ -73,8 +73,8 @@ var (
TakesFile: true,
},
&cli.StringFlag{
Name: "room-configuration",
Usage: "`NAME` of the room configuration to associate with the created room",
Name: "room-preset",
Usage: "`NAME` of the room configuration preset to associate with the created room",
},
&cli.UintFlag{
Name: "min-playout-delay",
Expand Down Expand Up @@ -594,11 +594,11 @@ func createRoom(ctx context.Context, cmd *cli.Command) error {
if err = protojson.Unmarshal(b, agent); err != nil {
return err
}
req.Agent = agent
req.Agents = agent.Dispatches
}

if roomConfig := cmd.String("room-configuration"); roomConfig != "" {
req.ConfigName = roomConfig
if roomPreset := cmd.String("room-preset"); roomPreset != "" {
req.RoomPreset = roomPreset
}

if cmd.Uint("min-playout-delay") != 0 {
Expand Down
9 changes: 6 additions & 3 deletions cmd/lk/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,10 @@ func createToken(ctx context.Context, c *cli.Command) error {
room := c.String("room")
metadata := c.String("metadata")
validFor := c.String("valid-for")
roomPreset := c.String("room-preset")

grant := &auth.VideoGrant{
Room: room,
RoomConfiguration: c.String("room-configuration"),
Room: room,
}
hasPerms := false
if c.Bool("create") {
Expand Down Expand Up @@ -333,6 +333,9 @@ func createToken(ctx context.Context, c *cli.Command) error {
if metadata != "" {
at.SetMetadata(metadata)
}
if roomPreset != "" {
at.SetRoomPreset(roomPreset)
}
if name == "" {
name = p
}
Expand Down Expand Up @@ -364,7 +367,7 @@ func accessToken(apiKey, apiSecret string, grant *auth.VideoGrant, identity stri
return nil
}
at := auth.NewAccessToken(apiKey, apiSecret).
AddGrant(grant).
SetVideoGrant(grant).
SetIdentity(identity)
return at
}
Loading
Loading