registry

package
v3.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2026 License: Apache-2.0 Imports: 37 Imported by: 0

Documentation

Index

Constants

View Source
const (
	VerbList    = "list"
	VerbGet     = "get"
	VerbCreate  = "create"
	VerbUpdate  = "update"
	VerbDelete  = "delete"
	VerbExecute = "execute"
)

Core verbs.

View Source
const (
	VerbAuth  = "auth"
	VerbDebug = "debug"
)

Group verbs — top-level commands that own their own subcommands.

View Source
const (
	VerbPush      = "push"
	VerbPull      = "pull"
	VerbConfigure = "configure"
)

Module-approved verbs (AR) — require client-side workflows, approved at framework level.

View Source
const (
	VerbInstall = "install"
)

Package manager verbs — install/uninstall for plugins, agents, mcp, and the CLI itself.

View Source
const (
	VerbMigrate = "migrate"
)

Pair verbs — take a noun pair ("<from>:<to>") instead of a single noun. Always module-approved workflows: no endpoint may back a pair-verb command.

View Source
const (
	VerbVersion = "version"
)

Leaf verbs — standalone commands with no noun and no subcommands. Only one registration per leaf verb is allowed.

Variables

VerbOrder is the canonical display order for verbs in tables and help output.

Functions

func CallEndpoint

func CallEndpoint(ctx *cmdctx.Ctx, ep *spec.EndpointSpec) (any, error)

CallEndpoint executes an API call described by ep using auth and flags from ctx. It returns the raw decoded response. Workflows use this to fetch data and manipulate it before deciding how to render output.

func FieldsToTableColumns

func FieldsToTableColumns(fields []spec.FieldDef) []spec.TableColumn

FieldsToTableColumns converts a []FieldDef to []spec.TableColumn.

func IndexVerbNoun

func IndexVerbNoun(args []string) (verbIdx, nounIdx int)

IndexVerbNoun scans raw CLI args (e.g. os.Args[1:]) and returns the index of the verb token and, if present, the noun token, skipping over any core flags (see coreFlagTable) that appear before either. verbIdx is -1 if args has no positional token at all; nounIdx is -1 if the verb is a leaf command or the noun was simply omitted.

This is purely positional — it does not check that the token found is actually a registered verb or noun, and it has no knowledge of per-command custom flags (flags3), so it can misparse a custom flag placed before the noun as the noun itself.

func MutableFields

func MutableFields(noun *spec.NounDef) []spec.FieldDef

MutableFields returns only the writable fields for a noun (those with mutable_path set).

func PrintFieldTable

func PrintFieldTable(w io.Writer, fields []spec.FieldDef) error

PrintFieldTable writes a human-readable table of available field IDs to w.

func PrintMutableFieldTable

func PrintMutableFieldTable(w io.Writer, fields []spec.FieldDef) error

PrintMutableFieldTable writes a table of settable (path-based) fields to w, including their field_type so users know the --set/--del semantics.

func RenderSingleItem

func RenderSingleItem(ctx *cmdctx.Ctx, ep *spec.EndpointSpec, result any) error

RenderSingleItem renders a single "get"-shaped result according to ep's field/text-formatter configuration. It is the tail end of RunEndpoint's rendering logic, factored out so handlers that resolve an item via custom logic (rather than a direct CallEndpoint) can render it the same way a plain endpoint-backed "get" command would. Unlike RunEndpoint, it does not handle --list-fields — that branch runs before CallEndpoint and only applies to endpoint-backed commands, so callers driving a workflow handler don't get --list-fields support for free.

func RunEndpoint

func RunEndpoint(ctx *cmdctx.Ctx, ep *spec.EndpointSpec) (any, error)

RunEndpoint calls CallEndpoint then renders the result according to ctx.FormatFlags and the endpoint's output spec. Workflows call this as the final output step.

func RunListEndpoint

func RunListEndpoint(ctx *cmdctx.Ctx, ep *spec.EndpointSpec) error

