From 86fcc6dd0888e38ee666d987e97d5f24734263cb Mon Sep 17 00:00:00 2001
From: Alessio Perugini <alessio@perugini.xyz>
Date: Wed, 16 Apr 2025 21:38:07 +0200
Subject: [PATCH] libraries: expose Dependencies field

---
 commands/service_library_search.go            |   3 +-
 internal/arduino/libraries/libraries.go       |  25 +++
 .../arduino/libraries/librariesindex/index.go |  22 +-
 .../arduino/libraries/librariesindex/json.go  |   9 +-
 internal/arduino/libraries/loader.go          |  38 ++++
 internal/arduino/libraries/loader_test.go     |  66 ++++++
 internal/cli/feedback/result/rpc.go           |   2 +
 internal/integrationtest/lib/lib_test.go      |  38 ++++
 rpc/cc/arduino/cli/commands/v1/lib.pb.go      | 204 ++++++++++--------
 rpc/cc/arduino/cli/commands/v1/lib.proto      |   3 +
 10 files changed, 292 insertions(+), 118 deletions(-)
 create mode 100644 internal/arduino/libraries/loader_test.go

diff --git a/commands/service_library_search.go b/commands/service_library_search.go
index 39ff4c51c6e..533232e8214 100644
--- a/commands/service_library_search.go
+++ b/commands/service_library_search.go
@@ -21,6 +21,7 @@ import (
 	"strings"
 
 	"github.com/arduino/arduino-cli/commands/internal/instances"
+	"github.com/arduino/arduino-cli/internal/arduino/libraries"
 	"github.com/arduino/arduino-cli/internal/arduino/libraries/librariesindex"
 	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
 	semver "go.bug.st/relaxed-semver"
@@ -116,7 +117,7 @@ func getLibraryParameters(rel *librariesindex.Release) *rpc.LibraryRelease {
 	}
 }
 
