feat(ninja): wire ListTags into popular-tag prompt and list helpers
This commit is contained in:
parent
bb3ddfe1bd
commit
26b262ce73
@ -606,17 +606,23 @@ func promptCategoriesWithDefault(ctx context.Context, cli *orchclient.Client, sc
|
||||
}
|
||||
|
||||
// fetchPopularTagsForPrompt returns a comma-joined "tag (count)" string of the
|
||||
// top tags for the given kind, or "" if the orchestrator lookup fails. The
|
||||
// current implementation always returns "" because core's copy of the
|
||||
// orchestrator proto bindings does not yet expose ListTags; once the bindings
|
||||
// are regenerated this body becomes a best-effort PluginRegistryService.ListTags
|
||||
// call. Callers must already tolerate an empty return.
|
||||
// top tags for the given kind, or "" if the orchestrator lookup fails (e.g.
|
||||
// offline, unauthenticated, RPC error). Callers must tolerate an empty return
|
||||
// and surface their own user-facing fallback message.
|
||||
func fetchPopularTagsForPrompt(ctx context.Context, cli *orchclient.Client, kind string) string {
|
||||
_ = ctx
|
||||
_ = cli
|
||||
_ = kind
|
||||
resp, err := cli.Reg.ListTags(ctx, connect.NewRequest(&v1.ListTagsRequest{Kind: kind, Limit: 20}))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
if len(resp.Msg.Tags) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, 0, len(resp.Msg.Tags))
|
||||
for _, t := range resp.Msg.Tags {
|
||||
parts = append(parts, fmt.Sprintf("%s (%d)", t.Tag, t.Count))
|
||||
}
|
||||
return strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// promptTagsWithDefault prompts the user for free-form tags. Best-effort fetches
|
||||
// the top-20 most-used tags via ListTags(kind) to surface popular suggestions;
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
core "git.dev.alexdunmow.com/block/core/plugin"
|
||||
"git.dev.alexdunmow.com/block/core/cmd/ninja/internal/creds"
|
||||
"git.dev.alexdunmow.com/block/core/cmd/ninja/internal/orchclient"
|
||||
v1 "git.dev.alexdunmow.com/block/core/internal/api/orchestrator/v1"
|
||||
)
|
||||
|
||||
func newPluginTagsCmd() *cobra.Command {
|
||||
@ -152,14 +155,21 @@ func writeLocalModTags(mod *core.ModFile, tags []string) error {
|
||||
}
|
||||
|
||||
// fetchPopularTagsForList returns a single user-facing line listing the most-used
|
||||
// tags for the given kind. The current body returns an unavailable-notice
|
||||
// because core's copy of the orchestrator proto bindings does not yet expose
|
||||
// ListTags; once bindings are regenerated this body becomes a real
|
||||
// PluginRegistryService.ListTags call rendering "Popular: tag (count), ..." or
|
||||
// "Popular tags: (none yet)".
|
||||
// tags for the given kind. Renders "Popular: tag (count), ...", "Popular tags:
|
||||
// (none yet)" when no tags exist on public plugins yet, or an "(unreachable)"
|
||||
// notice if the RPC fails.
|
||||
func fetchPopularTagsForList(cli *orchclient.Client, kind string) string {
|
||||
_ = cli
|
||||
_ = kind
|
||||
return "(popular tags unavailable — orchestrator bindings not yet regenerated)"
|
||||
resp, err := cli.Reg.ListTags(context.Background(), connect.NewRequest(&v1.ListTagsRequest{Kind: kind, Limit: 20}))
|
||||
if err != nil {
|
||||
return "(could not fetch popular tags — orchestrator unreachable)"
|
||||
}
|
||||
if len(resp.Msg.Tags) == 0 {
|
||||
return "Popular tags: (none yet)"
|
||||
}
|
||||
parts := make([]string, len(resp.Msg.Tags))
|
||||
for i, t := range resp.Msg.Tags {
|
||||
parts[i] = fmt.Sprintf("%s (%d)", t.Tag, t.Count)
|
||||
}
|
||||
return "Popular: " + strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
|
||||
@ -71,6 +71,9 @@ const (
|
||||
// PluginRegistryServiceListCategoriesProcedure is the fully-qualified name of the
|
||||
// PluginRegistryService's ListCategories RPC.
|
||||
PluginRegistryServiceListCategoriesProcedure = "/orchestrator.v1.PluginRegistryService/ListCategories"
|
||||
// PluginRegistryServiceListTagsProcedure is the fully-qualified name of the PluginRegistryService's
|
||||
// ListTags RPC.
|
||||
PluginRegistryServiceListTagsProcedure = "/orchestrator.v1.PluginRegistryService/ListTags"
|
||||
// PluginRegistryServiceSubmitForReviewProcedure is the fully-qualified name of the
|
||||
// PluginRegistryService's SubmitForReview RPC.
|
||||
PluginRegistryServiceSubmitForReviewProcedure = "/orchestrator.v1.PluginRegistryService/SubmitForReview"
|
||||
@ -280,6 +283,7 @@ type PluginRegistryServiceClient interface {
|
||||
GetVersion(context.Context, *connect.Request[v1.GetVersionRequest]) (*connect.Response[v1.GetVersionResponse], error)
|
||||
ResolveInstall(context.Context, *connect.Request[v1.ResolveInstallRequest]) (*connect.Response[v1.ResolveInstallResponse], error)
|
||||
ListCategories(context.Context, *connect.Request[v1.ListCategoriesRequest]) (*connect.Response[v1.ListCategoriesResponse], error)
|
||||
ListTags(context.Context, *connect.Request[v1.ListTagsRequest]) (*connect.Response[v1.ListTagsResponse], error)
|
||||
SubmitForReview(context.Context, *connect.Request[v1.SubmitForReviewRequest]) (*connect.Response[v1.SubmitForReviewResponse], error)
|
||||
// Private-plugin RPCs. All require the caller to be a member of the target
|
||||
// account; the server resolves account membership from the bearer token.
|
||||
@ -336,6 +340,12 @@ func NewPluginRegistryServiceClient(httpClient connect.HTTPClient, baseURL strin
|
||||
connect.WithSchema(pluginRegistryServiceMethods.ByName("ListCategories")),
|
||||
connect.WithClientOptions(opts...),
|
||||
),
|
||||
listTags: connect.NewClient[v1.ListTagsRequest, v1.ListTagsResponse](
|
||||
httpClient,
|
||||
baseURL+PluginRegistryServiceListTagsProcedure,
|
||||
connect.WithSchema(pluginRegistryServiceMethods.ByName("ListTags")),
|
||||
connect.WithClientOptions(opts...),
|
||||
),
|
||||
submitForReview: connect.NewClient[v1.SubmitForReviewRequest, v1.SubmitForReviewResponse](
|
||||
httpClient,
|
||||
baseURL+PluginRegistryServiceSubmitForReviewProcedure,
|
||||
@ -377,6 +387,7 @@ type pluginRegistryServiceClient struct {
|
||||
getVersion *connect.Client[v1.GetVersionRequest, v1.GetVersionResponse]
|
||||
resolveInstall *connect.Client[v1.ResolveInstallRequest, v1.ResolveInstallResponse]
|
||||
listCategories *connect.Client[v1.ListCategoriesRequest, v1.ListCategoriesResponse]
|
||||
listTags *connect.Client[v1.ListTagsRequest, v1.ListTagsResponse]
|
||||
submitForReview *connect.Client[v1.SubmitForReviewRequest, v1.SubmitForReviewResponse]
|
||||
listPrivatePlugins *connect.Client[v1.ListPrivatePluginsRequest, v1.ListPrivatePluginsResponse]
|
||||
deletePrivatePlugin *connect.Client[v1.DeletePrivatePluginRequest, v1.DeletePrivatePluginResponse]
|
||||
@ -414,6 +425,11 @@ func (c *pluginRegistryServiceClient) ListCategories(ctx context.Context, req *c
|
||||
return c.listCategories.CallUnary(ctx, req)
|
||||
}
|
||||
|
||||
// ListTags calls orchestrator.v1.PluginRegistryService.ListTags.
|
||||
func (c *pluginRegistryServiceClient) ListTags(ctx context.Context, req *connect.Request[v1.ListTagsRequest]) (*connect.Response[v1.ListTagsResponse], error) {
|
||||
return c.listTags.CallUnary(ctx, req)
|
||||
}
|
||||
|
||||
// SubmitForReview calls orchestrator.v1.PluginRegistryService.SubmitForReview.
|
||||
func (c *pluginRegistryServiceClient) SubmitForReview(ctx context.Context, req *connect.Request[v1.SubmitForReviewRequest]) (*connect.Response[v1.SubmitForReviewResponse], error) {
|
||||
return c.submitForReview.CallUnary(ctx, req)
|
||||
@ -450,6 +466,7 @@ type PluginRegistryServiceHandler interface {
|
||||
GetVersion(context.Context, *connect.Request[v1.GetVersionRequest]) (*connect.Response[v1.GetVersionResponse], error)
|
||||
ResolveInstall(context.Context, *connect.Request[v1.ResolveInstallRequest]) (*connect.Response[v1.ResolveInstallResponse], error)
|
||||
ListCategories(context.Context, *connect.Request[v1.ListCategoriesRequest]) (*connect.Response[v1.ListCategoriesResponse], error)
|
||||
ListTags(context.Context, *connect.Request[v1.ListTagsRequest]) (*connect.Response[v1.ListTagsResponse], error)
|
||||
SubmitForReview(context.Context, *connect.Request[v1.SubmitForReviewRequest]) (*connect.Response[v1.SubmitForReviewResponse], error)
|
||||
// Private-plugin RPCs. All require the caller to be a member of the target
|
||||
// account; the server resolves account membership from the bearer token.
|
||||
@ -502,6 +519,12 @@ func NewPluginRegistryServiceHandler(svc PluginRegistryServiceHandler, opts ...c
|
||||
connect.WithSchema(pluginRegistryServiceMethods.ByName("ListCategories")),
|
||||
connect.WithHandlerOptions(opts...),
|
||||
)
|
||||
pluginRegistryServiceListTagsHandler := connect.NewUnaryHandler(
|
||||
PluginRegistryServiceListTagsProcedure,
|
||||
svc.ListTags,
|
||||
connect.WithSchema(pluginRegistryServiceMethods.ByName("ListTags")),
|
||||
connect.WithHandlerOptions(opts...),
|
||||
)
|
||||
pluginRegistryServiceSubmitForReviewHandler := connect.NewUnaryHandler(
|
||||
PluginRegistryServiceSubmitForReviewProcedure,
|
||||
svc.SubmitForReview,
|
||||
@ -546,6 +569,8 @@ func NewPluginRegistryServiceHandler(svc PluginRegistryServiceHandler, opts ...c
|
||||
pluginRegistryServiceResolveInstallHandler.ServeHTTP(w, r)
|
||||
case PluginRegistryServiceListCategoriesProcedure:
|
||||
pluginRegistryServiceListCategoriesHandler.ServeHTTP(w, r)
|
||||
case PluginRegistryServiceListTagsProcedure:
|
||||
pluginRegistryServiceListTagsHandler.ServeHTTP(w, r)
|
||||
case PluginRegistryServiceSubmitForReviewProcedure:
|
||||
pluginRegistryServiceSubmitForReviewHandler.ServeHTTP(w, r)
|
||||
case PluginRegistryServiceListPrivatePluginsProcedure:
|
||||
@ -589,6 +614,10 @@ func (UnimplementedPluginRegistryServiceHandler) ListCategories(context.Context,
|
||||
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginRegistryService.ListCategories is not implemented"))
|
||||
}
|
||||
|
||||
func (UnimplementedPluginRegistryServiceHandler) ListTags(context.Context, *connect.Request[v1.ListTagsRequest]) (*connect.Response[v1.ListTagsResponse], error) {
|
||||
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginRegistryService.ListTags is not implemented"))
|
||||
}
|
||||
|
||||
func (UnimplementedPluginRegistryServiceHandler) SubmitForReview(context.Context, *connect.Request[v1.SubmitForReviewRequest]) (*connect.Response[v1.SubmitForReviewResponse], error) {
|
||||
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("orchestrator.v1.PluginRegistryService.SubmitForReview is not implemented"))
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2
proto
2
proto
@ -1 +1 @@
|
||||
Subproject commit 6d6445f74ec8152c0458257adf1f406d8ce8e68a
|
||||
Subproject commit cdb50a77f284f2ae124ddd777c688d352e63ed0c
|
||||
Loading…
x
Reference in New Issue
Block a user