RunListEndpoint calls CallEndpoint then renders the result as a list. It is the dedicated entry point for list verbs and mirrors RunEndpoint's logic.

func RunUIDetailForGet

func RunUIDetailForGet(ctx *cmdctx.Ctx, cs *spec.CommandSpec) error

RunUIDetailForGet opens the detail-only overlay (Case 4): no browse table underneath, rendered at the noun's default text entry, for a get command whose id is already fully specified and whose noun declares ui_commands.

func RunUIPicker

func RunUIPicker(ctx *cmdctx.Ctx, ep *spec.EndpointSpec, titleLine string, preview *PickerPreview) (string, error)

RunUIPicker runs a picker TUI over a list endpoint and returns the selected id. Returns an error if the user cancels without selecting. ctx should already have Verb/Noun/Auth/Level set for the list endpoint. titleLine is the fallback title; preview, when non-nil, enables the live command preview.

func RunUIPickerForGet

func RunUIPickerForGet(ctx *cmdctx.Ctx, cs *spec.CommandSpec) (bool, error)

RunUIPickerForGet intercepts a get command with --ui and, when ctx.Id isn't already fully specified, resolves it interactively following the command's completion spec exactly as tab-completion does.

Any completion_seq steps before the last are resolved via quick select-and-continue pickers (RunUIPicker). The final step — the actual target noun — hands off to the same browse+detail TUI used by "list <noun> --ui" (RunUITableForGet), so picking an id there and printing/viewing it goes through the identical screen as browsing the list directly. That final call fully owns the outcome (print, launch the viewer, or quit with nothing done), so handled=true tells the caller not to do anything further.

handled=false means ctx.Id was already fully specified and the caller should proceed with its normal (non-TUI) get flow.

ID pre-fill rules:

  • If ctx.Id is fully specified (last "/" segment non-empty, or no seq), handled=false.
  • If ctx.Id ends with "/" (trailing slash), the parts before the slash are treated as done.

func RunUITable

func RunUITable(ctx *cmdctx.Ctx, ep *spec.EndpointSpec) error

RunUITable runs the bubbletea paged table TUI for a list endpoint.

func RunUITableForGet

func RunUITableForGet(ctx *cmdctx.Ctx, ep *spec.EndpointSpec, getCs *spec.CommandSpec) error

RunUITableForGet runs the bubbletea paged table TUI for a list endpoint, with the enter-to-drilldown detail overlay driven by getCs (which may be nil to disable it): its text_formatter renders the row detail, and its noun's ui_commands (if any) drive the detail pane's hotkeys. Used both by "list <noun> --ui" and, for a get command's --ui with no id given, as the final step once any completion_seq prefix has been resolved — so picking an id and viewing/printing it go through the exact same screen either way.

Types

type CoreFlag

type CoreFlag struct {
	Name  string
	Short string
	Bool  bool // true if the flag takes no value argument
}

CoreFlag describes a flag known to the CLI's core command-building machinery: either a root-level flag (pkg/rootcmd, AttachGlobalAuthFlags) or a built-in flag wired in per verb/endpoint (bindEndpointCmdFlags, bindWorkflowCmd). Per-command custom flags declared in a spec's flags: block are NOT core flags — those are enumerated per-command via spec.Flag instead, since their names and shapes vary by command.

A core flag's name always has the same shape (bool or value-taking) everywhere it's attached, so this single flat table is enough to recognize any core flag — and tell whether it consumes a value — anywhere in a raw arg list, before the verb or noun is known.

type FlagCompletionFn

type FlagCompletionFn func(ctx *cmdctx.Ctx, args []string, flags *pflag.FlagSet) ([]string, error)

FlagCompletionFn is a custom completion function for a flag. It receives the resolved context, the positional args already typed, and the full flag set so it can read sibling flags (e.g. --stage when completing --step). Returns candidate strings or an error.

type ModuleRegistrar

