d3c03b2f34a596a5530e1b8a2cd768bb3760c8e4
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d3c03b2f34 |
feat(cli)!: v0.10 reliability, agent-UX, and command-surface hardening
A hardening + finalization pass over the agent-first CLI: correctness fixes,
richer machine-readable signals, flag/naming consistency, and a symmetric
config surface. Pre-1.0, so it includes breaking renames.
Correctness:
- agent update: resolve/validate --model/--rerank-model (was storing a bogus
name verbatim, corrupting config.model_id).
- doctor: honor WEKNORA_HOST / WEKNORA_API_KEY (headless path no longer reports
"no host configured").
- session ask / MCP session_ask: text answer was empty on non-TTY — the agent
stream sets Done=true on an intermediate agent_query frame before the answer,
and AgentAccumulator treated the first Done as terminal. Terminate on the
`complete` event (new sdk.AgentResponseTypeComplete), not a per-frame Done.
- batch exit codes: any per-item failure collapses to operation.failed (exit 1),
including `doc upload --recursive` partial failures — a permanent per-file
failure (e.g. a duplicate) no longer surfaces as a retryable exit 7 an agent
would loop on; per-item typed errors stay in the envelope.
Agent-first signals & discovery:
- error.exit_code in the envelope (type + exit_code disambiguate the
input.invalid_argument exit-2-vs-5 split in one JSON read).
- meta.hint on empty content search and on draft doc create; doc wait fails fast
on a never-parsing draft instead of hanging to --timeout.
- retrieval-readiness is visible in the natural flow: kb status / kb check emit
retrieval_ready, and kb create hints the fix when no embedding model is bound
— an unconfigured KB no longer looks silently healthy.
- schema contract completeness: every leaf declares output + >=1 example
(drift-guarded); output strings match the meta actually emitted; chunk list
and search docs now emit meta.total_count (both previously dropped it).
- schema tolerates a quoted multi-word command label; zero-state auth — and
`link` with no profile — point at profile setup / the headless WEKNORA_KB_ID
path instead of looping on `auth login`.
- id-addressed reads tolerate a redundant --kb (doc view/wait, chunk list/view
accept and ignore it, declared in schema) so a carried-over --kb doesn't
exit 2; streaming commands warn that --jq does not apply to an NDJSON stream.
- keep JSON-always as the default; --jq hints spell out the .data path.
Consistency & gating:
- doc create: drop the deprecated --name alias (--title only; pre-1.0 break).
- chunk list --limit aligned to 1..10000; model list --limit/-L with
has_more/total_count; api write-gates -X PUT/PATCH (exit 10); skills install
expands a leading ~.
- docs corrected: search docs / doc list --keyword help is case-insensitive
(server does LOWER LIKE); AGENTS.md risk-action list (no phantom kb.init; add
model.update / kb.config.set) and batch example (failed item carries `error`);
session resume --message id comes from `message list`, not the stream.
- auth/profile ergonomics: env credentials are now first-class — `auth token`
prints the active WEKNORA_API_KEY / WEKNORA_TOKEN, and auth login/logout/refresh
give an env-aware message instead of looping on "run auth login". `auth logout`
clears credentials but keeps the profile registered (host preserved for
re-login); deleting a profile is `profile remove`'s job (clean logout/remove
separation, matching gh / lark).
Config surface (symmetric read/write, in-place model edits):
- kb config now returns a secret-free KBModelConfigView (was {}); `kb config`
reads, new `kb config set` writes; `kb init` removed (misnomer).
- kb create --chat-model: retrieval-ready in one step.
- model update: edit a model in place (id preserved, references survive) —
rotate --api-key-stdin, change base-url / display-name / etc.
- session continue-stream renamed to session resume.
Docs: AGENTS.md is the single wire-contract source; CHANGELOG slimmed; stale
kb-init / continue-stream references removed; skill wire-vocab guard extended.
AGENTS.md / weknora-shared SKILL document retrieval_ready (a KB needs an
embedding model to be searchable), that --jq does not apply to NDJSON
streams, and the env-credential-first auth path; the KB quickstart example
now creates a retrieval-ready KB.
|
||
|
|
6f8b825f5f |
feat(cli): agent-first WeKnora CLI
The `weknora` command-line client for the WeKnora RAG server. Full command surface: kb / doc / chunk / session / message / agent / model / search / chat / auth / profile / link / api / mcp / skills / config / doctor / schema / exit-codes. Agent-first wire contract: JSON envelope by default, typed error codes mapped to stable exit codes, error.retry_argv / retryable / partial-failure status, global --dry-run preview, the exit-10 confirmation protocol for writes, and control/ANSI/Bidi input hygiene. Stateless env-credential auth (WEKNORA_API_KEY / WEKNORA_TOKEN + WEKNORA_HOST) for headless/CI/agent use. A curated read-only MCP tool surface (`mcp serve`) and embedded Agent Skills (`skills install`). Extensive unit + contract-golden tests and CI. |
||
|
|
2ce348d020 |
feat(cli): --format json default + NDJSON event stream + context→profile cascade + help calibration + docs (BREAKING)
D1 — --format default flipped to json regardless of TTY: - v0.6: smart default (text on TTY, json on pipe). - v0.7: always json; TTY only affects indent (compact in pipe). Enum values unchanged (text | json | ndjson). - Typed FormatMode enum replaces untyped string consts. - --format / --jq promoted to persistent root flags so unknown- subcommand paths still reach the typed-envelope guard (per-command registration in v0.6 would have rejected --format on unknown commands as cobra-prose exit 2). - WEKNORA_FORMAT env var added; precedence --format > env > default. Invalid env values silently ignored. D2 — chat / session ask default to NDJSON event-stream: - New cli/internal/output/ndjson_stream.go: InitEvent struct + EmitInit / EmitSDKEvent / WriteNDJSONLine helpers. EmitInit doc encodes the must-be-first-line invariant agents key on. - chat / session ask: --format json AND --format ndjson both emit one JSON event per line (no envelope wrapping). CLI injects exactly one `init` event at stream head carrying session_id + optional kb_id / agent_id / profile. Subsequent events pass through verbatim from the SDK (passthrough discipline per spec §5.1). - --format text keeps the SSE-style live renderer. context → profile full cascade: - Command group: cli/cmd/context/ → cli/cmd/profile/ (git mv; package contextcmd → profilecmd). - Global flag --context → --profile. Factory.ContextOverride → ProfileOverride. WEKNORA_PROFILE env var honored (--profile flag > env > config.CurrentContext). When --profile or WEKNORA_PROFILE references a missing profile, the error is input.invalid_argument with hint "weknora profile list" — not the destructive local.config_corrupt path (which would have told users to delete their config file). - Binding file .weknora/project.yaml field context: → profile: (no backwards-compat alias; re-run weknora link). - profile use JSON fields current_context / previous_context → current_profile / previous_profile. - weknora link JSON field context → profile. - CodeLocalContextNotFound → CodeLocalProfileNotFound (typed code rename). - Envelope top-level profile field populated via globalProfile (set by root PersistentPreRunE from Factory.ActiveProfile). chat / session ask NDJSON init event carries the same profile. - Rationale: "context" collided with LLM context window / RAG context / Go context.Context; mainstream multi-credential CLIs (AWS / Stripe / OpenAI / Anthropic / lark) all use "profile". H2/C1' help calibration: - AgentHelp gains Warnings []string; single SetAgentHelp helper routes on WEKNORA_AGENT_HELP=1 (emits JSON blob including warnings) vs human help (appends "AI agents:" block from same source). Warnings surface as both a structured JSON field and visible help-text addendum without drift. - 9 destructive commands carry warnings: kb / doc / agent / session / chunk delete; profile remove; kb / agent edit; auth logout. - weknora doc wait dedups ids at entry; SIGINT mid-wait returns silently (root signal handler maps to exit 130) instead of being miscategorised as operation.timeout / operation.failed. A4 — docs: - cli/AGENTS.md gains four agent-facing sections: Wire contract for AI agents (stdout / stderr / NDJSON / _notice evolution / SDK contract boundary); Deliberate deviations + mainstream alignments; Pre-1.0 breaking policy; Exit-10 anti-patterns. ERROR_REFERENCE table extended. - cli/README.md adds Agent quick start under Wire contract. - cli/CHANGELOG.md v0.7 section: BREAKING entries with migration notes, Added (WEKNORA_FORMAT / WEKNORA_PROFILE / retry_command / retry_after_seconds / risk / _notice reserved infra / meta.count / meta.has_more / doc fetch / doc create / session ask / doc delete --all / NDJSON init), Changed (docs additions), Deprecated (none — pre-release one-shot breaking). Spec: docs/superpowers/specs/2026-05-20-weknora-cli-v0.7-design.md §3 / §4 / §5 / §6 / §11 |
||
|
|
ad150c7126 |
refactor(cli): envelope sweep — Emit shape, batch ops, MCP StructuredContent, api flag cleanup
Sweep every CLI output path through the v0.7 envelope contract.
FormatOptions.Emit signature changes to (w, data, meta *output.Meta)
so list commands surface meta.count / has_more in the wire envelope.
TTY indent decision plumbed via FormatOptions.TTY (set by
ResolveDefault). --format and --jq promoted to persistent root flags
so unknown-subcommand paths still reach the typed-envelope guard
(per-command registration would have rejected --format on unknown
commands as cobra-prose exit 2). WEKNORA_FORMAT env-var fallback
honored before TTY-resolved default. AddFormatFlag retained for the
per-command --jq field-hint Long-text addendum.
~55 production Emit call sites swept across cli/cmd/**: list paths
populate meta.count; mutation paths pass nil meta; envelope.profile
threaded via globalProfile. Existing JSON-shape tests migrated to
decode the envelope wrapper.
Multi-target batch operations get a unified shape via new helpers:
- output.BatchItem + output.WriteBatchEnvelope (§4.5 per-item ok
pattern; data:[{id, ok, result?|error?}], meta:{count, successes*,
failures*}; Successes/Failures *int so explicit zero survives
omitempty in all-fail case).
- cmdutil.RunBatch + cmdutil.EmitBatch + cmdutil.DeletedAtNow +
cmdutil.ClassifyContextErr collapse the three previously-duplicated
multi-delete pipelines (doc / chunk / session) into one call site
pattern. doc upload --recursive uses the same helpers with a per-
file resultFn. Summary error sets Silent:true so the stderr
envelope path doesn't duplicate the stdout batch detail (exit 1
preserved via Code → ExitCode).
ConfirmDestructive / ConfirmDestructiveBatch extended with action +
retryCmd parameters. Every destructive command (kb delete, kb edit,
doc delete, doc delete --all, agent delete, agent edit, session
delete, chunk delete, auth logout, api -X DELETE) now attaches
error.risk.{level:"destructive", action:"<noun.verb>"} +
error.retry_command on the exit-10 envelope. kb edit / agent edit
also gain the destructive guard wiring (CHANGELOG listed them as
gated but they were silently executing without -y).
MCP tool handlers' 31 error paths return CallToolResult with
IsError + Content text fallback + StructuredContent (envelope.error
shape via cmdutil.ErrorToDetail). Handler Out type changed from
typed *sdk.X to any so the go-sdk auto-marshal doesn't overwrite
StructuredContent with a zero-struct on error returns. Success path
manually populates CallToolResult.StructuredContent via successResult
helper.
weknora api cleanup:
- -d/--data flag removed; body via --input <file> or --input -
(stdin) only. Aligns with gh / curl convention.
- HTTP method whitelist removed; any non-empty method accepted.
- HTTP Retry-After header → cmdutil.Error.RetryAfterSeconds →
envelope.error.retry_after_seconds.
- runAPIPaginated raw-passthrough fallback now wraps response in
envelope so --paginate never emits bare JSON to stdout.
Test sweep: ~60 cmd/** tests migrated to decode envelope shape.
9 wire-contract goldens updated under cli/acceptance/testdata/wire/.
Spec: docs/superpowers/specs/2026-05-20-weknora-cli-v0.7-design.md §4 / §5
|
||
|
|
0e081aec5c |
feat(cli): --log-level + kb/agent status & check + cross-cutting refactor
Operability surface and the bulk of the jopts→fopts migration: * --log-level error|warn|info|debug + WEKNORA_LOG_LEVEL env, wired to the SDK via client.SetDebugLevel. Invalid --log-level returns FlagError (exit 2). * kb status <kb-id> / kb check <kb-id> verb split (1 HTTP vs 1+N for failed_count aggregation). * agent status <agent-id> / agent check <agent-id> verb split (probes kb_scope_all_reachable via 1+N HTTP). * kb create <name> positional (matches agent create). * Positional id help strings namespaced (<kb-id> / <agent-id>). * All auth / context / link / doctor / kb / agent CRUD commands migrated to the FormatOptions API. * root.go Execute(ctx) takes a context so signal-cancellation propagates via cmd.Context() into long-running commands. * Pagination termination uses len(accum) >= total (not page*pageSize) so server-capped page sizes do not truncate aggregations. |
||
|
|
c87e35b34b |
chore(cli): polish + docs sync + pre-PR audit fixes
Code-reuse polish (post-implementation review pass): - Extract text.OneLine(maxWidth, s) helper combining preview-row normalization (newline/CR/tab → space) with text.Truncate's UTF-8-safe truncation. Replaces agent/view.go truncate1Line (ASCII '...' + byte-slice CJK-unsafe) and chunk/list.go singleLine. - Lift cmdutil.OpenInput(path) for the '-' = stdin / else os.Open pattern shared across agent create/edit and the api command. Replaces agent/create.go's private openInput. - Strip inline doc-spec parentheticals from source comments — those belong in commit messages and project docs, not in source where they rot. Pre-PR audit fixes: - doc upload: reject `--metadata` paired with `--from-url` as input.invalid_argument up-front (the URL-ingest request type has no metadata field server-side, so the pair would otherwise silently drop). Long help and CHANGELOG updated to call out the asymmetry. - doc upload (file path): map sdk.ErrDuplicateFile sentinel to resource.already_exists. The sentinel arrives with no "HTTP error <n>:" prefix because the SDK short-circuits on file-hash before reading the HTTP status, so the previous WrapHTTP fall-through misclassified it as network.error with a misleading "check base URL reachability" hint. The --from-url branch already handled ErrDuplicateURL this way; this closes the asymmetry. Caught by e2e re-upload of an already-ingested file; regression test added. - README exit-10 enumeration adds `agent delete` and `chunk delete` (these were missing alongside the v0.5 destructive verbs they were meant to gate). Docs sync: - cli/README.md: command tree now includes the chunk subtree; adds agent / chunk lines to the 5-minute quickstart; adds a "Contributing / Reporting issues" section pointing at the repo's SECURITY.md and AGENTS.md; drops third-party CLI parallels from the surface description. - cli/AGENTS.md: "Command surface design SOP" gains the flag-vs-escape-hatch step. "CRUD command flag canon" renamed to the hard-required-flags pattern with the contrast (TTY-prompts-fill) defined inline rather than via opaque shorthand. - cli/CHANGELOG.md: search docs case-sensitivity shift promoted to its own #### Breaking changes subsection. MCP doc_list filter count corrected from 5 to 6. Drops the bogus go.mod yaml.v3 entry (yaml.v3 was already a dependency on main; v0.5 added zero go.mod lines). Replaces internal-Go identifiers (fuzzyTime, NoOptDefVal) with user-language and drops the § section-symbol jargon. |
||
|
|
59132a56f6 |
feat(cli): agent CRUD + view full config rendering
Adds the three management verbs missing from v0.4's agent subtree (create / edit / delete) and expands v0.4-shipped agent view to render all 34 AgentConfig fields in human output (was 7). Surface: hot-path flags (--model required + 7 optional) + --config-file YAML/JSON tail + --generate-skeleton template emit. Flag > file > server-default precedence for hybrid invocation. - agent create <name> --model <id> [flags] + --from <agent-id> for copy-then-overlay (CopyAgent + UpdateAgent); preserves source config except for fields explicitly overridden - agent edit <id> with --add-kb / --remove-kb idempotent pair, L-2 fetch-then-update, at-least-one-flag validation, --description "" clearing via Flags().Changed(). --config-file fully replaces the AgentConfig baseline (use surgical flags for partial edits; the Long help spells this out + a test pins the contract). - agent delete <id> with ConfirmDestructive + exit-10 protocol; 404 propagates resource.not_found (not idempotent) - agent view: 10 grouped sections (Identity / LLM / KB attachment / Retrieval / Query rewrite / Tools / FAQ / Web search / Multi-turn / Fallback / Templates); --json field discovery includes all config.* keys Shared helper cli/internal/cmdutil/agentconfig.go handles YAML/JSON parsing, flag-overlay-file fusion, and skeleton emission. |