Files
WeKnora/cli/README.md
T
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

185 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.
```bash
$ 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](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+.
```bash
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](https://github.com/Tencent/WeKnora/releases)
once v0.2 ships.
---
## 5-minute quickstart
```bash
# 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:
```bash
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:
```bash
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:
```json
{
"ok": true,
"data": { /* command-specific payload */ },
"_meta": { "context": "prod", "kb_id": "a32a63ff-fb36-4874-bcaa-30f48570a694" }
}
```
On error:
```json
{
"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](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
```bash
# 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](../LICENSE).