type ModuleRegistrar interface {
	Register(cs *spec.CommandSpec) error
	// QualifyNoun rewrites nd's ui_commands[].ui_handler_fn entries to their
	// fully-qualified "module:id" form, mirroring what Register does for command
	// fields. Call before RegisterNoun.
	QualifyNoun(nd *spec.NounDef)
	RegisterWorkflow(shortID string, fn WorkflowFn)
	RegisterTextFormatter(shortID string, fn cmdctx.TextFormatterFn)
	RegisterBodyFn(shortID string, fn cmdctx.CreateBodyFn)
	RegisterQueryParamsFn(shortID string, fn cmdctx.QueryParamsFn)
	RegisterFollowFn(shortID string, fn cmdctx.FollowFn)
	RegisterFetchFn(shortID string, fn cmdctx.FetchFn)
	RegisterListTransformFn(shortID string, fn cmdctx.ListTransformFn)
	RegisterItemFn(shortID string, fn cmdctx.ItemFn)
	RegisterFlagCompletionFn(shortID string, fn FlagCompletionFn)
	RegisterFlagResolveFn(shortID string, fn cmdctx.FlagResolveFn)
	RegisterEndpointValidatorFn(shortID string, fn cmdctx.EndpointValidatorFn)
}

ModuleRegistrar is the interface passed to each module's ModuleInit. All IDs passed to RegisterWorkflow and RegisterTextFormatter are short (no colon) and are automatically namespaced as "module:id". Register stamps the module name onto spec.Module and rewrites WorkflowID / TextFormatter to their fully-qualified form.

type PickerPreview

type PickerPreview struct {
	Verb   string // e.g. "get artifact_version"
	Done   string // already-resolved prefix, e.g. "mikereg/" (empty on first step)
	Suffix string // remaining-steps placeholder, e.g. "/…" or "" on last step
}

PickerPreview carries the command-preview fields shown in the picker title.

type Registry

type Registry struct {
	StrictYAML   bool // when true, loadSpecs rejects unknown YAML fields
	IsMainBinary bool // when true, commands owned by external modules are exec'd to their plugin binary
	TelemetryEnv telemetry.Env
	// contains filtered or unexported fields
}

Registry holds all registered CommandSpecs and builds the cobra command tree.

func New

func New() *Registry

func (*Registry) AttachGlobalAuthFlags

func (r *Registry) AttachGlobalAuthFlags(cmd *cobra.Command)

AttachGlobalAuthFlags adds --profile, --org, and --project as persistent flags on cmd (intended to be the root command) so they can appear anywhere in the command line and are inherited by every subcommand.

func (*Registry) BuildCommands

func (r *Registry) BuildCommands() []*cobra.Command

BuildCommands returns the cobra commands for all registered specs.

func (*Registry) CanonicalizeNounArg

func (r *Registry) CanonicalizeNounArg(verb, noun string) string

CanonicalizeNounArg rewrites noun — as it appears in the noun slot: a plain noun, "noun:variant", or, for a NounPair verb like migrate, "<from>:<to>" — so every alias is replaced by its canonical noun name, using the full cross-module alias table (r.nounAliases) built up from every loaded spec.

This exists for plugin dispatch: the host resolves "harness migrate scm_bundle:repo" using code's "repo" alias for "repository" and execs the owning plugin binary with the original spelling — but that plugin process only loads its own module's spec, so it has no "repository" noun to source the "repo" alias from and rejects it. Canonicalizing at the boundary, on the host side where every alias is known, avoids that mismatch.

The ":" suffix means two different things depending on the verb: for a NounPair verb it's a second noun, canonicalized the same as the first half; for every other verb it's a variant selector and is left untouched.

func (*Registry) CanonicalizeNounArgs

func (r *Registry) CanonicalizeNounArgs(args []string) []string

CanonicalizeNounArgs rewrites the noun token in args (if present) via CanonicalizeNounArg, locating the verb/noun positions with IndexVerbNoun.

func (*Registry) CheckFunctions

func (r *Registry) CheckFunctions() error

CheckFunctions verifies that every function reference in all registered specs resolves to a registered function. Returns an error listing all unresolved references.

