Files
WeKnora/cli/README.md
nullkey e236be1ced fix(cli): correct KB id detection, SSE terminal-frame, and CI test isolation
Three defects surfaced during end-to-end RAG verification — the first two
block real chat usage, the third makes Linux CI flaky:

1. KB id detection — `IsKBID` was checking
   `strings.HasPrefix(s, "kb_")`, but WeKnora generates KB ids as bare
   UUIDs (internal/types/knowledge_base.go: `uuid.New().String()` stored
   in a `varchar(36)` column). Real ids therefore fell through to the
   name-resolution path:

     $ weknora chat ... --kb a32a63ff-fb36-4874-bcaa-30f48570a694
     Error: knowledge base not found: a32a63ff-...

   Switched the discriminator to a UUID regex
   (`^[0-9a-fA-F]{8}-…-[0-9a-fA-F]{12}$`). KB names are arbitrary
   user-supplied strings, so the canonical 8-4-4-4-12 form is an
   unambiguous signal. Mirrors gcloud `--project`'s id-vs-name detection.

2. SSE terminal-frame — the accumulator's `Append` was gating
   finalization on `r.Done`, but the server's KnowledgeQAStream protocol
   emits a leading `agent_query` frame with `done=true` to deliver
   session + message metadata *before* the answer fragments arrive:

     event: message
     data: {"response_type":"agent_query","content":"","done":true,…}

     event: message
     data: {"response_type":"answer","content":"你好","done":false}
     …
     event: message
     data: {"response_type":"complete","content":"","done":true}

   The accumulator therefore flipped to `finished=true` on frame #1 and
   discarded every subsequent answer fragment — `weknora chat … --json`
   returned `answer: ""` even though the LLM reported completion_tokens
   > 0. Fixed: terminate only on `response_type == complete`.
   References still captured opportunistically (they may arrive on a
   dedicated `references` event before the terminator).