-func getLibraryDependenciesParameter(deps []*librariesindex.Dependency) []*rpc.LibraryDependency {
+func getLibraryDependenciesParameter(deps []*libraries.Dependency) []*rpc.LibraryDependency {
 	res := []*rpc.LibraryDependency{}
 	for _, dep := range deps {
 		res = append(res, &rpc.LibraryDependency{
diff --git a/internal/arduino/libraries/libraries.go b/internal/arduino/libraries/libraries.go
index 9ffa1e27eea..d7fa6c0a947 100644
--- a/internal/arduino/libraries/libraries.go
+++ b/internal/arduino/libraries/libraries.go
@@ -25,6 +25,7 @@ import (
 	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
 	paths "github.com/arduino/go-paths-helper"
 	properties "github.com/arduino/go-properties-orderedmap"
+	"go.bug.st/f"
 	semver "go.bug.st/relaxed-semver"
 )
 
@@ -78,6 +79,7 @@ type Library struct {
 	License                string
 	Properties             *properties.Map
 	Examples               paths.PathList
+	Dependencies           []*Dependency
 	declaredHeaders        []string
 	sourceHeaders          []string
 	CompatibleWith         map[string]bool
@@ -142,6 +144,13 @@ func (library *Library) ToRPCLibrary() (*rpc.Library, error) {
 		Examples:          library.Examples.AsStrings(),
 		ProvidesIncludes:  headers,
 		CompatibleWith:    library.CompatibleWith,
+		Dependencies: f.Map(library.Dependencies, func(d *Dependency) *rpc.LibraryDependency {
+			dep := &rpc.LibraryDependency{Name: d.GetName()}
+			if d.GetConstraint() != nil {
+				dep.VersionConstraint = d.GetConstraint().String()
+			}
+			return dep
+		}),
 	}, nil
 }
 
@@ -239,3 +248,19 @@ func (library *Library) SourceHeaders() ([]string, error) {
 	}
 	return library.sourceHeaders, nil
 }
+
+// Dependency is a library dependency
+type Dependency struct {
+	Name              string
+	VersionConstraint semver.Constraint
+}
+
+// GetName returns the name of the dependency
+func (r *Dependency) GetName() string {
+	return r.Name
+}
+
+// GetConstraint returns the version Constraint of the dependecy
+func (r *Dependency) GetConstraint() semver.Constraint {
+	return r.VersionConstraint
+}
diff --git a/internal/arduino/libraries/librariesindex/index.go b/internal/arduino/libraries/librariesindex/index.go
index 033630f910d..04c0ad4a49a 100644
--- a/internal/arduino/libraries/librariesindex/index.go
+++ b/internal/arduino/libraries/librariesindex/index.go
@@ -45,7 +45,7 @@ type Library struct {
 type Release struct {
 	Author           string
 	Version          *semver.Version
-	Dependencies     []*Dependency
+	Dependencies     []*libraries.Dependency
 	Maintainer       string
 	Sentence         string
 	Paragraph        string
@@ -86,26 +86,10 @@ func (r *Release) GetVersion() *semver.Version {
 }
 
 // GetDependencies returns the dependencies of this library.
-func (r *Release) GetDependencies() []*Dependency {
+func (r *Release) GetDependencies() []*libraries.Dependency {
 	return r.Dependencies
 }
 
-// Dependency is a library dependency
-type Dependency struct {
-	Name              string
-	VersionConstraint semver.Constraint
-}
-
-// GetName returns the name of the dependency
-func (r *Dependency) GetName() string {
-	return r.Name
-}
-
-// GetConstraint returns the version Constraint of the dependecy
-func (r *Dependency) GetConstraint() semver.Constraint {
-	return r.VersionConstraint
-}
-
 func (r *Release) String() string {
 	return r.Library.Name + "@" + r.Version.String()
 }
@@ -155,7 +139,7 @@ func (idx *Index) FindLibraryUpdate(lib *libraries.Library) *Release {
 // An optional "override" releases may be passed if we want to exclude the same
 // libraries from the index (for example if we want to keep an installed library).
 func (idx *Index) ResolveDependencies(lib *Release, overrides []*Release) []*Release {
-	resolver := semver.NewResolver[*Release, *Dependency]()
+	resolver := semver.NewResolver[*Release, *libraries.Dependency]()
 
 	overridden := map[string]bool{}
 	for _, override := range overrides {
diff --git a/internal/arduino/libraries/librariesindex/json.go b/internal/arduino/libraries/librariesindex/json.go
index c5c8dd4de90..ee2a53d7016 100644
--- a/internal/arduino/libraries/librariesindex/json.go
+++ b/internal/arduino/libraries/librariesindex/json.go
@@ -18,6 +18,7 @@ package librariesindex
 import (
 	"errors"
 
+	"github.com/arduino/arduino-cli/internal/arduino/libraries"
 	"github.com/arduino/arduino-cli/internal/arduino/resources"
 	"github.com/arduino/arduino-cli/internal/i18n"
 	"github.com/arduino/go-paths-helper"
@@ -124,8 +125,8 @@ func (indexLib *indexRelease) extractReleaseIn(library *Library) {
 	}
 }
 
-func (indexLib *indexRelease) extractDependencies() []*Dependency {
-	res := []*Dependency{}
+func (indexLib *indexRelease) extractDependencies() []*libraries.Dependency {
+	res := []*libraries.Dependency{}
 	if len(indexLib.Dependencies) == 0 {
 		return res
 	}
@@ -135,13 +136,13 @@ func (indexLib *indexRelease) extractDependencies() []*Dependency {
 	return res
 }
 
-func (indexDep *indexDependency) extractDependency() *Dependency {
+func (indexDep *indexDependency) extractDependency() *libraries.Dependency {
 	var constraint semver.Constraint
 	if c, err := semver.ParseConstraint(indexDep.Version); err == nil {
 		constraint = c
 	}
 	// FIXME: else { report invalid constraint }
-	return &Dependency{
+	return &libraries.Dependency{
 		Name:              indexDep.Name,
 		VersionConstraint: constraint,
 	}
diff --git a/internal/arduino/libraries/loader.go b/internal/arduino/libraries/loader.go
index f3d3c896383..1963a08941b 100644
--- a/internal/arduino/libraries/loader.go
+++ b/internal/arduino/libraries/loader.go
@@ -18,6 +18,7 @@ package libraries
 import (
 	"errors"
 	"fmt"
+	"regexp"
 	"strings"
 
 	"github.com/arduino/arduino-cli/internal/arduino/globals"
@@ -130,6 +131,12 @@ func makeNewLibrary(libraryDir *paths.Path, location LibraryLocation) (*Library,
 	library.LDflags = strings.TrimSpace(libProperties.Get("ldflags"))
 	library.Properties = libProperties
 	library.InDevelopment = libraryDir.Join(".development").Exist()
+
+	dependencies, err := extractDependenciesList(libProperties.Get("depends"))
+	if err != nil {
+		return nil, fmt.Errorf("%s: %w", i18n.Tr("scanning library dependencies"), err)
+	}
+	library.Dependencies = dependencies
 	return library, nil
 }
 
@@ -220,3 +227,34 @@ func filterExamplesDirs(dir *paths.Path) bool {
 	}
 	return false
 }
+
+var libraryDependsRegex = regexp.MustCompile(`^([^()]+?) *(?: \((.*)\))?$`)
+
+// extractDependenciesList extracts dependencies from the "depends" field of library.properties
+func extractDependenciesList(depends string) ([]*Dependency, error) {
+	deps := []*Dependency{}
+	depends = strings.TrimSpace(depends)
+	if depends == "" {
+		return deps, nil
+	}
+	for dep := range strings.SplitSeq(depends, ",") {
+		dep = strings.TrimSpace(dep)
+		if dep == "" {
+			return nil, fmt.Errorf("invalid dep: %s", dep)
+		}
+		matches := libraryDependsRegex.FindAllStringSubmatch(dep, -1)
+		if matches == nil {
+			return nil, fmt.Errorf("invalid dep: %s", dep)
+		}
+
+		depConstraint, err := semver.ParseConstraint(matches[0][2])
+		if err != nil {
+			return nil, fmt.Errorf("invalid dep constraint: %s", matches[0][2])
+		}
+		deps = append(deps, &Dependency{
+			Name:              matches[0][1],
+			VersionConstraint: depConstraint,
+		})
+	}
+	return deps, nil
+}
diff --git a/internal/arduino/libraries/loader_test.go b/internal/arduino/libraries/loader_test.go
new file mode 100644
index 00000000000..75f0e164317
--- /dev/null
+++ b/internal/arduino/libraries/loader_test.go
@@ -0,0 +1,66 @@
+// This file is part of arduino-cli.
+//
+// Copyright 2025 ARDUINO SA (http://www.arduino.cc/)
+//
+// This software is released under the GNU General Public License version 3,
+// which covers the main part of arduino-cli.
+// The terms of this license can be found at:
+// https://www.gnu.org/licenses/gpl-3.0.en.html
+//
+// You can be released from the requirements of the above licenses by purchasing
+// a commercial license. Buying such a license is mandatory if you want to
+// modify or otherwise use the software for commercial activities involving the
+// Arduino software without disclosing the source code of your own applications.
+// To purchase a commercial license, send an email to license@arduino.cc.
+
+package libraries
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestDependencyExtract(t *testing.T) {
+	check := func(depDefinition string, name []string, ver []string) {
+		dep, err := extractDependenciesList(depDefinition)
+		require.NoError(t, err)
+		require.NotNil(t, dep)
+		require.Len(t, dep, len(name))
+		for i := range name {
+			require.Equal(t, name[i], dep[i].Name, depDefinition)
+			require.Equal(t, ver[i], dep[i].VersionConstraint.String(), depDefinition)
+		}
+	}
+	invalid := func(depends string) {
+		dep, err := extractDependenciesList(depends)
+		require.Nil(t, dep)
+		require.Error(t, err)
+	}
+	check("ciao", []string{"ciao"}, []string{""})
+	check("MyLib (>1.2.3)", []string{"MyLib"}, []string{">1.2.3"})
+	check("MyLib (>=1.2.3)", []string{"MyLib"}, []string{">=1.2.3"})
+	check("MyLib (<1.2.3)", []string{"MyLib"}, []string{"<1.2.3"})
+	check("MyLib (<=1.2.3)", []string{"MyLib"}, []string{"<=1.2.3"})
+	check("MyLib (!=1.2.3)", []string{"MyLib"}, []string{"!(=1.2.3)"})
+	check("MyLib (>1.0.0 && <2.1.0)", []string{"MyLib"}, []string{"(>1.0.0 && <2.1.0)"})
+	check("MyLib (<1.0.0 || >2.0.0)", []string{"MyLib"}, []string{"(<1.0.0 || >2.0.0)"})
+	check("MyLib ((>0.1.0 && <2.0.0) || >2.1.0)", []string{"MyLib"}, []string{"((>0.1.0 && <2.0.0) || >2.1.0)"})
+	check("MyLib ()", []string{"MyLib"}, []string{""})
+	check("MyLib (>=1.2.3),AnotherLib, YetAnotherLib (=1.0.0)",
+		[]string{"MyLib", "AnotherLib", "YetAnotherLib"},
+		[]string{">=1.2.3", "", "=1.0.0"})
+	invalid("MyLib,,AnotherLib")
+	invalid("(MyLib)")
+	invalid("MyLib(=1.2.3)")
+	check("Arduino Uno WiFi Dev Ed Library, LoRa Node (^2.1.2)",
+		[]string{"Arduino Uno WiFi Dev Ed Library", "LoRa Node"},
+		[]string{"", "^2.1.2"})
+	check("Arduino Uno WiFi Dev Ed Library   ,   LoRa Node    (^2.1.2)",
+		[]string{"Arduino Uno WiFi Dev Ed Library", "LoRa Node"},
+		[]string{"", "^2.1.2"})
+	check("Arduino_OAuth, ArduinoHttpClient (<0.3.0), NonExistentLib",
+		[]string{"Arduino_OAuth", "ArduinoHttpClient", "NonExistentLib"},
+		[]string{"", "<0.3.0", ""})
+	check("", []string{}, []string{})
+}
diff --git a/internal/cli/feedback/result/rpc.go b/internal/cli/feedback/result/rpc.go
index 9798e59584a..4524ae085e2 100644
--- a/internal/cli/feedback/result/rpc.go
+++ b/internal/cli/feedback/result/rpc.go
@@ -234,6 +234,7 @@ type Library struct {
 	ProvidesIncludes  []string                       `json:"provides_includes,omitempty"`
 	CompatibleWith    orderedmap.Map[string, bool]   `json:"compatible_with,omitempty"`
 	InDevelopment     bool                           `json:"in_development,omitempty"`
+	Dependencies      []*LibraryDependency           `json:"dependencies,omitempty"`
 }
 
 func NewLibrary(l *rpc.Library) *Library {
@@ -279,6 +280,7 @@ func NewLibrary(l *rpc.Library) *Library {
 		ProvidesIncludes:  l.GetProvidesIncludes(),
 		CompatibleWith:    libraryCompatibleWithMap,
 		InDevelopment:     l.GetInDevelopment(),
+		Dependencies:      NewLibraryDependencies(l.GetDependencies()),
 	}
 }
 
diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go
index f900a416dad..a95153f9678 100644
--- a/internal/integrationtest/lib/lib_test.go
+++ b/internal/integrationtest/lib/lib_test.go
@@ -1756,3 +1756,41 @@ func TestDependencyResolverNoOverwrite(t *testing.T) {
 	_, _, err = cli.Run("lib", "install", "EncoderTool@2.2.0", "--no-overwrite")
 	require.NoError(t, err)
 }
+
+func TestLibListContainsDependenciesField(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("lib", "update-index")
+	require.NoError(t, err)
+
+	_, _, err = cli.Run("lib", "install", "Arduino_ConnectionHandler@0.6.6")
+	require.NoError(t, err)
+	stdOut, _, err := cli.Run("lib", "list", "--json")
+	require.NoError(t, err)
+	requirejson.Contains(t, stdOut, `{"installed_libraries": [ { "library": {
+			"name":"Arduino_ConnectionHandler",
+			"version": "0.6.6",
+			"dependencies": [
+			  {"name": "Arduino_DebugUtils"},
+			  {"name": "WiFi101"},
+			  {"name": "WiFiNINA"},
+			  {"name": "MKRGSM"},
+			  {"name": "MKRNB"},
+			  {"name": "MKRWAN"}
+			]
+		} } ]}`)
+
+	_, _, err = cli.Run("lib", "install", "DebugLog@0.8.4")
+	require.NoError(t, err)
+	stdOut, _, err = cli.Run("lib", "list", "--json")
+	require.NoError(t, err)
+	requirejson.Contains(t, stdOut, `{"installed_libraries": [ { "library": {
+			"name":"DebugLog",
+			"version": "0.8.4",
+			"dependencies": [
+			  {"name": "ArxContainer", "version_constraint": ">=0.6.0"},
+			  {"name": "ArxTypeTraits"}
+			]
+		} } ]}`)
+}
diff --git a/rpc/cc/arduino/cli/commands/v1/lib.pb.go b/rpc/cc/arduino/cli/commands/v1/lib.pb.go
index 0910be91d8a..488607bb636 100644
--- a/rpc/cc/arduino/cli/commands/v1/lib.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/lib.pb.go
@@ -2000,6 +2000,9 @@ type Library struct {
 	// be treated as read-only. This status is determined by the presence of a
 	// `.development` file in the library root directory.
 	InDevelopment bool `protobuf:"varint,29,opt,name=in_development,json=inDevelopment,proto3" json:"in_development,omitempty"`
+	// The names of the library's dependencies, as defined by the 'depends'
+	// field of library.properties.
+	Dependencies []*LibraryDependency `protobuf:"bytes,30,rep,name=dependencies,proto3" json:"dependencies,omitempty"`
 }
 
 func (x *Library) Reset() {
@@ -2216,6 +2219,13 @@ func (x *Library) GetInDevelopment() bool {
 	return false
 }
 
+func (x *Library) GetDependencies() []*LibraryDependency {
+	if x != nil {
+		return x.Dependencies
+	}
+	return nil
+}
+
 type ZipLibraryInstallRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -3072,7 +3082,7 @@ var file_cc_arduino_cli_commands_v1_lib_proto_rawDesc = []byte{
 	0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
 	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x52,
-	0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0xf8, 0x08, 0x0a, 0x07, 0x4c, 0x69, 0x62,
+	0x07, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0xcb, 0x09, 0x0a, 0x07, 0x4c, 0x69, 0x62,
 	0x72, 0x61, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
 	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68,
 	0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
@@ -3136,94 +3146,99 @@ var file_cc_arduino_cli_commands_v1_lib_proto_rawDesc = []byte{
 	0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x57, 0x69, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e,
 	0x5f, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x1d, 0x20, 0x01,
 	0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e,
-	0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45,
-	0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
-	0x1a, 0x41, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x57, 0x69,
-	0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
+	0x74, 0x12, 0x51, 0x0a, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65,
+	0x73, 0x18, 0x1e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x70, 0x65,
+	0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e,
+	0x63, 0x69, 0x65, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69,
+	0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
 	0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
-	0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
-	0x02, 0x38, 0x01, 0x22, 0x8e, 0x01, 0x0a, 0x18, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61,
+	0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
+	0x02, 0x38, 0x01, 0x1a, 0x41, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c,
+	0x65, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+	0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8e, 0x01, 0x0a, 0x18, 0x5a, 0x69, 0x70, 0x4c, 0x69,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73,
+	0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x76, 0x65,
+	0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x76,
+	0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0xd9, 0x01, 0x0a, 0x19, 0x5a, 0x69, 0x70, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72,
+	0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72,
+	0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72,
+	0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x56, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e,
+	0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65,
+	0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x08,
+	0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
+	0x61, 0x67, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x18, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61,
 	0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
 	0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01,
 	0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
 	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
 	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e,
-	0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72,
-	0x69, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77,
-	0x72, 0x69, 0x74, 0x65, 0x22, 0xd9, 0x01, 0x0a, 0x19, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72,
-	0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72,
-	0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72,
-	0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72,
-	0x65, 0x73, 0x73, 0x12, 0x56, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61,
-	0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c,
-	0x74, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x08, 0x0a, 0x06, 0x52,
-	0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-	0x22, 0x8c, 0x01, 0x0a, 0x18, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49,
-	0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a,
-	0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73,
-	0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12,
-	0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72,
-	0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x03,
-	0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22,
-	0xd9, 0x01, 0x0a, 0x19, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e,
-	0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a,
-	0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00,
-	0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x56,
-	0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c,
-	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x06,
-	0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x08, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
-	0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x61, 0x0a, 0x16, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4c, 0x6f, 0x63,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59,
-	0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f,
-	0x4e, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x4c, 0x49, 0x42, 0x52,
+	0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x03, 0x75, 0x72, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74,
+	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69,
+	0x74, 0x65, 0x22, 0xd9, 0x01, 0x0a, 0x19, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x4f, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
+	0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
+	0x73, 0x48, 0x00, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
+	0x73, 0x12, 0x56, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47,
+	0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48,
+	0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x08, 0x0a, 0x06, 0x52, 0x65, 0x73,
+	0x75, 0x6c, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x61,
+	0x0a, 0x16, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+	0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x4c, 0x49, 0x42, 0x52,
 	0x41, 0x52, 0x59, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x5f, 0x4c, 0x4f, 0x43, 0x41,
-	0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x01, 0x2a, 0x5a,
-	0x0a, 0x13, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x53,
-	0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59,
-	0x5f, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x46,
-	0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x4c, 0x49, 0x42, 0x52, 0x41,
-	0x52, 0x59, 0x5f, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53,
-	0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x2a, 0x46, 0x0a, 0x0d, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x12, 0x17, 0x0a, 0x13, 0x4c,
-	0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x59, 0x4f, 0x55, 0x54, 0x5f, 0x46, 0x4c,
-	0x41, 0x54, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f,
-	0x4c, 0x41, 0x59, 0x4f, 0x55, 0x54, 0x5f, 0x52, 0x45, 0x43, 0x55, 0x52, 0x53, 0x49, 0x56, 0x45,
-	0x10, 0x01, 0x2a, 0xc3, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x6f,
-	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x18, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52,
-	0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54,
-	0x49, 0x4e, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f,
-	0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12,
-	0x25, 0x0a, 0x21, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54,
-	0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x4c, 0x41, 0x54, 0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x42, 0x55, 0x49,
-	0x4c, 0x54, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x30, 0x0a, 0x2c, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52,
-	0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x46, 0x45, 0x52,
-	0x45, 0x4e, 0x43, 0x45, 0x44, 0x5f, 0x50, 0x4c, 0x41, 0x54, 0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x42,
-	0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x4c, 0x49, 0x42, 0x52,
-	0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4d,
-	0x41, 0x4e, 0x41, 0x47, 0x45, 0x44, 0x10, 0x04, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68,
-	0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63,
-	0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x4c,
+	0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x5f, 0x4c,
+	0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10,
+	0x01, 0x2a, 0x5a, 0x0a, 0x13, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72,
+	0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x49, 0x42, 0x52,
+	0x41, 0x52, 0x59, 0x5f, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55,
+	0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x4c, 0x49,
+	0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x53, 0x45, 0x41, 0x52, 0x43, 0x48, 0x5f, 0x53, 0x54, 0x41,
+	0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x2a, 0x46, 0x0a,
+	0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x12, 0x17,
+	0x0a, 0x13, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x41, 0x59, 0x4f, 0x55, 0x54,
+	0x5f, 0x46, 0x4c, 0x41, 0x54, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x4c, 0x49, 0x42, 0x52, 0x41,
+	0x52, 0x59, 0x5f, 0x4c, 0x41, 0x59, 0x4f, 0x55, 0x54, 0x5f, 0x52, 0x45, 0x43, 0x55, 0x52, 0x53,
+	0x49, 0x56, 0x45, 0x10, 0x01, 0x2a, 0xc3, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x18, 0x4c, 0x49, 0x42,
+	0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x55,
+	0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x42, 0x52, 0x41,
+	0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x53, 0x45, 0x52,
+	0x10, 0x01, 0x12, 0x25, 0x0a, 0x21, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f,
+	0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x4c, 0x41, 0x54, 0x46, 0x4f, 0x52, 0x4d, 0x5f,
+	0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x30, 0x0a, 0x2c, 0x4c, 0x49, 0x42,
+	0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45,
+	0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x44, 0x5f, 0x50, 0x4c, 0x41, 0x54, 0x46, 0x4f, 0x52,
+	0x4d, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x49, 0x4e, 0x10, 0x03, 0x12, 0x1e, 0x0a, 0x1a, 0x4c,
+	0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
+	0x55, 0x4e, 0x4d, 0x41, 0x4e, 0x41, 0x47, 0x45, 0x44, 0x10, 0x04, 0x42, 0x48, 0x5a, 0x46, 0x67,
+	0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70,
+	0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69,
+	0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -3323,18 +3338,19 @@ var file_cc_arduino_cli_commands_v1_lib_proto_depIdxs = []int32{
 	3,  // 33: cc.arduino.cli.commands.v1.Library.location:type_name -> cc.arduino.cli.commands.v1.LibraryLocation
 	2,  // 34: cc.arduino.cli.commands.v1.Library.layout:type_name -> cc.arduino.cli.commands.v1.LibraryLayout
 	38, // 35: cc.arduino.cli.commands.v1.Library.compatible_with:type_name -> cc.arduino.cli.commands.v1.Library.CompatibleWithEntry
-	41, // 36: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	43, // 37: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
-	39, // 38: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse.result:type_name -> cc.arduino.cli.commands.v1.ZipLibraryInstallResponse.Result
-	41, // 39: cc.arduino.cli.commands.v1.GitLibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	43, // 40: cc.arduino.cli.commands.v1.GitLibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
-	40, // 41: cc.arduino.cli.commands.v1.GitLibraryInstallResponse.result:type_name -> cc.arduino.cli.commands.v1.GitLibraryInstallResponse.Result
-	20, // 42: cc.arduino.cli.commands.v1.SearchedLibrary.ReleasesEntry.value:type_name -> cc.arduino.cli.commands.v1.LibraryRelease
-	43, // [43:43] is the sub-list for method output_type
-	43, // [43:43] is the sub-list for method input_type
-	43, // [43:43] is the sub-list for extension type_name
-	43, // [43:43] is the sub-list for extension extendee
-	0,  // [0:43] is the sub-list for field type_name
+	21, // 36: cc.arduino.cli.commands.v1.Library.dependencies:type_name -> cc.arduino.cli.commands.v1.LibraryDependency
+	41, // 37: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	43, // 38: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
+	39, // 39: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse.result:type_name -> cc.arduino.cli.commands.v1.ZipLibraryInstallResponse.Result
+	41, // 40: cc.arduino.cli.commands.v1.GitLibraryInstallRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	43, // 41: cc.arduino.cli.commands.v1.GitLibraryInstallResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
+	40, // 42: cc.arduino.cli.commands.v1.GitLibraryInstallResponse.result:type_name -> cc.arduino.cli.commands.v1.GitLibraryInstallResponse.Result
+	20, // 43: cc.arduino.cli.commands.v1.SearchedLibrary.ReleasesEntry.value:type_name -> cc.arduino.cli.commands.v1.LibraryRelease
+	44, // [44:44] is the sub-list for method output_type
+	44, // [44:44] is the sub-list for method input_type
+	44, // [44:44] is the sub-list for extension type_name
+	44, // [44:44] is the sub-list for extension extendee
+	0,  // [0:44] is the sub-list for field type_name
 }
 
 func init() { file_cc_arduino_cli_commands_v1_lib_proto_init() }
diff --git a/rpc/cc/arduino/cli/commands/v1/lib.proto b/rpc/cc/arduino/cli/commands/v1/lib.proto
index 1878b07ec53..8453e904902 100644
--- a/rpc/cc/arduino/cli/commands/v1/lib.proto
+++ b/rpc/cc/arduino/cli/commands/v1/lib.proto
@@ -355,6 +355,9 @@ message Library {
   // be treated as read-only. This status is determined by the presence of a
   // `.development` file in the library root directory.
   bool in_development = 29;
+  // The names of the library's dependencies, as defined by the 'depends'
+  // field of library.properties.
+  repeated LibraryDependency dependencies = 30;
 }
 
 // Represent the library layout.