func (*Registry) CheckNoConflicts

func (r *Registry) CheckNoConflicts(nouns []spec.NounDef, cmds []*spec.CommandSpec) error

CheckNoConflicts reports the first way the given nouns/commands would collide with anything already registered, without mutating the registry. It is the read-only precondition for atomically loading an untrusted (plugin) spec: callers run it before touching the registry so a spec that would partially register — leaking dangling nouns before a later command collision aborts — is rejected whole. Returns nil when the spec can be loaded cleanly.

A plugin can never override a builtin: nouns, noun aliases, and verb+noun command identities are all single-owner, and builtins load first.

func (*Registry) CheckWarnings

func (r *Registry) CheckWarnings() []string

CheckWarnings returns non-fatal spec warnings. Checks list endpoint commands and that every module has a help_text defined.

func (*Registry) FetchItems

func (r *Registry) FetchItems(ctx *cmdctx.Ctx, ep *spec.EndpointSpec, pf cmdctx.PagingFlags) ([]any, error)

FetchItems implements cmdctx.Resolver.

func (*Registry) FormatList

func (r *Registry) FormatList(ctx *cmdctx.Ctx, rows []any, fields []spec.FieldDef, columnIDs []string) error

FormatList renders rows through the standard list formatting pipeline.

func (*Registry) GetAllSpecs

func (r *Registry) GetAllSpecs() []*spec.CommandSpec

GetAllSpecs returns every registered CommandSpec across all modules.

func (*Registry) GetHiddenModule

func (r *Registry) GetHiddenModule(name string) *spec.ModuleMeta

GetHiddenModule returns the recorded hidden-module stub for name, or nil if name isn't a known module_type: hidden module.

func (*Registry) GetModuleMetas

func (r *Registry) GetModuleMetas() []spec.ModuleMeta

GetModuleMetas returns metadata for all loaded modules, sorted by spec.ModuleOrder.

func (*Registry) GetNoun

func (r *Registry) GetNoun(noun string) *spec.NounDef

GetNoun returns the NounDef for a noun, or nil if not registered.

func (*Registry) GetSpec

func (r *Registry) GetSpec(verb, noun string) *spec.CommandSpec

GetSpec returns the CommandSpec for the given verb and noun, or nil if not found. Pass an empty string for noun when looking up leaf verbs (e.g. "version", "ask"). For variant commands, pass the full "noun:variant" string.

func (*Registry) GetSpecsForModule

func (r *Registry) GetSpecsForModule(module string) []*spec.CommandSpec

GetSpecsForModule returns all registered CommandSpecs belonging to the given module.

func (*Registry) GetVerbInfos

func (r *Registry) GetVerbInfos() []spec.VerbInfo

GetVerbInfos returns display metadata for all verbs that have at least one registered command, in canonical VerbOrder.

func (*Registry) HasModule

func (r *Registry) HasModule(name string) bool

HasModule reports whether a module with the given name has been registered.

func (*Registry) Module

func (r *Registry) Module(name string) ModuleRegistrar

Module returns a ModuleRegistrar that namespaces all IDs under name.

func (*Registry) RecordHiddenModule

func (r *Registry) RecordHiddenModule(m spec.ModuleMeta)

RecordHiddenModule records a module declared module_type: hidden, regardless of whether it is currently enabled. This is the only place `install module` can recognize a hidden-but-disabled module by name — such a module is otherwise fully absent from GetModuleMetas.

func (*Registry) RecordPluginOwnedNouns

func (r *Registry) RecordPluginOwnedNouns(module string, nouns []spec.NounDef)

RecordPluginOwnedNouns records module as the owner of nouns (and their aliases), for best-effort "plugin not installed" error messages.

func (*Registry) Register

func (r *Registry) Register(cs *spec.CommandSpec) error

Register adds a spec to the registry. Returns an error if the verb is not in the allowed set, if verb/noun constraints are violated, or if a duplicate exists.

func (*Registry) RegisterBodyFn