3. doctor credential_storage CI isolation — the check probes the real
   OS keyring via `secrets.NewBestEffortStore()`: present on macOS dev
   machines → StatusOK; absent on Linux CI runners without libsecret /
   Gnome-Keyring → StatusWarn ("falling back to file store"). That
   host-dependence was leaking into two test classes that assumed
   StatusOK:

     * cmd/doctor/doctor_test.go: TestDoctor_AllOK and
       TestDoctor_NoConfig_StillRunsCredentialStorage already had a
       withCredStoreFactory seam but didn't use it. Added the pin.

     * acceptance/contract/envelope_test.go: doctor.success_offline
       and doctor.error_network golden cases. The contract test runs
       through the cobra tree in-process and shares cmd/doctor's
       package-level credStoreFactory var — but couldn't reach it
       because the existing seam was unexported.

   Fix: export `doctor.SetCredStoreFactoryForTest(fn) (restore func())`
   for out-of-package tests; acceptance/contract/helpers_test.go adds
   a TestMain that pins the factory to a MemStore-returning closure
   for the whole suite (MemStore is neither *FileStore nor a real
   keyring, so doctor's type-switch hits StatusOK). Production stays
   at secrets.NewBestEffortStore — only the test hook is now reachable
   from across packages.

Test fixtures and goldens that used the old `kb_xxx` literals or
`Done: true` terminators were rewritten to use real UUIDs and
`ResponseType: ResponseTypeComplete` respectively. Per-command --help
text and Long descriptions / Examples now show a UUID rather than
`kb_…` so users see the correct shape from the start. New
TestAccumulator_IgnoresAgentQueryDone pins the SSE terminator bug so
it can't regress.

Tests: 24 cli packages green on macOS dev + Linux/macOS/Windows CI
matrix. Verified end-to-end against a live WeKnora server: `weknora
chat "..." --kb <UUID> --no-stream --json` returns the full LLM answer
in the envelope, live token streaming in TTY mode works, and the
credential_storage check renders deterministic envelopes across hosts.
2026-05-12 13:20:42 +08:00

5.1 KiB
Raw Blame History

weknora — WeKnora CLI

A command-line interface for the WeKnora RAG knowledge-base server. Lets you authenticate, manage knowledge bases and documents, run hybrid search, and ask streaming RAG questions from your terminal or from an AI agent.

$ weknora --help
WeKnora CLI lets you authenticate, browse knowledge bases, and run
hybrid searches against a WeKnora server from your shell or an AI agent.

Available Commands:
  api         Make a raw API request to the WeKnora server
  auth        Manage authentication credentials and contexts
  chat        Ask a streaming RAG question against a knowledge base
  context     Manage CLI contexts (named connection targets)
  doc         Manage documents in a knowledge base
  doctor      Run 4 self-checks: base URL, auth, server version, credential storage
  kb          Manage knowledge bases
  link        Bind the current directory to a knowledge base
  search      Hybrid (vector + keyword) chunk retrieval against a knowledge base
  version     Show CLI build metadata

The command surface mirrors gh CLI's <noun> <verb> convention. See AGENTS.md for the operational contract that AI agents (Claude Code, Cursor, Aider, …) can rely on: envelope schema, exit-code protocol, error-code registry, and per-command guidance.


Install

From source

Requires Go 1.24+.

git clone https://github.com/Tencent/WeKnora.git
cd WeKnora/cli
go build -o weknora .
sudo mv weknora /usr/local/bin/   # or anywhere on $PATH

Pre-built binaries

Pre-built binaries for Linux / macOS / Windows are produced by CI on each release. Grab the latest from the Releases page once v0.2 ships.


5-minute quickstart

# 1. Log in to your WeKnora server (interactive password prompt)
weknora auth login --host https://kb.example.com

# 2. Or pipe an API key from stdin (for CI / agents)
echo "sk-..." | weknora auth login --host https://kb.example.com --with-token

# 3. List knowledge bases
weknora kb list

# 4. Bind this directory to a knowledge base — subsequent commands auto-resolve --kb
weknora link --kb my-knowledge-base

# 5. Upload a document
weknora doc upload notes.md

# 6. Search
weknora search "what is reciprocal rank fusion?"

# 7. Ask the LLM (streams to terminal)
weknora chat "summarise the design doc"

Multi-context

Switch between several WeKnora servers (or several tenants on the same server) without re-logging in:

weknora auth login --host https://prod.example.com    --name prod
weknora auth login --host https://staging.example.com --name staging --with-token < .staging-key
weknora auth list
weknora context use prod

Credentials are persisted to your OS keyring (Keychain on macOS, libsecret on Linux, Wincred on Windows) when available, otherwise to a 0600-mode file under $XDG_CONFIG_HOME/weknora/secrets/. The active context lives in ~/.config/weknora/config.yaml.

To remove a context's stored credentials:

weknora auth logout                  # current context
weknora auth logout --name staging   # specific
weknora auth logout --all

JSON envelope output

Every command supports --json, returning a stable envelope shape:

{
  "ok": true,
  "data": { /* command-specific payload */ },
  "_meta": { "context": "prod", "kb_id": "a32a63ff-fb36-4874-bcaa-30f48570a694" }
}

On error:

{
  "ok": false,
  "error": {
    "code": "auth.unauthenticated",
    "message": "...",
    "hint": "run `weknora auth login`"
  }
}

The full schema, error-code registry, and exit-code protocol (0 / 1 / 2 / 10 / 130) are documented in AGENTS.md.


Agent / scripting integration

Designed to be agent-first:

  • --dry-run previews any write command (kb create/delete, doc upload/delete, api POST/PUT/PATCH/DELETE) without hitting the server, emitting an envelope with risk classification and dry_run: true.
  • -y/--yes skips confirmation prompts for high-risk writes. Without -y on a non-TTY/--json invocation, destructive commands return error.code: input.confirmation_required and exit code 10 so an agent can ask the user before retrying.
  • --json coexists with the global --context <name> for single-shot context override.
  • Set CLAUDECODE or CURSOR_AGENT environment variables to surface per-command "AI agents:" guidance in --help output.

Health check

Run weknora doctor for a 4-status diagnostic (OK / warn / fail / skip) covering base URL reachability, authentication, server-CLI version skew, and credential storage backend. Add --json for machine-readable output, --offline to skip network checks.


Development

# Run unit + contract tests
go test ./...

# Run the real-server e2e suite (requires WEKNORA_E2E_HOST + token env vars)
go test -tags acceptance_e2e ./acceptance/e2e/...

# Static analysis
go vet ./...

CI (.github/workflows/cli.yml) runs build + unit + contract tests on Linux / macOS / Windows × Go 1.24, path-filtered to changes under cli/.


License

MIT — see the repository LICENSE.