dispatch() already prefixes errors with 'hyperguild <subcmd>: ', so handlers re-prefixing with their own name produced stuttered output like 'hyperguild brain: brain query: topic required'. Strip the redundant prefixes from the seven affected errors.New / fmt.Errorf calls in brain.go and mode.go. Also fix the LITELLM_BASE_URL usage text — it's optional (empty falls through to airplane tier), not required, matching the README.
72 lines
2.3 KiB
Go
72 lines
2.3 KiB
Go
// Package main implements the hyperguild CLI: tier probe, brain HTTP REST
|
|
// access, and .mcp.json mode bootstrap. See docs/superpowers/specs/.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
)
|
|
|
|
// subcommand is the contract every hyperguild subcommand satisfies.
|
|
// Functions take an explicit context, args (without the subcommand name
|
|
// itself), and explicit IO so tests can exercise full flows without
|
|
// touching os.Stdin / os.Stdout / os.Exit.
|
|
type subcommand func(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) error
|
|
|
|
func subcommands() map[string]subcommand {
|
|
return map[string]subcommand{
|
|
"tier": runTier,
|
|
"brain": runBrain,
|
|
"mode": runMode,
|
|
}
|
|
}
|
|
|
|
const usage = `Usage: hyperguild <subcommand> [options]
|
|
|
|
Subcommands:
|
|
tier Probe Anthropic + LiteLLM, print current operating tier.
|
|
brain query <q> BM25 search the brain (HTTP REST).
|
|
brain write <t> <s>
|
|
Write stdin as a knowledge entry of type <t>, slug <s>.
|
|
mode <name> Bootstrap .mcp.json for a chosen mode:
|
|
cloud | client-local | sovereign
|
|
|
|
Environment:
|
|
BRAIN_URL Brain HTTP REST + MCP base URL.
|
|
Default: http://koala:30330
|
|
ANTHROPIC_PROBE_URL Tier probe URL for the Anthropic API.
|
|
Default: https://api.anthropic.com
|
|
LITELLM_BASE_URL Tier probe URL for the LiteLLM gateway.
|
|
Optional; if empty, falls through to airplane tier.
|
|
`
|
|
|
|
// dispatch routes args to a subcommand and returns the process exit code.
|
|
// Split from main() so tests can drive it without process exit.
|
|
func dispatch(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
|
|
if len(args) == 0 {
|
|
fmt.Fprint(stderr, usage) //nolint:errcheck
|
|
return 2
|
|
}
|
|
switch args[0] {
|
|
case "-h", "--help", "help":
|
|
fmt.Fprint(stdout, usage) //nolint:errcheck
|
|
return 0
|
|
}
|
|
cmd, ok := subcommands()[args[0]]
|
|
if !ok {
|
|
fmt.Fprintf(stderr, "hyperguild: unknown subcommand: %s\n%s", args[0], usage) //nolint:errcheck
|
|
return 2
|
|
}
|
|
if err := cmd(ctx, args[1:], stdin, stdout, stderr); err != nil {
|
|
fmt.Fprintf(stderr, "hyperguild %s: %v\n", args[0], err) //nolint:errcheck
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func main() {
|
|
os.Exit(dispatch(context.Background(), os.Args[1:], os.Stdin, os.Stdout, os.Stderr))
|
|
}
|