func (r *Registry) RegisterBodyFn(id string, fn cmdctx.CreateBodyFn)

RegisterBodyFn registers a fully-qualified body constructor ID.

func (*Registry) RegisterEndpointValidatorFn

func (r *Registry) RegisterEndpointValidatorFn(id string, fn cmdctx.EndpointValidatorFn)

RegisterEndpointValidatorFn registers a fully-qualified endpoint validator ID.

func (*Registry) RegisterFetchFn

func (r *Registry) RegisterFetchFn(id string, fn cmdctx.FetchFn)

RegisterFetchFn registers a fully-qualified fetch function ID.

func (*Registry) RegisterFlagCompletionFn

func (r *Registry) RegisterFlagCompletionFn(id string, fn FlagCompletionFn)

RegisterFlagCompletionFn registers a fully-qualified flag completion function.

func (*Registry) RegisterFlagResolveFn

func (r *Registry) RegisterFlagResolveFn(id string, fn cmdctx.FlagResolveFn)

RegisterFlagResolveFn registers a fully-qualified flag resolver function ID.

func (*Registry) RegisterFollowFn

func (r *Registry) RegisterFollowFn(id string, fn cmdctx.FollowFn)

RegisterFollowFn registers a fully-qualified follow function ID.

func (*Registry) RegisterItemFn

func (r *Registry) RegisterItemFn(id string, fn cmdctx.ItemFn)

RegisterItemFn registers a fully-qualified item resolver function ID.

func (*Registry) RegisterListTransformFn

func (r *Registry) RegisterListTransformFn(id string, fn cmdctx.ListTransformFn)

RegisterListTransformFn registers a fully-qualified list transform function ID.

func (*Registry) RegisterNoun

func (r *Registry) RegisterNoun(nd spec.NounDef) error

RegisterNoun registers a noun definition. Returns an error on duplicate or invalid fields.

func (*Registry) RegisterQueryParamsFn

func (r *Registry) RegisterQueryParamsFn(id string, fn cmdctx.QueryParamsFn)

RegisterQueryParamsFn registers a fully-qualified query params function ID.

func (*Registry) RegisterTextFormatter

func (r *Registry) RegisterTextFormatter(id string, fn cmdctx.TextFormatterFn)

RegisterTextFormatter registers a fully-qualified text formatter ID.

func (*Registry) RegisterWorkflow

func (r *Registry) RegisterWorkflow(id string, fn WorkflowFn)

RegisterWorkflow registers a fully-qualified workflow handler. Panics on duplicate.

func (*Registry) ResolveBodyFn

func (r *Registry) ResolveBodyFn(id string) cmdctx.CreateBodyFn

ResolveBodyFn implements cmdctx.Resolver.

func (*Registry) ResolveCommandFields

func (r *Registry) ResolveCommandFields(cs *spec.CommandSpec) []spec.FieldDef

ResolveCommandFields returns the effective []FieldDef for a CommandSpec: noun fields (respecting fields_noun), filtered by fields_subset, with fields_extra appended.

func (*Registry) ResolveEndpointValidator

func (r *Registry) ResolveEndpointValidator(id string) cmdctx.EndpointValidatorFn

ResolveEndpointValidator implements cmdctx.Resolver.

func (*Registry) ResolveFetchFn

func (r *Registry) ResolveFetchFn(id string) (cmdctx.FetchFn, error)

ResolveFetchFn implements cmdctx.Resolver.

func (*Registry) ResolveFlagResolveFn

func (r *Registry) ResolveFlagResolveFn(id string) cmdctx.FlagResolveFn

ResolveFlagResolveFn implements cmdctx.Resolver.

func (*Registry) ResolveItemFn

func (r *Registry) ResolveItemFn(id string) cmdctx.ItemFn

ResolveItemFn implements cmdctx.Resolver.

func (*Registry) ResolveListTransformFn

func (r *Registry) ResolveListTransformFn(id string) cmdctx.ListTransformFn

