From 51537e9c0f81b2b1e08ea76e6003aef9d2378d4c Mon Sep 17 00:00:00 2001 From: Nishad Musthafa Date: Sun, 29 Jun 2025 23:18:53 -0700 Subject: [PATCH 1/2] Adding support in livekit-cli for dynamic dispatch rules PR for dynamic dispatch rules: https://github.com/livekit/protocol/pull/1123 go.mod changes will be made once that PR is approved. --- cmd/lk/sip.go | 177 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 133 insertions(+), 44 deletions(-) diff --git a/cmd/lk/sip.go b/cmd/lk/sip.go index 109a4ffe..c71cd809 100644 --- a/cmd/lk/sip.go +++ b/cmd/lk/sip.go @@ -227,57 +227,19 @@ var ( Usage: "Create a SIP Dispatch Rule", Action: createSIPDispatchRule, ArgsUsage: RequestDesc[livekit.CreateSIPDispatchRuleRequest](), - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "name", - Usage: "Sets a new name for the dispatch rule", - }, - &cli.StringSliceFlag{ - Name: "trunks", - Usage: "Sets a list of trunks for the dispatch rule", - }, - &cli.StringFlag{ - Name: "direct", - Usage: "Sets a direct dispatch to a specified room", - }, - &cli.StringFlag{ - Name: "caller", - Aliases: []string{"individual"}, - Usage: "Sets a individual caller dispatch to a new room with a specific prefix", - }, - &cli.StringFlag{ - Name: "callee", - Usage: "Sets a callee number dispatch to a new room with a specific prefix", - }, - &cli.BoolFlag{ - Name: "pin", - Usage: "PIN for a dispatch rule", - }, - &cli.BoolFlag{ - Name: "randomize", - Usage: "Randomize room name, only applies to callee dispatch", - }, - }, + Flags: sipDispatchRuleBaseFlags, }, { Name: "update", Usage: "Update a SIP Dispatch Rule", Action: updateSIPDispatchRule, ArgsUsage: RequestDesc[livekit.UpdateSIPDispatchRuleRequest](), - Flags: []cli.Flag{ + Flags: append([]cli.Flag{ &cli.StringFlag{ Name: "id", Usage: "ID for the rule to update", }, - &cli.StringFlag{ - Name: "name", - Usage: "Sets a new name for the rule", - }, - &cli.StringSliceFlag{ - Name: "trunks", - Usage: "Sets a new list of trunk IDs", - }, - }, + }, sipDispatchRuleBaseFlags...), }, { Name: "delete", @@ -413,6 +375,47 @@ var ( }, }, } + + // Define a shared base flag list for SIP Dispatch Rule create/update + sipDispatchRuleBaseFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "name", + Usage: "Sets a name for the dispatch rule", + }, + &cli.StringSliceFlag{ + Name: "trunks", + Usage: "Sets a list of trunks for the dispatch rule", + }, + &cli.StringFlag{ + Name: "direct", + Usage: "Sets a direct dispatch to a specified room", + }, + &cli.StringFlag{ + Name: "caller", + Aliases: []string{"individual"}, + Usage: "Sets an individual caller dispatch to a new room with a specific prefix", + }, + &cli.StringFlag{ + Name: "callee", + Usage: "Sets a callee number dispatch to a new room with a specific prefix", + }, + &cli.BoolFlag{ + Name: "pin", + Usage: "PIN for a dispatch rule", + }, + &cli.BoolFlag{ + Name: "randomize", + Usage: "Randomize room name, only applies to callee dispatch", + }, + &cli.StringFlag{ + Name: "dispatch-url", + Usage: "Sets a dynamic dispatch rule with webhook URL (uses POST method)", + }, + &cli.StringFlag{ + Name: "method", + Usage: "Sets the HTTP method for dynamic dispatch rule (default: POST)", + }, + } ) func listUpdateFlag(cmd *cli.Command, setName string) *livekit.ListUpdate { @@ -895,6 +898,23 @@ func createSIPDispatchRule(ctx context.Context, cmd *cli.Command) error { }, } } + if val := cmd.String("dispatch-url"); val != "" { + if p.Rule != nil { + return fmt.Errorf("only one dispatch rule type is allowed") + } + method := cmd.String("method") + if method == "" { + method = "POST" + } + p.Rule = &livekit.SIPDispatchRule{ + Rule: &livekit.SIPDispatchRule_DispatchRuleDynamic{ + DispatchRuleDynamic: &livekit.SIPDispatchRuleDynamic{ + Url: val, + Method: method, + }, + }, + } + } return nil }, cli.CreateSIPDispatchRule, printSIPDispatchRuleID) } @@ -945,6 +965,71 @@ func updateSIPDispatchRule(ctx context.Context, cmd *cli.Command) error { if id == "" { return errors.New("no ID specified") } + + // Check if any dispatch rule flags are set + hasDispatchRuleFlags := cmd.IsSet("direct") || cmd.IsSet("caller") || cmd.IsSet("callee") || cmd.IsSet("dispatch-url") + + if hasDispatchRuleFlags { + // Create a new dispatch rule from flags (similar to create function) + rule := &livekit.SIPDispatchRule{} + + if val := cmd.String("direct"); val != "" { + rule.Rule = &livekit.SIPDispatchRule_DispatchRuleDirect{ + DispatchRuleDirect: &livekit.SIPDispatchRuleDirect{ + RoomName: val, + Pin: cmd.String("pin"), + }, + } + } else if val := cmd.String("caller"); val != "" { + rule.Rule = &livekit.SIPDispatchRule_DispatchRuleIndividual{ + DispatchRuleIndividual: &livekit.SIPDispatchRuleIndividual{ + RoomPrefix: val, + Pin: cmd.String("pin"), + }, + } + } else if val := cmd.String("callee"); val != "" { + rule.Rule = &livekit.SIPDispatchRule_DispatchRuleCallee{ + DispatchRuleCallee: &livekit.SIPDispatchRuleCallee{ + RoomPrefix: val, + Randomize: cmd.Bool("randomize"), + Pin: cmd.String("pin"), + }, + } + } else if val := cmd.String("dispatch-url"); val != "" { + method := cmd.String("method") + if method == "" { + method = "POST" + } + rule.Rule = &livekit.SIPDispatchRule_DispatchRuleDynamic{ + DispatchRuleDynamic: &livekit.SIPDispatchRuleDynamic{ + Url: val, + Method: method, + }, + } + } + + // Use Update action with the rule field populated + req := &livekit.SIPDispatchRuleUpdate{ + Rule: rule, + } + if val := cmd.String("name"); val != "" { + req.Name = &val + } + req.TrunkIds = listUpdateFlag(cmd, "trunks") + + info, err := cli.UpdateSIPDispatchRule(ctx, &livekit.UpdateSIPDispatchRuleRequest{ + SipDispatchRuleId: id, + Action: &livekit.UpdateSIPDispatchRuleRequest_Update{ + Update: req, + }, + }) + if err != nil { + return err + } + printSIPDispatchRuleID(info) + return err + } + req := &livekit.SIPDispatchRuleUpdate{} if val := cmd.String("name"); val != "" { req.Name = &val @@ -969,10 +1054,10 @@ func listSipDispatchRule(ctx context.Context, cmd *cli.Command) error { return err } return listAndPrint(ctx, cmd, cli.ListSIPDispatchRule, &livekit.ListSIPDispatchRuleRequest{}, []string{ - "SipDispatchRuleID", "Name", "SipTrunks", "Type", "RoomName", "Pin", + "SipDispatchRuleID", "Name", "SipTrunks", "Type", "RoomName", "Pin", "DispatchURL", "Attributes", "Agents", }, func(item *livekit.SIPDispatchRuleInfo) []string { - var room, typ, pin string + var room, typ, pin, dispatchUrl string switch r := item.GetRule().GetRule().(type) { case *livekit.SIPDispatchRule_DispatchRuleDirect: room = r.DispatchRuleDirect.RoomName @@ -989,6 +1074,10 @@ func listSipDispatchRule(ctx context.Context, cmd *cli.Command) error { } pin = r.DispatchRuleCallee.Pin typ = "Callee" + case *livekit.SIPDispatchRule_DispatchRuleDynamic: + room = "" + dispatchUrl = r.DispatchRuleDynamic.Url + typ = "Dynamic" } trunks := strings.Join(item.TrunkIds, ",") if trunks == "" { @@ -1001,7 +1090,7 @@ func listSipDispatchRule(ctx context.Context, cmd *cli.Command) error { } } return []string{ - item.SipDispatchRuleId, item.Name, trunks, typ, room, pin, + item.SipDispatchRuleId, item.Name, trunks, typ, room, pin, dispatchUrl, fmt.Sprintf("%v", item.Attributes), strings.Join(agents, ","), } }) From 71f1aa52801866cb64f9b2af8f634a580b86f11d Mon Sep 17 00:00:00 2001 From: Nishad Musthafa Date: Sun, 29 Jun 2025 23:24:22 -0700 Subject: [PATCH 2/2] Temporarily pointing livekit-cli to the PR commit to make the build work --- go.mod | 3 +-- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3f2878c4..6795dcf7 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/go-logr/logr v1.4.3 github.com/go-task/task/v3 v3.43.3 github.com/joho/godotenv v1.5.1 - github.com/livekit/protocol v1.39.3-0.20250620210232-022f52ebc520 + github.com/livekit/protocol v1.39.4-0.20250630060303-c71f9553b08a github.com/livekit/server-sdk-go/v2 v2.9.2-0.20250612220331-fb6301c37033 github.com/moby/buildkit v0.22.0 github.com/pion/rtcp v1.2.15 @@ -47,7 +47,6 @@ require ( github.com/alecthomas/chroma/v2 v2.16.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/atotto/clipboard v0.1.4 // indirect - github.com/aws/smithy-go v1.22.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/go.sum b/go.sum index 4f6ccab8..d6d85ab7 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= -github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= @@ -278,8 +276,8 @@ github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731 h1:9x+U2HGLrSw5AT github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731/go.mod h1:Rs3MhFwutWhGwmY1VQsygw28z5bWcnEYmS1OG9OxjOQ= github.com/livekit/mediatransportutil v0.0.0-20250519131108-fb90f5acfded h1:ylZPdnlX1RW9Z15SD4mp87vT2D2shsk0hpLJwSPcq3g= github.com/livekit/mediatransportutil v0.0.0-20250519131108-fb90f5acfded/go.mod h1:mSNtYzSf6iY9xM3UX42VEI+STHvMgHmrYzEHPcdhB8A= -github.com/livekit/protocol v1.39.3-0.20250620210232-022f52ebc520 h1:PDL0srf3NH7B6XnAHyRZkvcZq808R0rBTAvPr9W0NiQ= -github.com/livekit/protocol v1.39.3-0.20250620210232-022f52ebc520/go.mod h1:W1zjNtf9w2EVlVfdfXjRp+K9Ng51KWKsBG7Sghk9x3Y= +github.com/livekit/protocol v1.39.4-0.20250630060303-c71f9553b08a h1:8W+OwGRRPwVu2rFefuYq6i4dR5Yw1obqF1F9Nh7pYEs= +github.com/livekit/protocol v1.39.4-0.20250630060303-c71f9553b08a/go.mod h1:6HPISM0bkTXTk9RIaQTCe0IDbomBPz7Jwp+N3w5sqL0= github.com/livekit/psrpc v0.6.1-0.20250511053145-465289d72c3c h1:WwEr0YBejYbKzk8LSaO9h8h0G9MnE7shyDu8yXQWmEc= github.com/livekit/psrpc v0.6.1-0.20250511053145-465289d72c3c/go.mod h1:kmD+AZPkWu0MaXIMv57jhNlbiSZZ/Jx4bzlxBDVmJes= github.com/livekit/server-sdk-go/v2 v2.9.2-0.20250612220331-fb6301c37033 h1:5znH+FcwNGJMVfLVqrTcVMeurZGTcVnH+4l4o1wfU5k=