9d2e740753
Audited the v0.0~v0.2 21-command surface against gh / kubectl / cargo /
npm / git / docker / flyctl / vercel / supabase / brew. WeKnora was
cherry-picking from multiple heritages, producing an inconsistent feel:
the kb subtree mixed gh verbs (create / delete / list) with a kubectl
verb (get); confirmation flag duplicated --force (docker/kubectl) with
global -y/--yes (gh/vercel/npm); the --agent flag stretched Stripe's
telemetry-tag pattern into a behavior-mode switch that no mainstream
CLI does.
ADR-3 picks gh as the primary north star. Documented deviations remain
for project-link (vercel/cargo), chat (openai-cli), context (kubectl-
light), and doctor (brew/flutter). The decision and its deviations are
documented self-contained in cli/AGENTS.md.
Surface changes:
- kb get → kb view (gh repo view convention); "get" kept as cobra Alias
for v0.0/v0.1 callers — see https://cli.github.com/manual/gh_repo_view.
- kb delete --force / doc delete --force removed in favor of the global
-y/--yes persistent flag (gh repo delete --yes convention). One
mechanism skips destructive prompts; ConfirmDestructive's parameter
renamed `force` → `yes` to match.
- --agent omnibus mode-switch removed. Stripe's DetectAIAgent (the
cited inspiration) only tags User-Agent for telemetry, never flips
behavior; gh / kubectl / aws / docker / flyctl all decline this kind
of flag. The 7-env auto-detect list is reduced to the two entries
Stripe also recognizes (CLAUDECODE, CURSOR_AGENT) — the other five
had no agent-documented source. ApplyAgentSugar / ShouldUseAgentMode
and the dead --no-interactive / --no-progress globals are deleted
entirely.
- DetectAIAgent and SetAgentHelp annotations are kept: env detection
now only triggers AGENT-targeted help text rendering (no behavior
change), matching Stripe's narrower scope.
Tests: 27 cli packages green (acceptance/contract still pins kb get
golden; the alias keeps it valid).
65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
package kb
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/Tencent/WeKnora/cli/internal/cmdutil"
|
|
"github.com/Tencent/WeKnora/cli/internal/iostreams"
|
|
sdk "github.com/Tencent/WeKnora/client"
|
|
)
|
|
|
|
type fakeGetSvc struct {
|
|
kb *sdk.KnowledgeBase
|
|
err error
|
|
}
|
|
|
|
func (f *fakeGetSvc) GetKnowledgeBase(ctx context.Context, id string) (*sdk.KnowledgeBase, error) {
|
|
return f.kb, f.err
|
|
}
|
|
|
|
func TestGet_OK_Human(t *testing.T) {
|
|
out, _ := iostreams.SetForTest(t)
|
|
svc := &fakeGetSvc{kb: &sdk.KnowledgeBase{
|
|
ID: "kb1", Name: "Marketing", KnowledgeCount: 12, ChunkCount: 245,
|
|
}}
|
|
if err := runView(context.Background(), &ViewOptions{}, svc, "kb1"); err != nil {
|
|
t.Fatalf("runGet: %v", err)
|
|
}
|
|
got := out.String()
|
|
for _, want := range []string{"ID:", "kb1", "NAME:", "Marketing", "DOCS:", "12 docs", "CHUNKS:", "245 chunks"} {
|
|
if !strings.Contains(got, want) {
|
|
t.Errorf("missing %q in:\n%s", want, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGet_OK_JSON(t *testing.T) {
|
|
out, _ := iostreams.SetForTest(t)
|
|
svc := &fakeGetSvc{kb: &sdk.KnowledgeBase{ID: "kb1", Name: "Marketing"}}
|
|
if err := runView(context.Background(), &ViewOptions{JSONOut: true}, svc, "kb1"); err != nil {
|
|
t.Fatalf("runGet: %v", err)
|
|
}
|
|
got := out.String()
|
|
if !strings.Contains(got, `"ok":true`) {
|
|
t.Errorf("expected ok:true in %q", got)
|
|
}
|
|
if !strings.Contains(got, `"id":"kb1"`) {
|
|
t.Errorf("expected id field in %q", got)
|
|
}
|
|
}
|
|
|
|
func TestGet_NotFound(t *testing.T) {
|
|
_, _ = iostreams.SetForTest(t)
|
|
svc := &fakeGetSvc{err: errors.New("HTTP error 404: not found")}
|
|
err := runView(context.Background(), &ViewOptions{}, svc, "missing")
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
if !cmdutil.IsNotFound(err) {
|
|
t.Errorf("expected resource.not_found, got %v", err)
|
|
}
|
|
}
|