mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 19:15:59 +08:00
112 lines
4.8 KiB
Go
112 lines
4.8 KiB
Go
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 (1–50); retrieval depth still belongs to the space profile.")
|
||
case "depth":
|
||
cmd.Flags().Int(flag, 2, "Maximum tree depth (1–4).")
|
||
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
|
||
}
|