mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-03-27 17:29:39 +08:00
### What problem does this PR solve? - Add multiple output format to ragflow_cli - Initialize contextengine to Go module - ls datasets/ls files - cat file - search -d dir -q query issue: #13714 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
181 lines
4.5 KiB
Go
181 lines
4.5 KiB
Go
//
|
|
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
package contextengine
|
|
|
|
import (
|
|
stdctx "context"
|
|
)
|
|
|
|
// Provider is the interface for all context providers
|
|
// Each provider handles a specific resource type (datasets, chats, agents, etc.)
|
|
type Provider interface {
|
|
// Name returns the provider name (e.g., "datasets", "chats")
|
|
Name() string
|
|
|
|
// Description returns a human-readable description of the provider
|
|
Description() string
|
|
|
|
// Supports returns true if this provider can handle the given path
|
|
Supports(path string) bool
|
|
|
|
// List lists nodes at the given path
|
|
List(ctx stdctx.Context, path string, opts *ListOptions) (*Result, error)
|
|
|
|
// Search searches for nodes matching the query under the given path
|
|
Search(ctx stdctx.Context, path string, opts *SearchOptions) (*Result, error)
|
|
|
|
// Cat retrieves the content of a file/document at the given path
|
|
Cat(ctx stdctx.Context, path string) ([]byte, error)
|
|
}
|
|
|
|
// BaseProvider provides common functionality for all providers
|
|
type BaseProvider struct {
|
|
name string
|
|
description string
|
|
rootPath string
|
|
}
|
|
|
|
// Name returns the provider name
|
|
func (p *BaseProvider) Name() string {
|
|
return p.name
|
|
}
|
|
|
|
// Description returns the provider description
|
|
func (p *BaseProvider) Description() string {
|
|
return p.description
|
|
}
|
|
|
|
// GetRootPath returns the root path for this provider
|
|
func (p *BaseProvider) GetRootPath() string {
|
|
return p.rootPath
|
|
}
|
|
|
|
// IsRootPath checks if the given path is the root path for this provider
|
|
func (p *BaseProvider) IsRootPath(path string) bool {
|
|
return normalizePath(path) == normalizePath(p.rootPath)
|
|
}
|
|
|
|
// ParsePath parses a path and returns the subpath relative to the provider root
|
|
func (p *BaseProvider) ParsePath(path string) string {
|
|
normalized := normalizePath(path)
|
|
rootNormalized := normalizePath(p.rootPath)
|
|
|
|
if normalized == rootNormalized {
|
|
return ""
|
|
}
|
|
|
|
if len(normalized) > len(rootNormalized) && normalized[:len(rootNormalized)+1] == rootNormalized+"/" {
|
|
return normalized[len(rootNormalized)+1:]
|
|
}
|
|
|
|
return normalized
|
|
}
|
|
|
|
// SplitPath splits a path into components
|
|
func SplitPath(path string) []string {
|
|
path = normalizePath(path)
|
|
if path == "" {
|
|
return []string{}
|
|
}
|
|
parts := splitString(path, '/')
|
|
result := make([]string, 0, len(parts))
|
|
for _, part := range parts {
|
|
if part != "" {
|
|
result = append(result, part)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// normalizePath normalizes a path (removes leading/trailing slashes, handles "." and "..")
|
|
func normalizePath(path string) string {
|
|
path = trimSpace(path)
|
|
if path == "" {
|
|
return ""
|
|
}
|
|
|
|
// Remove leading slashes
|
|
for len(path) > 0 && path[0] == '/' {
|
|
path = path[1:]
|
|
}
|
|
|
|
// Remove trailing slashes
|
|
for len(path) > 0 && path[len(path)-1] == '/' {
|
|
path = path[:len(path)-1]
|
|
}
|
|
|
|
// Handle "." and ".."
|
|
parts := splitString(path, '/')
|
|
result := make([]string, 0, len(parts))
|
|
for _, part := range parts {
|
|
switch part {
|
|
case "", ".":
|
|
// Skip empty and current directory
|
|
continue
|
|
case "..":
|
|
// Go up one directory
|
|
if len(result) > 0 {
|
|
result = result[:len(result)-1]
|
|
}
|
|
default:
|
|
result = append(result, part)
|
|
}
|
|
}
|
|
|
|
return joinStrings(result, "/")
|
|
}
|
|
|
|
// Helper functions to avoid importing strings package in basic operations
|
|
func trimSpace(s string) string {
|
|
start := 0
|
|
end := len(s)
|
|
for start < end && (s[start] == ' ' || s[start] == '\t' || s[start] == '\n' || s[start] == '\r') {
|
|
start++
|
|
}
|
|
for end > start && (s[end-1] == ' ' || s[end-1] == '\t' || s[end-1] == '\n' || s[end-1] == '\r') {
|
|
end--
|
|
}
|
|
return s[start:end]
|
|
}
|
|
|
|
func splitString(s string, sep byte) []string {
|
|
var result []string
|
|
start := 0
|
|
for i := 0; i < len(s); i++ {
|
|
if s[i] == sep {
|
|
result = append(result, s[start:i])
|
|
start = i + 1
|
|
}
|
|
}
|
|
result = append(result, s[start:])
|
|
return result
|
|
}
|
|
|
|
func joinStrings(strs []string, sep string) string {
|
|
if len(strs) == 0 {
|
|
return ""
|
|
}
|
|
if len(strs) == 1 {
|
|
return strs[0]
|
|
}
|
|
result := strs[0]
|
|
for i := 1; i < len(strs); i++ {
|
|
result += sep + strs[i]
|
|
}
|
|
return result
|
|
}
|