Files
Enterprise-Knowledge-Base/cli/README.md
T
nullkey 2ee9741fa1 refactor(cli): finish context→profile cascade + post-review hardening (BREAKING)
Post-review polish on the v0.7 wire / surface contract. Bundles five
follow-ups that landed after the main BREAKING feat commit:

1. Complete context→profile cascade (internal API + YAML schema)

The prior commit renamed only the user-visible surface (commands /
flags / env / project link / envelope field). The internal Go API
and on-disk config schema were still half-renamed — an L-25
self-consistency violation flagged by post-merge review. Closed here:

Internal Go API:
- config.Context           → config.Profile
- config.Config.CurrentContext → CurrentProfile
- config.Config.Contexts       → Profiles
- LoginOptions.Context     → LoginOptions.Profile
- clearContextSecrets()    → clearProfileSecrets()
- saveContextRef()         → saveProfileRef()
- secrets.Store: param name `context` → `profile` (interface +
  FileStore + KeyringStore + MemStore)
- cmdutil.LoadSecret(store, context, key) → LoadSecret(store, profile, key)
- cmdutil.RefreshAndPersist's ctxName → profileName
- Local var `ctx := &config.Profile{...}` → `prof := &config.Profile{...}`
  in auth/login.go to eliminate the visual collision with Go stdlib
  context.Context that motivated the whole rename in the first place.

On-disk config.yaml schema:
- current_context: → current_profile:
- contexts:       → profiles:
- Pre-1.0 break, no compat alias. Users on v0.6 dogfooded configs
  must delete ~/.config/weknora/config.yaml or hand-rename the two
  keys (CHANGELOG migration note added).

Tests / fixtures / golden files:
- factory_test.go YAML fixture + assertion updated.
- acceptance/e2e/e2e_test.go writeContextYAML → writeProfileYAML,
  fixture YAML keys updated.
- acceptance/testdata/wire/doctor.error_network.json golden updated
  ("active context" → "active profile" in hint string).

User-visible prose sweep:
- cmd/mcp/serve.go --help Long: "active context (or --context)" →
  "active profile (or --profile)" — most-visible miss.
- cmd/{kb/list, search/kb, session/list, api/api} Short/Long help.
- cmd/auth/login.go stdout: `(context=%s)` → `(profile=%s)`.
- cmd/auth/logout.go error: `"no current context"` → `"no current profile"`.
- cmd/doctor/doctor.go hint string (also the wire golden above).
- cmd/auth/refresh.go error: `"refresh token missing for context"` →
  `"refresh token missing for profile"`.
- README.md: `## Multi-context` H2 → `## Multi-profile`; code-block
  comment `# current context` → `# current profile`.

Code-comment / docstring sweep across cli/cmd/auth/ and
cli/internal/cmdutil/. Comments referencing Go stdlib context.Context,
the RAG / LLM "context window" concept, and historical CHANGELOG
entries for v0.4 / v0.5 were left alone.

CHANGELOG v0.7 BREAKING entry gains the on-disk-schema bullet under
the existing "context → profile" item.

2. Profile name validation (shell-injection guard)

`envelope.error.retry_command` is a single shell-string field. An
AI agent that exec()s it via `sh -c <retry_command>` was injectable
through a maliciously-named profile:

  weknora auth logout --name 'x; rm -rf ~'
  # would produce: retry_command = "weknora auth logout --name x; rm -rf ~ -y"

`cmd/profile/add.go` already enforced an alphanumeric + `-_.`
allowlist via `validateName`. The `auth login` and `auth logout`
paths bypassed it.

