dify/dify-agent-runtime/cmd/dify-agent-cli/knowledge.go

112 lines
4.8 KiB
Go
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.

package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"github.com/langgenius/dify/dify-agent-runtime/internal/agentcli"
"github.com/spf13/cobra"
)
func newKnowledgeCommand() *cobra.Command {
var protocolVersion bool
root := &cobra.Command{Use: "knowledge", Short: "Autonomously inspect read-only KnowledgeFS evidence. All results are JSON.",
RunE: func(cmd *cobra.Command, args []string) error {
if protocolVersion {
_, err := fmt.Fprintln(cmd.OutOrStdout(), "1")
return err
}
return cmd.Help()
}, Args: cobra.NoArgs}
root.Flags().BoolVar(&protocolVersion, "protocol-version", false, "Print the locally supported knowledge protocol version.")
definitions := []struct {
name, description string
flags []string
}{
{"spaces", "List only spaces bound to this Agent and their current availability.", nil},
{"capabilities", "Inspect this space's current capabilities (no model credentials).", []string{"space"}},
{"search", "Retrieve evidence using the space profile; no nested planner or generated answer.", []string{"space", "query", "image-file-id", "limit"}},
{"ls", "List a bounded page of /knowledge entries.", []string{"space", "path", "cursor", "limit"}},
{"tree", "Browse a bounded /knowledge subtree.", []string{"space", "path", "cursor", "limit", "depth"}},
{"find", "Find /knowledge entries whose names contain the query.", []string{"space", "path", "query", "cursor", "limit"}},
{"grep", "Search text inside /knowledge with a bounded server timeout.", []string{"space", "path", "query", "cursor", "limit"}},
{"cat", "Read a page of text. Raw manifests and binary artifacts are not exposed.", []string{"space", "path", "cursor", "limit"}},
{"stat", "Inspect safe metadata for one /knowledge path.", []string{"space", "path"}},
{"diff", "Compare two readable paths without an LLM semantic-diff call.", []string{"space", "old-path", "new-path"}},
{"open", "Open a node ID or validate/reopen a trusted evidence receipt.", []string{"space", "node-id", "receipt"}},
{"images", "List image items and captions from a receipt's immutable document artifact.", []string{"space", "receipt", "cursor", "limit"}},
{"image", "Deliver one bounded image to a vision-capable Agent via the trusted runtime channel.", []string{"space", "receipt", "item-id"}},
}
for _, definition := range definitions {
cmd := &cobra.Command{Use: definition.name, Short: definition.description, Args: cobra.NoArgs}
cmd.Flags().String("command-id", "", "Logical UUID for this command; generated by default. Reusing it will not repeat retrieval.")
cmd.Flags().Bool("json", true, "Emit complete JSON (always enabled).")
for _, flag := range definition.flags {
switch flag {
case "limit":
cmd.Flags().Int(flag, 10, "Maximum returned items/segments (150); retrieval depth still belongs to the space profile.")
case "depth":
cmd.Flags().Int(flag, 2, "Maximum tree depth (14).")
case "path":
cmd.Flags().String(flag, "/knowledge", "Canonical read-only /knowledge path.")
case "image-file-id":
cmd.Flags().StringArray(flag, nil, "Authorized upload UUID or local_file dify-file-ref from inputs; repeat at most four times, never a URL.")
default:
cmd.Flags().String(flag, "", "Knowledge command "+flag+".")
}
}
cmd.RunE = func(cmd *cobra.Command, args []string) error {
env, err := agentcli.ReadEnvironment()
if err != nil {
return err
}
id, _ := cmd.Flags().GetString("command-id")
if id == "" {
id, err = agentcli.NewKnowledgeCommandID()
if err != nil {
return err
}
}
payload := map[string]any{"version": 1, "command": cmd.Name(), "command_id": id}
keys := map[string]string{"space": "space", "query": "query", "path": "path", "cursor": "cursor",
"old-path": "old_path", "new-path": "new_path", "node-id": "node_id", "receipt": "receipt_id", "item-id": "item_id"}
for flag, key := range keys {
if cmd.Flags().Lookup(flag) != nil {
value, _ := cmd.Flags().GetString(flag)
if value != "" {
payload[key] = value
}
}
}
for _, flag := range []string{"limit", "depth"} {
if cmd.Flags().Lookup(flag) != nil {
value, _ := cmd.Flags().GetInt(flag)
payload[flag] = value
}
}
if cmd.Flags().Lookup("image-file-id") != nil {
images, _ := cmd.Flags().GetStringArray("image-file-id")
if len(images) > 4 {
return fmt.Errorf("knowledge search accepts at most four query images")
}
for index, value := range images {
images[index], err = agentcli.KnowledgeQueryImageID(value)
if err != nil {
return err
}
}
if len(images) > 0 {
payload["image_file_ids"] = images
}
}
ctx, stop := signal.NotifyContext(cmd.Context(), os.Interrupt, syscall.SIGTERM)
defer stop()
return agentcli.RunKnowledge(ctx, env, payload, cmd.OutOrStdout())
}
root.AddCommand(cmd)
}
return root
}