cc8254f862
Two intertwined mainstream-alignment moves bundled because they share
the migration target (every command's --json path):
1. Drop --dry-run entirely. Survey of comparable API-wrapper CLIs
(gh, aws, stripe, lark): none expose --dry-run. The mainstream that
does (kubectl/git/helm/ansible) operates on declarative manifests
or local state where the preview is materially different from the
executed action. WeKnora's CLI just echoed the same parameters
that would have gone on the wire — the preview added no real
signal over `--help` + reading the call site. Removes:
- root --dry-run persistent flag + cmdutil/dryrun.go
- DryRun fields + EmitDryRun calls in 12 write commands
- format.Envelope.DryRun field
- 8 corresponding *_test.go cases
- --dry-run mention from README.md and CHANGELOG.md
- "dry_run":false from 16 golden envelopes
2. Migrate every --json output to bare data:
- New format.WriteJSON / WriteJSONFiltered helpers
(cli/internal/format/bare.go) share filterArrayItems /
filterObjectKeys / writeJQ with the (still-live for now) envelope
filter helpers.
- Read commands (kb/doc/session list+view, search chunks/docs/
sessions/kb, auth list/status, agent list/view, context list,
doctor) emit bare arrays / objects on stdout.
- Write commands (kb create/edit/delete/pin/empty, doc upload/
upload_recursive/delete, session delete, auth login/logout/
refresh/token, link/unlink, context add/use/remove, agent
invoke, chat, api, version) emit bare result objects. Risk
classification dropped — the resource + exit code already
convey the action.
Per-command shape changes:
list / search → []T (was {ok, data:{items:[…]}})
view → T (was {ok, data:T, _meta:…})
create / edit → T
delete / pin / etc. → {id, …action result…}
doctor → {summary, checks}
api → {status, headers, body}
_meta dropped on the read path:
pagination (page/page_size/total/has_more) — agents iterate with
--all-pages or accept --limit (gh CLI parity);
kb_id / context echo — caller already knows what it asked for.
Acceptance contract goldens regenerated for the new bare shape.
Error envelope on stdout (PrintErrorEnvelope) stays live for now —
the envelope-infra deletion lands in the next commit.
87 lines
3.0 KiB
Go
87 lines
3.0 KiB
Go
package doc
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/Tencent/WeKnora/cli/internal/aiclient"
|
|
"github.com/Tencent/WeKnora/cli/internal/cmdutil"
|
|
"github.com/Tencent/WeKnora/cli/internal/format"
|
|
"github.com/Tencent/WeKnora/cli/internal/iostreams"
|
|
"github.com/Tencent/WeKnora/cli/internal/prompt"
|
|
)
|
|
|
|
// docDeleteFields enumerates the fields surfaced for `--json` discovery on
|
|
// `doc delete`. The result payload is a small {id, deleted} object.
|
|
var docDeleteFields = []string{"id", "deleted"}
|
|
|
|
type DeleteOptions struct {
|
|
Yes bool // sourced from the global -y/--yes persistent flag (see cli/cmd/root.go)
|
|
}
|
|
|
|
// DeleteService is the narrow SDK surface this command depends on.
|
|
// *sdk.Client satisfies it.
|
|
type DeleteService interface {
|
|
DeleteKnowledge(ctx context.Context, id string) error
|
|
}
|
|
|
|
// deleteResult is the typed payload emitted under data on success.
|
|
type deleteResult struct {
|
|
ID string `json:"id"`
|
|
Deleted bool `json:"deleted"`
|
|
}
|
|
|
|
// NewCmdDelete builds `weknora doc delete`. Confirmation routed through
|
|
// the global -y/--yes persistent flag.
|
|
func NewCmdDelete(f *cmdutil.Factory) *cobra.Command {
|
|
opts := &DeleteOptions{}
|
|
cmd := &cobra.Command{
|
|
Use: "delete <id>",
|
|
Short: "Delete a document from a knowledge base",
|
|
Long: `Permanently deletes one document. Prompts for confirmation by default
|
|
when stdout is a TTY and --json is not set; pass -y/--yes (global flag) to skip
|
|
the prompt (required in agent / CI / piped contexts).
|
|
|
|
AI agents: This is a high-risk write. Without -y/--yes the CLI exits 10 and
|
|
returns an envelope describing the missing confirmation. NEVER auto-pass -y
|
|
without the user's explicit go-ahead.`,
|
|
Example: ` weknora doc delete doc_abc # interactive confirm
|
|
weknora doc delete doc_abc -y # no prompt
|
|
weknora doc delete doc_abc -y --json # envelope output`,
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(c *cobra.Command, args []string) error {
|
|
jopts, err := cmdutil.CheckJSONFlags(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
opts.Yes, _ = c.Flags().GetBool("yes")
|
|
cli, err := f.Client()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return runDelete(c.Context(), opts, jopts, cli, f.Prompter(), args[0])
|
|
},
|
|
}
|
|
cmdutil.AddJSONFlags(cmd, docDeleteFields)
|
|
aiclient.SetAgentHelp(cmd, "Destructively deletes one document by id. ALWAYS pass -y/--yes in agent mode (no TTY ⇒ confirm prompt fails). Returns data: {id, deleted:true}.")
|
|
return cmd
|
|
}
|
|
|
|
func runDelete(ctx context.Context, opts *DeleteOptions, jopts *cmdutil.JSONOptions, svc DeleteService, p prompt.Prompter, id string) error {
|
|
if err := cmdutil.ConfirmDestructive(p, opts.Yes, jopts.Enabled(), "document", id); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := svc.DeleteKnowledge(ctx, id); err != nil {
|
|
return cmdutil.WrapHTTP(err, "delete document %s", id)
|
|
}
|
|
|
|
if jopts.Enabled() {
|
|
return format.WriteJSONFiltered(iostreams.IO.Out, deleteResult{ID: id, Deleted: true}, jopts.Fields, jopts.JQ)
|
|
}
|
|
fmt.Fprintf(iostreams.IO.Out, "✓ Deleted document %s\n", id)
|
|
return nil
|
|
}
|