- Moved validation from `cmd/profile/add.go` to
  `cli/internal/cmdutil/profilename.go` as exported
  `ValidateProfileName` (cmdutil is the import-cycle-safe home;
  internal/config can't depend on cmdutil).
- `auth login` runs the validator before any persist call.
- `auth logout` runs the validator on `opts.Name` before
  constructing `retry_command`.
- Unit tests (`profilename_test.go`) cover the allowlist, empty
  rejection, path-traversal, shell metacharacters (`;`, `&`, `|`,
  `$()`, backticks, quotes, whitespace, glob, redirects), and the
  user-facing hint text. The shell-metachar test exists as a
  regression guard.

Wire shape (`retry_command` string → `retry_command_argv []string`)
remains a v0.8 additive change per ROADMAP — this fix removes the
practical exploit path without touching the wire contract.

3. AI-agent terminology disambiguation

"agent" has three referents in this codebase: (a) WeKnora's
server-side Custom Agent resource, (b) the removed `agent invoke`
verb, (c) external LLM/automation consumers. Per project memory
feedback_no_meta_disambiguation_in_docs, the fix is full-term
naming, not "X has N meanings" prose. Surgical changes at section
headers + ambiguous prose:

- AGENTS.md: "Agent decision shortcuts" → "AI agent decision
  shortcuts"; "agent-callable surface" → "AI-agent-callable
  surface".
- README.md: "Designed to be agent-first" → "AI-agent-first";
  "Other agent ergonomics" → "Other AI-agent ergonomics"; "in
  agent contexts" → "in AI-agent contexts"; "for CI / agents" →
  "for CI / AI agents".

Anaphoric "agents" inside paragraphs that already established
"AI agents" was left alone — full substitution everywhere would
have been prose noise without clarity gain.

4. Wire-contract review follow-ups

Real findings from a second-pass review of the v0.7 envelope /
streaming / surface design. Per project memory
feedback_check_in_domain_anchor_first, candidate findings were
first verified against the in-domain peer CLI explicitly cited as
the envelope anchor; two earlier-flagged issues turned out to be
in-pattern and were withdrawn.

Surviving fixes:

- AGENTS.md success-envelope example rewritten. The prior example
  showed `has_more: false` / `_notice: {}` as if they were always
  present, but both fields are `omitempty` and never serialize
  when zero / nil. Replaced with three realistic shapes (list /
  single resource / mutation with no payload) and added a note
  that optional fields are omitted when empty.

- cmd/chat/chat.go Args: MinimumNArgs(1) → ExactArgs(1).
  v0.6 silently joined `weknora chat hello world` into
  `"hello world"`. v0.7 now rejects multi-arg with exit 2,
  matching `weknora session ask`. BREAKING; CHANGELOG entry
  added under v0.7 BREAKING.

- internal/output/envelope.go extracts NewEnvelope(data, meta,
  profile) constructor. The jq-filter path in
  cmdutil.FormatOptions.Emit was manually rebuilding the
  envelope literal alongside the canonical WriteEnvelope path —
  drift risk when fields are added. Single construction point now.

- internal/cmdutil/factory.go adds AddKBFlag(cmd) helper.
  Five files (chat, doc/list, doc/upload, doc/create, doc/fetch)
  had verbatim-identical `cmd.Flags().String("kb", ...)`
  declarations. Centralised so flag name + help text stay
  in sync with Factory.ResolveKB. Docstring reordering + gofmt
  fixup landed in the same edit to keep ResolveKB's own godoc
  attached to its function.

5. OSS-readiness comment / doc sweep

Pre-publication scrub of code, comments, and shipped Markdown to
remove references that only make sense in the development repo:

- AGENTS.md "Deliberate deviations + mainstream alignments"
  section: removed peer-project name-drops from the comparison
  table; rewrote as five flagged design decisions with rationale
  but no specific competitor named. The four rows that previously
  contrasted against a named peer CLI now state WeKnora's choice
  + rationale directly. Section header renamed to "Design
  decisions worth flagging" since it is no longer a
  deviation/alignment matrix.

- CHANGELOG v0.7 BREAKING rationales: three references to a
  named peer CLI removed; the context→profile rationale now
  cites only mainstream multi-credential CLIs by category (AWS /
  Stripe / OpenAI / Anthropic), and the `api -d/--data` removal
  rationale cites only `gh api` / `curl`. `chat` BREAKING entry
  rationale similarly simplified.

- 35 cross-references to design-spec section numbers (§4.1 /
  §4.5 / §5.3 etc.) removed from Go doc comments and test
  comments across 13 files. The referenced spec lives outside
  the shipped tree; readers of the public repo cannot resolve
  them. Each reference replaced with a self-contained semantic
  description (e.g. "the batch envelope" / "AGENTS.md section
  on the success path").

- Mixed-language strings translated to English:
  - Four Go comments: internal/cmdutil/exit.go:213,215,
    internal/cmdutil/errors.go:156,
    internal/output/batch_test.go:90,
    internal/output/envelope_test.go:27.
  - One CHANGELOG section title:
    `v0.7 — Agent-first wire contract + 命令面集中清理` →
    `... + command-surface cleanup`.
  - CJK test fixtures (internal/text/truncate_test.go CJK
    truncation cases, cmd/session/list_test.go Chinese session
    title, acceptance/e2e/e2e_test.go Chinese RAG corpus)
    retained — they are intentional test inputs, not stray prose.

- Makefile help comment: `golangci-lint added in PR-9` →
  `golangci-lint planned`. Internal PR numbering should not
  surface in shipped Makefile prose.

Build green, 28/28 packages, +5 new ValidateProfileName tests.
go vet / gofmt / go mod verify / go mod tidy all clean.

Rationale for the cascade: pre-1.0 is the cheapest moment to close
L-25 self-consistency (L-26). The half-finished internal rename
would have perpetuated the very `context` vs `context.Context`
ambiguity that motivated v0.7's user-visible rename in the first
place.
2026-05-27 10:56:34 +08:00

320 lines
12 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
Command-line client for the WeKnora RAG server. Manage knowledge bases
and documents, run hybrid search, chat with grounded answers, or expose
a curated read-only MCP tool surface for AI agents.
Available Commands:
agent Manage custom agents (CRUD + status/check)
api Make a raw API request to the WeKnora server
auth Manage authentication credentials and profiles
chat Ask a streaming RAG question against a knowledge base
chunk Manage document chunks (RAG retrieval debug)
completion Generate the autocompletion script for the specified shell
profile Manage CLI profiles (named connection targets)
doc Manage documents in a knowledge base
doctor Run 4 self-checks: base URL, auth, server version, credential storage
help Help about any command
kb Manage knowledge bases
link Bind the current directory to a knowledge base
mcp Run weknora as a Model Context Protocol server
search Search across chunks, knowledge bases, documents, or sessions
session Manage chat sessions
unlink Remove the directory's knowledge-base binding
version Show CLI build metadata
```
The wire contract for AI agents is documented [below](#wire-contract).
For contributing to the CLI source, see [AGENTS.md](AGENTS.md).
---
## Install
### From source
Requires Go 1.26+.
```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).
---
## 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 / AI 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, then block until parsing finishes
weknora doc upload notes.md
weknora doc wait doc_abc # exit 0 completed, 1 failed, 124 --timeout, 130 ^C
# 6. Search
weknora search chunks "what is reciprocal rank fusion?"
# 7. Ask the LLM (streams to terminal)
weknora chat "summarise the design doc"
# 8. Manage custom agents and run them (see `weknora agent --help` / `weknora session --help`)
weknora agent list
weknora session ask --agent ag_abc "what's our q4 retention plan?"
# 9. Inspect a document's chunks for RAG retrieval debug
weknora chunk list --doc doc_xyz
# 10. Health & verification verbs
weknora kb status kb_abc # fast snapshot: reachable / counts / processing flag (1 HTTP)
weknora kb check kb_abc # deep verify: also aggregates failed_count via doc list (1+N HTTP)
weknora agent status ag_abc # fast: reachable / model_id
weknora agent check ag_abc # deep: probes every KB in the agent's scope
```
---
### Agent quick start
For AI agents (Claude Code, Cursor, Gemini CLI, etc.) integrating WeKnora:
1. Install: `brew install weknora` or `go install github.com/Tencent/WeKnora/cli@latest`
2. Authenticate (background; extract login URL for the user):
```bash
weknora auth login --host <server-url>
```
3. Register MCP in the host's MCP config:
```json
{"mcpServers": {"weknora": {"command": "weknora", "args": ["mcp", "serve"]}}}
```
4. Read the [wire contract](AGENTS.md#wire-contract-for-ai-agents) before
parsing `--format json` output.
5. Read the [exit-10 anti-patterns](AGENTS.md#exit-10-anti-patterns) before
any destructive call.
---
## Multi-profile
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 profile 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 profile lives in
`~/.config/weknora/config.yaml`.
To remove a profile's stored credentials:
```bash
weknora auth logout # current profile
weknora auth logout --name staging # specific
weknora auth logout --all
```
---
## Wire contract
Designed to be AI-agent-first. Stable across minor releases; breaking
changes announced in the changelog and the corresponding
`weknora --version` bump.
### Streams
- **stdout** is the data channel: bare JSON with `--format json`, or
human-formatted output. Never carries error text.
- **stderr** is logs, progress, warnings, and errors. A non-empty
stderr does **not** mean failure — read the exit code.
### JSON output
Every command supports `--format json`, emitting bare JSON for the
resource it produces — an array for `list` / `search`, a single object
for `view` and write outcomes:
```bash
weknora kb list --format json # [{ "id": "kb_x", "name": "Eng" }, …]
weknora kb view kb_x --format json # { "id": "kb_x", "name": "Eng", … }
weknora kb list --format json --jq '.[] | {id, name}' # project to listed fields
weknora kb list --format json --jq '.[].id' # jq over the bare data
```
`--format ndjson` is also accepted for streaming list commands; each
element is emitted as its own JSON line. `--format json` is the default
regardless of TTY — running `weknora kb list | jq` works without an
explicit flag. Use `--format text` for human-readable output.
### Errors
On failure, stdout stays empty and the typed error goes to stderr in
this format:
```
<code.namespace>: <message>[: <wrapped cause>]
hint: <actionable next-step>
```
Example:
```
auth.unauthenticated: fetch current user: HTTP error 401: ...
hint: run `weknora auth login`
```
The full code registry is in `cli/internal/cmdutil/errors.go`
(`AllCodes()`). Code namespaces: `auth.*` / `resource.*` / `input.*` /
`server.*` / `network.*` / `local.*` / `mcp.*` / `operation.*` (CLI-level
wait/poll outcomes: `operation.timeout`, `operation.failed`, `operation.cancelled`).
### Exit codes
| Code | Meaning | Agent action |
|---|---|---|
| `0` | success | continue |
| `1` | typed `local.*` / `operation.failed` / unclassified | read stderr, decide retry/abort |
| `2` | flag / argument validation error | re-check `weknora <cmd> --help` |
| `3` | `auth.*` (token missing / expired / forbidden) | re-auth, then retry |
| `4` | `resource.not_found` | verify the resource id |
| `5` | `input.*` (other than `confirmation_required`) | adjust args, retry |
| `6` | `server.rate_limited` | back off, retry |
| `7` | `server.*` / `network.*` | transient — retry with backoff |
| `10` | **`input.confirmation_required`** (high-risk write) | ask the human, retry with `-y` only after explicit approval |
| `124` | `operation.timeout` (e.g. `doc wait --timeout` reached) | raise `--timeout` or check the underlying job |
| `130` | `operation.cancelled` (SIGINT / SIGTERM) | stop, do not retry |
**Exit 10** is the wire-level signal for "destructive write needs
explicit confirmation". Pass `-y/--yes` on `kb delete` /
`doc delete` (including `--all --kb=<id>`) / `session delete` /
`profile remove` (on the current profile) / `agent delete` /
`chunk delete` when running headless.
**Never auto-add `-y` without the user's explicit go-ahead** — exit 10
is the guard against unintended writes.
### Other AI-agent ergonomics
- For chat / session ask in AI-agent contexts, pass `--format json` —
streaming tokens to stdout makes JSON parsing impossible.
- `--format json` composes with the global `--profile <name>` for
single-shot profile overrides without disk writes.
- `weknora mcp serve` exposes a curated read-only tool surface over
stdio MCP for any MCP-compatible client.
---
## Advanced operations not exposed as flags
WeKnora CLI exposes top use cases as polished commands; deep
configuration goes through the raw HTTP passthrough. CLI flag coverage
targets common workflows, not 1:1 API parity. Examples of deep
operations that intentionally go through `weknora api`:
- **Tuning a KB's nested config** — chunking strategy, summary model,
multimodal extraction defaults, FAQ thresholds, VLM model. Use
`weknora api PUT /api/v1/knowledge-bases/<id> --input -` with a JSON
body matching the server's `UpdateKnowledgeBaseRequest`. (Note: the
storage provider is set once at create time via
`kb create --storage-provider <name>` and is not updatable.)
- **Per-request `chat` parameters** — multi-KB scope, summary model
override, image attachments, web search toggle. Use `weknora api POST
/api/v1/knowledge-chat/<session-id> --input -`.
- **Per-request `session ask --agent` overrides** — same shape via
`weknora api POST /api/v1/agent-chat/<session-id> --input -`.
- **Operations without a CLI verb** — register / change-password /
OIDC flows, organization / sharing endpoints, tenant management.
`weknora api --help` documents the raw passthrough. Run
`weknora doctor` first to verify auth and base URL.
---
## 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 `--format json` for
machine-readable output, `--offline` to skip network checks.
For per-resource verification, the `status` / `check` verb pair gives
a fast vs deep choice:
| Verb | Cost | Use |
|---|---|---|
| `weknora kb status <kb-id>` | 1 HTTP | live counts / processing flag |
| `weknora kb check <kb-id>` | 1+N HTTP | adds `failed_count` via doc-list page-walk |
| `weknora agent status <agent-id>` | 1 HTTP | reachable / model_id |
| `weknora agent check <agent-id>` | 1+N HTTP | also probes every KB in the agent's scope |
`weknora doc wait <doc-id> [<doc-id>...]` blocks until each document
reaches a terminal `parse_status` (completed or failed). Exit codes:
0 (all completed), 1 (any failed), 124 (`--timeout` reached), 130
(Ctrl-C / SIGTERM). Multi-target is polled concurrently (max 5 in
flight; pipe through `xargs -P` for more).
---
## 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.26, path-filtered to changes under `cli/`.
---
## Contributing / Reporting issues
- **Bugs and feature requests**: file an issue at
[github.com/Tencent/WeKnora/issues](https://github.com/Tencent/WeKnora/issues).
- **Security disclosures**: see the repository-level
[SECURITY.md](../SECURITY.md). Do not file public issues for
security findings.
- **Pull requests**: the developer guide for editing the CLI lives in
[AGENTS.md](AGENTS.md) (build / test / command-surface design SOP /
CRUD flag conventions). Run `go test ./... -race -count=1` and `go vet ./...`
before submitting.
---
## License
MIT — see the repository [LICENSE](../LICENSE).