ResolveListTransformFn implements cmdctx.Resolver.

func (*Registry) ResolveNounAlias

func (r *Registry) ResolveNounAlias(alias string) string

ResolveNounAlias implements cmdctx.Resolver.

func (*Registry) ResolveQueryParamsFn

func (r *Registry) ResolveQueryParamsFn(id string) cmdctx.QueryParamsFn

ResolveQueryParamsFn implements cmdctx.Resolver.

func (*Registry) ResolveTextFormatter

func (r *Registry) ResolveTextFormatter(id string) cmdctx.TextFormatterFn

ResolveTextFormatter implements cmdctx.Resolver.

func (*Registry) RunEndpoint

func (r *Registry) RunEndpoint(ctx *cmdctx.Ctx, ep *spec.EndpointSpec) (any, error)

RunEndpoint implements cmdctx.Resolver.

func (*Registry) RunUIHandler

func (r *Registry) RunUIHandler(ctx *cmdctx.Ctx, fnID string) error

RunUIHandler implements cmdctx.Resolver.

func (*Registry) SetModuleMeta

func (r *Registry) SetModuleMeta(m spec.ModuleMeta)

SetModuleMeta stores metadata for a module loaded from a spec file.

func (*Registry) SuggestRootCommand

func (r *Registry) SuggestRootCommand(args []string) string

SuggestRootCommand inspects raw CLI args and returns a user-friendly error message when the user likely made one of these mistakes, checked in order from most to least specific:

  1. Migrate transposition: "harness github_repo migrate ..." or "harness repo export ..." instead of "harness migrate ...". Detected whenever "migrate", "import", or "export" appears in the second positional slot — checked before the general transposition case since migrate's noun slot is a "<from>:<to>" pair that can't be reconstructed from a single transposed noun, and "import"/"export" aren't real verbs at all (there's only migrate).

  2. Noun-verb transposition: "harness pr create" instead of "harness create pr". Detected deterministically — the first positional token must be a known noun (or alias), the second a known verb, and the combination must exist in the registry.

  3. Verb typo: "harness creaet pipeline" — the first positional token looks like a mistyped verb (Levenshtein ≤ 2 from a known verb that has registered commands).

  4. A noun owned by a plugin that isn't installed, so it was never registered and cobra can't dispatch it as either a verb or a noun. Checked last since it's the fuzziest signal — a plugin-owned noun name could otherwise coincidentally look like a verb typo (e.g. a hypothetical noun "got" would misreport instead of suggesting "get").

Returns "" when none of the above applies so the caller can fall through to the original error.

type VerbKind

type VerbKind int

VerbKind classifies how a verb behaves in the command tree.

const (
	// VerbKindCore groups nouns under the verb: "harness <verb> <noun>".
	VerbKindCore VerbKind = iota
	// VerbKindLeaf is a standalone command with no noun and no subcommands.
	VerbKindLeaf
	// VerbKindGroup owns its own subcommands (auth, plugin, debug, …).
	VerbKindGroup
)

type VerbSpec

type VerbSpec struct {
	Kind           VerbKind
	ShortDesc      string // used as the Short field on the parent group command
	Gerund         string // present-participle form for UX messages, e.g. "Deleting"
	HideGroup      bool   // hides the parent group command from --help
	SkipSetup      bool   // skips environment setup (EnsureHarnessHome etc); only version
	RequiresId     bool   // a positional <id> arg is mandatory; sets ctx.Id
	AllowsId       bool   // a positional <id> arg is optional; sets ctx.Id when present
	AllowsParentId bool   // an optional positional parentid arg is accepted; sets ctx.ParentId
	// NounPair marks a verb whose noun slot is a "<from>:<to>" pair, exempt from
	// single-module noun ownership. Workflow-backed only; framework adds --from/--to flags.
	NounPair bool
}

VerbSpec captures all properties of a verb in one place.

type WorkflowFn

type WorkflowFn func(ctx *cmdctx.Ctx) error

WorkflowFn is a named workflow handler registered in the Registry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL