// // 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 cli import ( "fmt" "io" ce "ragflow/internal/cli/filesystem" ) // PasswordPromptFunc is a function type for password input type PasswordPromptFunc func(prompt string) (string, error) // CurrentModel holds the current model configuration type CurrentModel struct { Provider string Instance string Model string } // RAGFlowClient handles API interactions with the RAGFlow server type RAGFlowClient struct { HTTPClient *HTTPClient ServerType string // "admin" or "user" PasswordPrompt PasswordPromptFunc // Function for password input OutputFormat OutputFormat // Output format: table, plain, json ContextEngine *ce.Engine // Context Engine for virtual filesystem CurrentModel *CurrentModel // Current model configuration } func NewRAGFlowClient(serverType string) *RAGFlowClient { httpClient := NewHTTPClient() // Set port from configuration file based on server type if serverType == "admin" { httpClient.Port = 9381 } else { httpClient.Port = 9380 } client := &RAGFlowClient{ HTTPClient: httpClient, ServerType: serverType, } // Initialize Context Engine client.initContextEngine() return client } // initContextEngine initializes the Context Engine with all providers func (c *RAGFlowClient) initContextEngine() { engine := ce.NewEngine() // Register providers engine.RegisterProvider(ce.NewDatasetProvider(&httpClientAdapter{c.HTTPClient})) engine.RegisterProvider(ce.NewFileProvider(&httpClientAdapter{c.HTTPClient})) engine.RegisterProvider(ce.NewSkillProvider(&httpClientAdapter{c.HTTPClient})) c.ContextEngine = engine } // httpClientAdapter adapts HTTPClient to ce.HTTPClientInterface type httpClientAdapter struct { client *HTTPClient } func (a *httpClientAdapter) Request(method, path string, authKind string, headers map[string]string, jsonBody map[string]interface{}) (*ce.HTTPResponse, error) { // Auto-detect auth kind based on available tokens // If authKind is "auto" or empty, determine based on token availability if authKind == "auto" || authKind == "" { if a.client.useAPIToken && a.client.APIToken != "" { authKind = "api" } else if a.client.LoginToken != "" { authKind = "web" } else { authKind = "web" // default } } resp, err := a.client.Request(method, path, authKind, headers, jsonBody) if err != nil { return nil, err } return &ce.HTTPResponse{ StatusCode: resp.StatusCode, Body: resp.Body, Headers: resp.Headers, Duration: resp.Duration, }, nil } func (a *httpClientAdapter) UploadMultipart(path string, contentType string, body io.Reader) error { return a.client.UploadMultipart(path, contentType, body) } // ExecuteCommand executes a parsed command // Returns benchmark result map for commands that support it (e.g., ping_server with iterations > 1) func (c *RAGFlowClient) ExecuteCommand(cmd *Command) (ResponseIf, error) { switch c.ServerType { case "admin": // Admin mode: execute command with admin privileges return c.ExecuteAdminCommand(cmd) case "user": // User mode: execute command with user privileges return c.ExecuteUserCommand(cmd) default: return nil, fmt.Errorf("invalid server type: %s", c.ServerType) } } func (c *RAGFlowClient) ExecuteAdminCommand(cmd *Command) (ResponseIf, error) { switch cmd.Type { case "login_user": return nil, c.LoginUser(cmd) case "logout": return c.Logout() case "ping": return c.PingAdmin(cmd) case "benchmark": return c.RunBenchmark(cmd) case "list_users": return c.ListUsers(cmd) case "list_services": return c.ListServices(cmd) case "grant_admin": return c.GrantAdmin(cmd) case "revoke_admin": return c.RevokeAdmin(cmd) case "create_user": return c.CreateUser(cmd) case "activate_user": return c.ActivateUser(cmd) case "alter_user": return c.AlterUserPassword(cmd) case "drop_user": return c.DropUser(cmd) case "show_service": return c.ShowService(cmd) case "show_version": return c.ShowAdminVersion(cmd) case "show_user": return c.ShowUser(cmd) case "list_variables": return c.ListVariables(cmd) case "show_variable": return c.ShowVariable(cmd) case "set_variable": return c.SetVariable(cmd) case "list_user_datasets": return c.ListUserDatasets(cmd) case "list_agents": return c.ListAgents(cmd) case "generate_token": return c.GenerateAdminToken(cmd) case "list_tokens": return c.ListAdminTokens(cmd) case "drop_token": return c.DropAdminToken(cmd) case "list_available_providers": return c.ListAvailableProviders(cmd) case "show_provider": return c.ShowProvider(cmd) case "list_provider_models": return c.ListModels(cmd) case "list_supported_models": return c.ListSupportedModels(cmd) case "list_instance_models": return c.ListInstanceModels(cmd) case "show_model": return c.ShowModel(cmd) case "list_admin_tasks": return c.ListAdminTasks(cmd) // TODO: Implement other commands default: return nil, fmt.Errorf("command '%s' would be executed with API", cmd.Type) } } func (c *RAGFlowClient) ExecuteUserCommand(cmd *Command) (ResponseIf, error) { switch cmd.Type { case "register_user": return c.RegisterUser(cmd) case "login_user": return nil, c.LoginUser(cmd) case "logout": return c.Logout() case "ping": return c.PingServer(cmd) // Configuration commands case "list_configs": return c.ListConfigs(cmd) case "set_log_level": return c.SetLogLevel(cmd) case "benchmark": return c.RunBenchmark(cmd) case "list_datasets": return c.ListDatasets(cmd) case "list_dataset_documents": return c.ListDatasetDocumentUserCommand(cmd) case "search_on_datasets": return c.SearchOnDatasets(cmd) case "create_token": return c.CreateToken(cmd) case "list_tokens": return c.ListTokens(cmd) case "drop_token": return c.DropToken(cmd) case "set_token": return c.SetToken(cmd) case "show_token": return c.ShowToken(cmd) case "unset_token": return c.UnsetToken(cmd) case "show_version": return c.ShowServerVersion(cmd) case "list_available_providers": return c.ListAvailableProviders(cmd) case "show_provider": return c.ShowProvider(cmd) case "list_provider_models": return c.ListModels(cmd) case "list_supported_models": return c.ListSupportedModels(cmd) case "list_instance_models": return c.ListInstanceModels(cmd) case "show_model": return c.ShowModel(cmd) // Provider commands case "add_provider": return c.AddProvider(cmd) case "list_providers": return c.ListProviders(cmd) case "delete_provider": return c.DeleteProvider(cmd) // Provider instance commands case "create_provider_instance": return c.CreateProviderInstance(cmd) case "list_provider_instances": return c.ListProviderInstances(cmd) case "show_provider_instance": return c.ShowProviderInstance(cmd) case "show_instance_balance": return c.ShowInstanceBalance(cmd) case "alter_provider_instance": return c.AlterProviderInstance(cmd) case "drop_provider_instance": return c.DropProviderInstance(cmd) case "drop_instance_model": return c.DropInstanceModel(cmd) case "enable_model": return c.EnableOrDisableModel(cmd, "enable") case "disable_model": return c.EnableOrDisableModel(cmd, "disable") case "add_custom_model": return c.AddCustomModel(cmd) case "chat_to_model": return c.ChatToModel(cmd) case "think_chat_to_model": return c.ChatToModel(cmd) case "embed_user_text": return c.EmbedUserText(cmd) case "rarank_user_document": return c.RerankUserDocument(cmd) case "tts_user_command": return c.TTSUserCommand(cmd) case "asr_user_command": return c.ASRUserCommand(cmd) case "ocr_user_command": return c.OCRUserCommand(cmd) case "parse_file_user_command": return c.ParseFileUserCommand(cmd) case "check_provider_connection": return c.CheckProviderConnection(cmd) case "use_model": return c.UseModel(cmd) case "show_current_model": return c.ShowCurrentModel(cmd) case "set_default_model": return c.SetDefaultModel(cmd) case "reset_default_model": return c.ResetDefaultModel(cmd) case "list_user_default_models": return c.ListDefaultModels(cmd) case "list_tasks_user_command": return c.ListTasksUserCommand(cmd) case "show_task_user_command": return c.ShowTaskUserCommand(cmd) // Dataset, metadata commands case "create_dataset_table": return c.CreateDatasetInDocEngine(cmd) case "drop_dataset_table": return c.DropDatasetInDocEngine(cmd) case "create_metadata_table": return c.CreateMetadataInDocEngine(cmd) case "drop_metadata_table": return c.DropMetadataInDocEngine(cmd) case "insert_dataset_from_file": return c.InsertDatasetFromFile(cmd) case "insert_metadata_from_file": return c.InsertMetadataFromFile(cmd) case "update_chunk": return c.UpdateChunk(cmd) case "get_chunk": return c.GetChunk(cmd) case "set_meta": return c.SetMeta(cmd) case "rm_tags": return c.RmTags(cmd) case "remove_chunks": return c.RemoveChunks(cmd) case "list_metadata": return c.ListMetadata(cmd) // ContextEngine commands case "ce_ls": return c.CEList(cmd) case "ce_cat": return c.CECat(cmd) case "ce_search": return c.CESearch(cmd) // TODO: Implement other commands default: return nil, fmt.Errorf("command '%s' would be executed with API", cmd.Type) } } // ShowCurrentUser shows the current logged-in user information // TODO: Implement showing current user information when API is available func (c *RAGFlowClient) ShowCurrentUser(cmd *Command) (map[string]interface{}, error) { // TODO: Call the appropriate API to get current user information // Currently there is no /admin/user/info or /user/info API available // The /admin/auth API only verifies authorization, does not return user info return nil, fmt.Errorf("command 'SHOW CURRENT USER' is not yet implemented") }