Files
Enterprise-Knowledge-Base/cli/cmd/kb/get.go
T
nullkey cf84bf2a38 feat(cli): add whoami / doctor / kb / context commands (PR-7)
5 new leaf commands wired into the root tree:
  whoami      — simplified `auth status` (user_id + tenant_id only)
  doctor      — 4-item self-check (base_url / auth / server_version / cred_storage)
                with --offline / --no-cache flags + skip cascade + summary.all_passed
                防 agent 看到 envelope.ok=true 误判命令整体 success
  kb list     — list KBs (default updated_at desc; 0 KB → "(no knowledge bases)")
                tabwriter 4-col (ID/NAME/DOCS/UPDATED), display-width truncation
  kb get      — show single KB details (KEY: VALUE, suppress empty fields)
  context use — switch default context (writes config.current_context),
                带 levenshtein distance ≤ 2 的 did-you-mean hint

Each command uses the v0.0 narrow Service interface pattern (testable via
fakes), agent.SetAgentHelp for AI-friendly hints, and ClassifyHTTPError
for stable error code mapping.

cmdutil/errors.go: 新增 CodeLocalContextNotFound for `context use`,加入 AllCodes() 注册集.

cli/cmd/root.go: NewRootCmd 改为 exported (acceptance/contract 测试需要),
                 注册 4 个新命令 + 1 parent group; root_test.go 跟随更新.
2026-05-09 12:18:01 +08:00

73 lines
2.2 KiB
Go

package kb
import (
"context"
"fmt"
"github.com/spf13/cobra"
"github.com/Tencent/WeKnora/cli/internal/agent"
"github.com/Tencent/WeKnora/cli/internal/cmdutil"
"github.com/Tencent/WeKnora/cli/internal/format"
"github.com/Tencent/WeKnora/cli/internal/iostreams"
"github.com/Tencent/WeKnora/cli/internal/text"
sdk "github.com/Tencent/WeKnora/client"
)
// GetOptions captures `weknora kb get` flags.
type GetOptions struct {
JSONOut bool
}
// GetService is the narrow SDK surface this command depends on.
type GetService interface {
GetKnowledgeBase(ctx context.Context, id string) (*sdk.KnowledgeBase, error)
}
// NewCmdGet builds `weknora kb get <id>`.
func NewCmdGet(f *cmdutil.Factory) *cobra.Command {
opts := &GetOptions{}
cmd := &cobra.Command{
Use: "get <id>",
Short: "Show a knowledge base by ID",
Args: cobra.ExactArgs(1),
RunE: func(c *cobra.Command, args []string) error {
cli, err := f.Client()
if err != nil {
return err
}
return runGet(c.Context(), opts, cli, args[0])
},
}
cmd.Flags().BoolVar(&opts.JSONOut, "json", false, "Output JSON envelope")
agent.SetAgentHelp(cmd, "Returns details of one knowledge base by ID (config + counts).")
return cmd
}
func runGet(ctx context.Context, opts *GetOptions, svc GetService, id string) error {
kb, err := svc.GetKnowledgeBase(ctx, id)
if err != nil {
return cmdutil.Wrapf(cmdutil.ClassifyHTTPError(err), err, "get knowledge base %q", id)
}
if opts.JSONOut {
return format.WriteEnvelope(iostreams.IO.Out, format.Success(kb, nil))
}
// Human: KEY: VALUE
w := iostreams.IO.Out
fmt.Fprintf(w, "ID: %s\n", kb.ID)
fmt.Fprintf(w, "NAME: %s\n", kb.Name)
if kb.Description != "" {
fmt.Fprintf(w, "DESC: %s\n", kb.Description)
}
fmt.Fprintf(w, "DOCS: %s\n", text.Pluralize(int(kb.KnowledgeCount), "doc"))
fmt.Fprintf(w, "CHUNKS: %s\n", text.Pluralize(int(kb.ChunkCount), "chunk"))
if kb.EmbeddingModelID != "" {
fmt.Fprintf(w, "EMBEDDING: %s\n", kb.EmbeddingModelID)
}
if !kb.UpdatedAt.IsZero() {
// Detail page favors absolute time; FuzzyAgo is reserved for list views.
fmt.Fprintf(w, "UPDATED: %s\n", kb.UpdatedAt.Format("2006-01-02 15:04:05"))
}
return nil
}