repo_description: RAGFlow is a leading open-source Retrieval-Augmented Generation (RAG) engine that fuses cutting-edge RAG with Agent capabilities to create a superior context layer for LLMs
repo_topics: agent agentic agentic-ai agentic-workflow ai context-engineering context-retrieval deep-research deepseek deepseek-r1 document-understanding graphrag harness llm mcp ollama openai openclaw rag retrieval-augmented-generation
code: //
  //  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 (
  	"bufio"
  	"context"
  	"encoding/json"
  	"fmt"
  	"os"
  	ce "ragflow/internal/cli/contextengine"
  	"strings"
  )
  
  // PingServer pings the server to check if it's alive
  // Returns benchmark result map if iterations > 1, otherwise prints status
  func (c *RAGFlowClient) PingServer(cmd *Command) (ResponseIf, error) {
  	// Get iterations from command params (for benchmark)
  	iterations := 1
  	if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
  		iterations = val
  	}
  
  	if iterations > 1 {
  		// Benchmark mode: multiple iterations
  		return c.HTTPClient.RequestWithIterations("GET", "/system/ping", false, "web", nil, nil, iterations)
  	}
  
  	// Single mode
  	resp, err := c.HTTPClient.Request("GET", "/system/ping", false, "web", nil, nil)
  	if err != nil {
  		fmt.Printf("Error: %v\n", err)
  		fmt.Println("Server is down")
  		return nil, err
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to ping: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result SimpleResponse
  	result.Message = string(resp.Body)
  	result.Code = 0
  	return &result, nil
  }
  
  // Show server version to show RAGFlow server version
  // Returns benchmark result map if iterations > 1, otherwise prints status
  func (c *RAGFlowClient) ShowServerVersion(cmd *Command) (ResponseIf, error) {
  	// Get iterations from command params (for benchmark)
  	iterations := 1
  	if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
  		iterations = val
  	}
  
  	if iterations > 1 {
  		// Benchmark mode: multiple iterations
  		return c.HTTPClient.RequestWithIterations("GET", "/system/version", true, "web", nil, nil, iterations)
  	}
  
  	// Single mode
  	resp, err := c.HTTPClient.Request("GET", "/system/version", true, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to show version: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to show version: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result KeyValueResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("show version failed: invalid JSON (%w)", err)
  	}
  	result.Key = "version"
  	result.Duration = resp.Duration
  
  	return &result, nil
  }
  
  func (c *RAGFlowClient) ListConfigs(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in ADMIN mode")
  	}
  	// Get iterations from command params (for benchmark)
  	iterations := 1
  	if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
  		iterations = val
  	}
  
  	if iterations > 1 {
  		// Benchmark mode: multiple iterations
  		return c.HTTPClient.RequestWithIterations("GET", "/system/configs", true, "web", nil, nil, iterations)
  	}
  
  	// Single mode
  	resp, err := c.HTTPClient.Request("GET", "/system/configs", true, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to list configs: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to list configs: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var response CommonDataResponse
  	if err = json.Unmarshal(resp.Body, &response); err != nil {
  		return nil, fmt.Errorf("list configs failed: invalid JSON (%w)", err)
  	}
  
  	var result CommonResponse
  	result.Code = 0
  	result.Data, err = GetConfigs(&response.Data)
  	if err != nil {
  		return nil, fmt.Errorf("failed to list configs: %w", err)
  	}
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  func GetConfigs(config *map[string]interface{}) ([]map[string]interface{}, error) {
  	if config == nil {
  		return nil, fmt.Errorf("config is nil")
  	}
  	result := []map[string]interface{}{}
  	{
  		redisHost := GetHost(config, "Redis", "Host", "Port")
  		result = append(result, map[string]interface{}{
  			"key":   "redis_host",
  			"value": redisHost})
  	}
  	{
  		if docEngine, ok := (*config)["DocEngine"].(map[string]interface{}); ok {
  			engineType, _ := docEngine["Type"].(string)
  			result = append(result, map[string]interface{}{
  				"key":   "doc_engine",
  				"value": engineType})
  			if engineType == "elasticsearch" {
  				esCfg, _ := docEngine["ES"].(map[string]interface{})
  				esHost, _ := esCfg["Hosts"].(string)
  				result = append(result, map[string]interface{}{
  					"key":   "elasticsearch_host",
  					"value": esHost})
  			} else if engineType == "Infinity" {
  				infinityCfg, _ := docEngine["Infinity"].(map[string]interface{})
  				infinityHost, _ := infinityCfg["URI"]
  				result = append(result, map[string]interface{}{
  					"key":   "infinity_host",
  					"value": infinityHost})
  			} else {
  				return nil, fmt.Errorf("unknown doc engine: %s", engineType)
  			}
  		}
  	}
  	{
  		if logConfig, ok := (*config)["Log"].(map[string]interface{}); ok {
  			level, _ := logConfig["Level"].(string)
  			result = append(result, map[string]interface{}{
  				"key":   "log_level",
  				"value": level})
  		}
  	}
  	{
  		if databaseConfig, ok := (*config)["Database"].(map[string]interface{}); ok {
  			driver, _ := databaseConfig["Driver"].(string)
  			result = append(result, map[string]interface{}{
  				"key":   "database",
  				"value": driver})
  			driverAddr, _ := databaseConfig["Host"].(string)
  			driverPort, _ := databaseConfig["Port"].(float64)
  			driverHost := fmt.Sprintf("%s:%0.f", driverAddr, driverPort)
  			result = append(result, map[string]interface{}{
  				"key":   "database_host",
  				"value": driverHost})
  		}
  	}
  	{
  		if language, ok := (*config)["Language"].(map[string]interface{}); ok {
  			result = append(result, map[string]interface{}{
  				"key":   "language",
  				"value": language})
  		}
  	}
  	{
  		if adminConfig, ok := (*config)["Admin"].(map[string]interface{}); ok {
  			adminAddr, _ := adminConfig["Host"].(string)
  			adminPort, _ := adminConfig["Port"].(float64)
  			adminHost := fmt.Sprintf("%s:%0.f", adminAddr, adminPort)
  			result = append(result, map[string]interface{}{
  				"key":   "admin",
  				"value": adminHost})
  		}
  	}
  	{
  		if storageEngineConfig, ok := (*config)["StorageEngine"].(map[string]interface{}); ok {
  			engineType, _ := storageEngineConfig["Type"].(string)
  			result = append(result, map[string]interface{}{
  				"key":   "storage_engine",
  				"value": engineType})
  			if engineType == "minio" {
  				minioCfg, _ := storageEngineConfig["Minio"].(map[string]interface{})
  				miniHost, _ := minioCfg["Host"].(string)
  				result = append(result, map[string]interface{}{
  					"key":   "minio_host",
  					"value": miniHost})
  			} else {
  				return nil, fmt.Errorf("unknown storage engine: %s", engineType)
  			}
  		}
  	}
  	return result, nil
  }
  
  func GetHost(config *map[string]interface{}, serverType, address, port string) string {
  	if config == nil {
  		return ""
  	}
  
  	result := ""
  
  	if redis, ok := (*config)[serverType].(map[string]interface{}); ok {
  		serverAddr, hostOk := redis[address].(string)
  		serverPort, portOk := redis[port].(float64)
  
  		if hostOk && portOk {
  			result = fmt.Sprintf("%s:%.0f", serverAddr, serverPort)
  		}
  	}
  
  	return result
  }
  
  func (c *RAGFlowClient) SetLogLevel(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in ADMIN mode")
  	}
  
  	if logLevel, ok := cmd.Params["level"].(string); ok {
  		payload := map[string]interface{}{
  			"level": logLevel,
  		}
  
  		resp, err := c.HTTPClient.Request("PUT", "/system/log", true, "admin", nil, payload)
  		if err != nil {
  			return nil, fmt.Errorf("failed to change log level: %w", err)
  		}
  
  		if resp.StatusCode != 200 {
  			return nil, fmt.Errorf("failed to register user: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  		}
  
  		var result SimpleResponse
  		if err = json.Unmarshal(resp.Body, &result); err != nil {
  			return nil, fmt.Errorf("change log level failed: invalid JSON (%w)", err)
  		}
  		result.Code = 0
  		result.Duration = resp.Duration
  		return &result, nil
  	}
  
  	return nil, fmt.Errorf("no log level")
  }
  
  func (c *RAGFlowClient) RegisterUser(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in ADMIN mode")
  	}
  
  	// Check for benchmark iterations
  	var ok bool
  	_, ok = cmd.Params["iterations"].(int)
  	if ok {
  		return nil, fmt.Errorf("failed to register user in benchmark statement")
  	}
  
  	var email string
  	email, ok = cmd.Params["user_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("no email")
  	}
  
  	var password string
  	password, ok = cmd.Params["password"].(string)
  	if !ok {
  		return nil, fmt.Errorf("no password")
  	}
  
  	var nickname string
  	nickname, ok = cmd.Params["nickname"].(string)
  	if !ok {
  		return nil, fmt.Errorf("no nickname")
  	}
  
  	payload := map[string]interface{}{
  		"email":    email,
  		"password": password,
  		"nickname": nickname,
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/user/register", false, "admin", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to register user: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to register user: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result RegisterResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("register user failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  	result.Duration = resp.Duration
  
  	return &result, nil
  }
  
  // ListDatasets lists datasets for current user (user mode)
  // Returns (result_map, error) - result_map is non-nil for benchmark mode
  func (c *RAGFlowClient) ListDatasets(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	// Check for benchmark iterations
  	iterations := 1
  	if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
  		iterations = val
  	}
  
  	// Determine auth kind based on whether API token is being used
  	if c.HTTPClient.LoginToken == "" && !c.HTTPClient.useAPIToken {
  		return nil, fmt.Errorf("no authorization")
  	}
  
  	authKind := "web"
  	if c.HTTPClient.useAPIToken {
  		authKind = "api"
  	}
  
  	if c.HTTPClient.LoginToken != "" {
  		authKind = "web"
  	}
  
  	if iterations > 1 {
  		// Benchmark mode - return raw result for benchmark stats
  		return c.HTTPClient.RequestWithIterations("GET", "/datasets", true, authKind, nil, nil, iterations)
  	}
  
  	// Normal mode
  	resp, err := c.HTTPClient.Request("GET", "/datasets", true, authKind, nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to list datasets: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to list datasets: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result CommonResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("list users failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  	result.Duration = resp.Duration
  
  	return &result, nil
  }
  
  // getDatasetID gets dataset ID by name
  func (c *RAGFlowClient) getDatasetID(datasetName string) (string, error) {
  	resp, err := c.HTTPClient.Request("GET", "/datasets", true, "web", nil, nil)
  	if err != nil {
  		return "", fmt.Errorf("failed to list datasets: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return "", fmt.Errorf("failed to list datasets: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return "", fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok || code != 0 {
  		msg, _ := resJSON["message"].(string)
  		return "", fmt.Errorf("failed to list datasets: %s", msg)
  	}
  
  	data, ok := resJSON["data"].([]interface{})
  	if !ok {
  		return "", fmt.Errorf("invalid response format")
  	}
  
  	for _, kb := range data {
  		if kbMap, ok := kb.(map[string]interface{}); ok {
  			if name, _ := kbMap["name"].(string); name == datasetName {
  				if id, _ := kbMap["id"].(string); id != "" {
  					return id, nil
  				}
  			}
  		}
  	}
  
  	return "", fmt.Errorf("dataset '%s' not found", datasetName)
  }
  
  // formatEmptyArray converts empty arrays to "[]" string
  func formatEmptyArray(v interface{}) string {
  	if v == nil {
  		return "[]"
  	}
  	switch val := v.(type) {
  	case []interface{}:
  		if len(val) == 0 {
  			return "[]"
  		}
  	case []string:
  		if len(val) == 0 {
  			return "[]"
  		}
  	case []int:
  		if len(val) == 0 {
  			return "[]"
  		}
  	}
  	return fmt.Sprintf("%v", v)
  }
  
  // SearchOnDatasets searches for chunks in specified datasets
  // Returns (result_map, error) - result_map is non-nil for benchmark mode
  func (c *RAGFlowClient) SearchOnDatasets(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	question, ok := cmd.Params["question"].(string)
  	if !ok {
  		return nil, fmt.Errorf("question not provided")
  	}
  
  	datasets, ok := cmd.Params["datasets"].(string)
  	if !ok {
  		return nil, fmt.Errorf("datasets not provided")
  	}
  
  	// Parse dataset names (comma-separated) and convert to IDs
  	datasetNames := strings.Split(datasets, ",")
  	datasetIDs := make([]string, 0, len(datasetNames))
  	for _, name := range datasetNames {
  		name = strings.TrimSpace(name)
  		id, err := c.getDatasetID(name)
  		if err != nil {
  			return nil, err
  		}
  		datasetIDs = append(datasetIDs, id)
  	}
  
  	// Check for benchmark iterations
  	iterations := 1
  	if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
  		iterations = val
  	}
  
  	payload := map[string]interface{}{
  		"kb_id":                    datasetIDs,
  		"question":                 question,
  		"similarity_threshold":     0.2,
  		"vector_similarity_weight": 0.3,
  	}
  
  	if iterations > 1 {
  		// Benchmark mode - return raw result for benchmark stats
  		return c.HTTPClient.RequestWithIterations("POST", "/chunk/retrieval_test", false, "web", nil, payload, iterations)
  	}
  
  	// Normal mode
  	resp, err := c.HTTPClient.Request("POST", "/chunk/retrieval_test", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to search on datasets: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to search on datasets: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok || code != 0 {
  		msg, _ := resJSON["message"].(string)
  		return nil, fmt.Errorf("failed to search on datasets: %s", msg)
  	}
  
  	data, ok := resJSON["data"].(map[string]interface{})
  	if !ok {
  		return nil, fmt.Errorf("invalid response format")
  	}
  
  	chunks, ok := data["chunks"].([]interface{})
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: chunks not found")
  	}
  
  	// Convert to slice of maps for printing
  	tableData := make([]map[string]interface{}, 0, len(chunks))
  	for _, chunk := range chunks {
  		if chunkMap, ok := chunk.(map[string]interface{}); ok {
  			row := map[string]interface{}{
  				"id":                chunkMap["chunk_id"],
  				"content":           chunkMap["content_with_weight"],
  				"document_id":       chunkMap["doc_id"],
  				"dataset_id":        chunkMap["kb_id"],
  				"docnm_kwd":         chunkMap["docnm_kwd"],
  				"image_id":          chunkMap["image_id"],
  				"similarity":        chunkMap["similarity"],
  				"term_similarity":   chunkMap["term_similarity"],
  				"vector_similarity": chunkMap["vector_similarity"],
  			}
  			// Add optional fields that may be empty arrays
  			if v, ok := chunkMap["doc_type_kwd"]; ok {
  				row["doc_type_kwd"] = formatEmptyArray(v)
  			}
  			if v, ok := chunkMap["important_kwd"]; ok {
  				row["important_kwd"] = formatEmptyArray(v)
  			}
  			if v, ok := chunkMap["mom_id"]; ok {
  				row["mom_id"] = formatEmptyArray(v)
  			}
  			if v, ok := chunkMap["positions"]; ok {
  				row["positions"] = formatEmptyArray(v)
  			}
  			if v, ok := chunkMap["content_ltks"]; ok {
  				row["content_ltks"] = v
  			}
  			tableData = append(tableData, row)
  		}
  	}
  
  	PrintTableSimple(tableData)
  	return nil, nil
  }
  
  // CreateToken creates a new API token
  func (c *RAGFlowClient) CreateToken(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/system/tokens", true, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to create token: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to create token: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var createResult CommonDataResponse
  	if err = json.Unmarshal(resp.Body, &createResult); err != nil {
  		return nil, fmt.Errorf("create token failed: invalid JSON (%w)", err)
  	}
  
  	if createResult.Code != 0 {
  		return nil, fmt.Errorf("%s", createResult.Message)
  	}
  
  	var result SimpleResponse
  	result.Code = 0
  	result.Message = "Token created successfully"
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // ListTokens lists all API tokens for the current user
  func (c *RAGFlowClient) ListTokens(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	resp, err := c.HTTPClient.Request("GET", "/system/tokens", true, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to list tokens: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to list tokens: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result CommonResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("list tokens failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // DropToken deletes an API token
  func (c *RAGFlowClient) DropToken(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	token, ok := cmd.Params["token"].(string)
  	if !ok {
  		return nil, fmt.Errorf("token not provided")
  	}
  
  	resp, err := c.HTTPClient.Request("DELETE", fmt.Sprintf("/system/tokens/%s", token), true, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to drop token: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to drop token: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result SimpleResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("drop token failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // SetToken sets the API token after validating it
  func (c *RAGFlowClient) SetToken(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	token, ok := cmd.Params["token"].(string)
  	if !ok {
  		return nil, fmt.Errorf("token not provided")
  	}
  
  	// Save current token to restore if validation fails
  	savedToken := c.HTTPClient.APIToken
  	savedUseAPIToken := c.HTTPClient.useAPIToken
  
  	// Set the new token temporarily for validation
  	c.HTTPClient.APIToken = token
  	c.HTTPClient.useAPIToken = true
  
  	// Validate token by calling list tokens API
  	resp, err := c.HTTPClient.Request("GET", "/tokens", true, "api", nil, nil)
  	if err != nil {
  		// Restore original token on error
  		c.HTTPClient.APIToken = savedToken
  		c.HTTPClient.useAPIToken = savedUseAPIToken
  		return nil, fmt.Errorf("failed to validate token: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		// Restore original token on error
  		c.HTTPClient.APIToken = savedToken
  		c.HTTPClient.useAPIToken = savedUseAPIToken
  		return nil, fmt.Errorf("token validation failed: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result CommonResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		// Restore original token on error
  		c.HTTPClient.APIToken = savedToken
  		c.HTTPClient.useAPIToken = savedUseAPIToken
  		return nil, fmt.Errorf("token validation failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		// Restore original token on error
  		c.HTTPClient.APIToken = savedToken
  		c.HTTPClient.useAPIToken = savedUseAPIToken
  		return nil, fmt.Errorf("token validation failed: %s", result.Message)
  	}
  
  	// Token is valid, keep it set
  	var successResult SimpleResponse
  	successResult.Code = 0
  	successResult.Message = "API token set successfully"
  	successResult.Duration = resp.Duration
  	return &successResult, nil
  }
  
  // ShowToken displays the current API token
  func (c *RAGFlowClient) ShowToken(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	if c.HTTPClient.APIToken == "" {
  		return nil, fmt.Errorf("no API token is currently set")
  	}
  
  	//fmt.Printf("Token: %s\n", c.HTTPClient.APIToken)
  
  	var result CommonResponse
  	result.Code = 0
  	result.Message = ""
  	result.Data = []map[string]interface{}{
  		{
  			"token": c.HTTPClient.APIToken,
  		},
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // UnsetToken removes the current API token
  func (c *RAGFlowClient) UnsetToken(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	if c.HTTPClient.APIToken == "" {
  		return nil, fmt.Errorf("no API token is currently set")
  	}
  
  	c.HTTPClient.APIToken = ""
  	c.HTTPClient.useAPIToken = false
  
  	var result SimpleResponse
  	result.Code = 0
  	result.Message = "API token unset successfully"
  	result.Duration = 0
  	return &result, nil
  }
  
  // CreateDataset creates a table for a dataset
  func (c *RAGFlowClient) CreateDataset(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	datasetName, ok := cmd.Params["dataset_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("dataset_name not provided")
  	}
  
  	vectorSize, ok := cmd.Params["vector_size"].(int)
  	if !ok {
  		return nil, fmt.Errorf("vector_size not provided")
  	}
  
  	// Get dataset ID by name
  	datasetID, err := c.getDatasetID(datasetName)
  	if err != nil {
  		return nil, err
  	}
  
  	payload := map[string]interface{}{
  		"kb_id":       datasetID,
  		"vector_size": vectorSize,
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/kb/doc_engine_table", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to create table: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to create table: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = fmt.Sprintf("Success to create table for dataset: %s", datasetName)
  	} else {
  		result.Message = fmt.Sprintf("Failed to create table: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // CreateDatasetInDocEngine creates a table for a dataset in doc engine
  func (c *RAGFlowClient) CreateDatasetInDocEngine(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	datasetName, ok := cmd.Params["dataset_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("dataset_name not provided")
  	}
  
  	vectorSize, ok := cmd.Params["vector_size"].(int)
  	if !ok {
  		return nil, fmt.Errorf("vector_size not provided")
  	}
  
  	// Get dataset ID by name
  	datasetID, err := c.getDatasetID(datasetName)
  	if err != nil {
  		return nil, err
  	}
  
  	payload := map[string]interface{}{
  		"kb_id":       datasetID,
  		"vector_size": vectorSize,
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/kb/doc_engine_table", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to create table: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to create table: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = fmt.Sprintf("Success to create table for dataset: %s", datasetName)
  	} else {
  		result.Message = fmt.Sprintf("Failed to create table: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // DropDatasetInDocEngine drops a table for a dataset in doc engine
  func (c *RAGFlowClient) DropDatasetInDocEngine(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	datasetName, ok := cmd.Params["dataset_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("dataset_name not provided")
  	}
  
  	// Get dataset ID by name
  	datasetID, err := c.getDatasetID(datasetName)
  	if err != nil {
  		return nil, err
  	}
  
  	payload := map[string]interface{}{
  		"kb_id": datasetID,
  	}
  
  	resp, err := c.HTTPClient.Request("DELETE", "/kb/doc_engine_table", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to drop dataset: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to drop dataset: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = fmt.Sprintf("Success to drop table for dataset: %s", datasetName)
  	} else {
  		result.Message = fmt.Sprintf("Failed to drop table for dataset: %s: %v", datasetName, resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // CreateMetadataInDocEngine creates the document metadata table for the tenant
  func (c *RAGFlowClient) CreateMetadataInDocEngine(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/tenant/doc_engine_metadata_table", false, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to create metadata table: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to create metadata table: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = "Success to create metadata table"
  	} else {
  		result.Message = fmt.Sprintf("Failed to create metadata table: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // DropMetadataInDocEngine drops the document metadata table for the tenant
  func (c *RAGFlowClient) DropMetadataInDocEngine(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	resp, err := c.HTTPClient.Request("DELETE", "/tenant/doc_engine_metadata_table", false, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to drop metadata table: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to drop metadata table: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = "Success to drop metadata table"
  	} else {
  		result.Message = fmt.Sprintf("Failed to drop metadata table: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // AddProvider creates a new model provider
  // ADD PROVIDER <name>
  // ADD PROVIDER <name> <api_key>
  func (c *RAGFlowClient) AddProvider(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	providerName, ok := cmd.Params["provider_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("provider name not provided")
  	}
  
  	// Build payload
  	payload := map[string]interface{}{
  		"provider_name": providerName,
  	}
  
  	resp, err := c.HTTPClient.Request("PUT", "/providers", true, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to add provider: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to add provider: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result SimpleResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("add provider failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // ListProviders lists all providers
  // LIST PROVIDERS
  func (c *RAGFlowClient) ListProviders(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	resp, err := c.HTTPClient.Request("GET", "/providers", true, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to list providers: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to list providers: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result CommonResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("list providers failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // DeleteProvider deletes a provider
  // DELETE PROVIDER <name>
  func (c *RAGFlowClient) DeleteProvider(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	providerName, ok := cmd.Params["provider_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("provider name not provided")
  	}
  
  	url := fmt.Sprintf("/providers/%s", providerName)
  
  	// Build payload
  	payload := map[string]interface{}{
  		"llm_factory": providerName,
  	}
  
  	resp, err := c.HTTPClient.Request("DELETE", url, true, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to delete provider: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to delete provider: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result SimpleResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("delete provider failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // CreateProviderInstance creates a new provider instance
  // CREATE PROVIDER <name> INSTANCE <instance_name> <api_key>
  func (c *RAGFlowClient) CreateProviderInstance(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	providerName, ok := cmd.Params["provider_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("provider name not provided")
  	}
  
  	instanceName, ok := cmd.Params["instance_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("instance name not provided")
  	}
  
  	apiKey, ok := cmd.Params["api_key"].(string)
  	if !ok {
  		return nil, fmt.Errorf("API key not provided")
  	}
  
  	url := fmt.Sprintf("/providers/%s/instances", providerName)
  
  	payload := map[string]interface{}{
  		"instance_name": instanceName,
  		"api_key":       apiKey,
  	}
  
  	resp, err := c.HTTPClient.Request("POST", url, true, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to create provider instance: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to create provider instance: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result SimpleResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("create provider instance failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // ListProviderInstances lists all instances of a provider
  // LIST INSTANCES FROM PROVIDER <name>
  func (c *RAGFlowClient) ListProviderInstances(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	providerName, ok := cmd.Params["provider_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("provider name not provided")
  	}
  
  	url := fmt.Sprintf("/providers/%s/instances", providerName)
  
  	resp, err := c.HTTPClient.Request("GET", url, true, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to list instances: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to list instances: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result CommonResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("list instances failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // ShowProviderInstance shows details of a specific instance
  // SHOW INSTANCE <name> FROM PROVIDER <name>
  func (c *RAGFlowClient) ShowProviderInstance(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	instanceName, ok := cmd.Params["instance_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("instance name not provided")
  	}
  
  	providerName, ok := cmd.Params["provider_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("provider name not provided")
  	}
  
  	url := fmt.Sprintf("/providers/%s/instances/%s", providerName, instanceName)
  
  	resp, err := c.HTTPClient.Request("GET", url, true, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to show instance: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to show instance: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result CommonDataResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("show instance failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // AlterProviderInstance renames a provider instance
  // ALTER INSTANCE <name> NAME <new_name> FROM PROVIDER <name>
  func (c *RAGFlowClient) AlterProviderInstance(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	instanceName, ok := cmd.Params["instance_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("instance name not provided")
  	}
  
  	newName, ok := cmd.Params["new_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("new name not provided")
  	}
  
  	providerName, ok := cmd.Params["provider_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("provider name not provided")
  	}
  
  	url := fmt.Sprintf("/providers/%s/instances/%s", providerName, instanceName)
  
  	payload := map[string]interface{}{
  		"llm_name": newName,
  	}
  
  	resp, err := c.HTTPClient.Request("PUT", url, true, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to alter instance: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to alter instance: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result SimpleResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("alter instance failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  // DropProviderInstance deletes a provider instance
  // DROP INSTANCE <name> FROM PROVIDER <name>
  func (c *RAGFlowClient) DropProviderInstance(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	instanceName, ok := cmd.Params["instance_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("instance name not provided")
  	}
  
  	providerName, ok := cmd.Params["provider_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("provider name not provided")
  	}
  
  	payload := map[string]interface{}{
  		"instances": []string{instanceName},
  	}
  
  	url := fmt.Sprintf("/providers/%s/instances", providerName)
  
  	resp, err := c.HTTPClient.Request("DELETE", url, true, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to drop instance: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to drop instance: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result SimpleResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("drop instance failed: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  func (c *RAGFlowClient) ListInstanceModels(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  	providerName, ok := cmd.Params["provider_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("provider_name not provided")
  	}
  	instanceName, ok := cmd.Params["instance_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("instance_name not provided")
  	}
  
  	var endPoint string
  	endPoint = fmt.Sprintf("/providers/%s/instances/%s/models", providerName, instanceName)
  
  	resp, err := c.HTTPClient.Request("GET", endPoint, true, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to list instance models: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to list instance models: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	var result CommonResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("failed to list instance models: invalid JSON (%w)", err)
  	}
  
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  func (c *RAGFlowClient) EnableOrDisableModel(cmd *Command, status string) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	modelName, ok := cmd.Params["model_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("model name not provided")
  	}
  
  	instanceName, ok := cmd.Params["instance_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("instance name not provided")
  	}
  
  	providerName, ok := cmd.Params["provider_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("provider name not provided")
  	}
  
  	url := fmt.Sprintf("/providers/%s/instances/%s/models/%s", providerName, instanceName, modelName)
  
  	payload := map[string]interface{}{
  		"status": status,
  	}
  
  	resp, err := c.HTTPClient.Request("PATCH", url, true, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to enable/disable model: %w", err)
  	}
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to enable/disable model: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  	var result SimpleResponse
  	if err = json.Unmarshal(resp.Body, &result); err != nil {
  		return nil, fmt.Errorf("enable/disable model failed: invalid JSON (%w)", err)
  	}
  	if result.Code != 0 {
  		return nil, fmt.Errorf("%s", result.Message)
  	}
  	result.Duration = resp.Duration
  	return &result, nil
  }
  
  func (c *RAGFlowClient) ChatToModel(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	var providerName, instanceName, modelName string
  
  	// Check if model_name is provided in command
  	if compositeModelName, ok := cmd.Params["model_name"].(string); ok && compositeModelName != "" {
  		names := strings.Split(compositeModelName, "/")
  		if len(names) != 3 {
  			return nil, fmt.Errorf("model name must be in format 'provider/instance/model'")
  		}
  		providerName = names[0]
  		instanceName = names[1]
  		modelName = names[2]
  	} else if c.CurrentModel != nil {
  		// Use current model if set
  		providerName = c.CurrentModel.Provider
  		instanceName = c.CurrentModel.Instance
  		modelName = c.CurrentModel.Model
  	} else {
  		return nil, fmt.Errorf("model name not provided and no current model set. Use 'use model' command first")
  	}
  
  	message := cmd.Params["message"].(string)
  	reasoning := cmd.Params["reasoning"].(bool)
  
  	url := fmt.Sprintf("/providers/%s/instances/%s/models/%s", providerName, instanceName, modelName)
  
  	payload := map[string]interface{}{
  		"message":   message,
  		"stream":    true, // use stream API
  		"reasoning": reasoning,
  	}
  
  	// Call stream http api
  	reader, duration, err := c.HTTPClient.RequestStream("POST", url, true, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to chat model: %w", err)
  	}
  	defer reader.Close()
  
  	// Parse SSE and output to console
  	scanner := bufio.NewScanner(reader)
  	var fullMessage strings.Builder
  
  	reasoningPrint := true
  	messagePrint := true
  	for scanner.Scan() {
  		line := scanner.Text()
  		if strings.HasPrefix(line, "data:") {
  			data := strings.TrimPrefix(line, "data:")
  			data = strings.TrimSpace(data)
  
  			if strings.HasPrefix(data, "[REASONING]") {
  				data = strings.TrimPrefix(data, "[REASONING]")
  				if reasoningPrint {
  					fmt.Print("Thinking: ")
  					reasoningPrint = false
  				} else {
  					fmt.Print(data)
  				}
  				os.Stdout.Sync()
  			}
  			if strings.HasPrefix(data, "[MESSAGE]") {
  				data = strings.TrimPrefix(data, "[MESSAGE]")
  				if messagePrint {
  					if reasoning {
  						fmt.Println()
  					}
  					fmt.Print("Answer: ")
  					messagePrint = false
  				} else {
  					fmt.Print(data)
  					os.Stdout.Sync()
  					fullMessage.WriteString(data)
  				}
  			}
  		} else if strings.HasPrefix(line, "event:error") {
  			// error event
  			if scanner.Scan() {
  				errData := strings.TrimPrefix(scanner.Text(), "data:")
  				errData = strings.TrimSpace(errData)
  				return nil, fmt.Errorf("chat error: %s", errData)
  			}
  			// If there's an error, return a generic error
  			return nil, fmt.Errorf("chat error: received error event from server")
  		}
  	}
  
  	if err := scanner.Err(); err != nil {
  		return nil, fmt.Errorf("error reading stream: %w", err)
  	}
  
  	fmt.Println()
  
  	result := &StreamMessageResponse{
  		Code:     0,
  		Message:  fullMessage.String(),
  		Duration: duration,
  	}
  	return result, nil
  }
  
  // UseModel sets the current model for chat
  func (c *RAGFlowClient) UseModel(cmd *Command) (ResponseIf, error) {
  	if c.HTTPClient.APIToken == "" && c.HTTPClient.LoginToken == "" {
  		return nil, fmt.Errorf("API token not set. Please login first")
  	}
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	modelIdentifier, ok := cmd.Params["model_identifier"].(string)
  	if !ok || modelIdentifier == "" {
  		return nil, fmt.Errorf("model identifier not provided")
  	}
  
  	names := strings.Split(modelIdentifier, "/")
  	if len(names) != 3 {
  		return nil, fmt.Errorf("model identifier must be in format 'provider/instance/model'")
  	}
  
  	c.CurrentModel = &CurrentModel{
  		Provider: names[0],
  		Instance: names[1],
  		Model:    names[2],
  	}
  
  	var result SimpleResponse
  	result.Code = 0
  	result.Message = fmt.Sprintf("Current model set to: %s/%s/%s", c.CurrentModel.Provider, c.CurrentModel.Instance, c.CurrentModel.Model)
  	return &result, nil
  }
  
  // ShowCurrentModel displays the current model configuration
  func (c *RAGFlowClient) ShowCurrentModel(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	if c.CurrentModel == nil {
  		return nil, fmt.Errorf("no current model set. Use 'use model' command first")
  	}
  
  	var result CommonResponse
  	result.Code = 0
  	result.Data = []map[string]interface{}{
  		{
  			"provider": c.CurrentModel.Provider,
  			"instance": c.CurrentModel.Instance,
  			"model":    c.CurrentModel.Model,
  		},
  	}
  	return &result, nil
  }
  
  // Context related commands
  
  // CEList handles the ls command - lists nodes using Context Engine
  func (c *RAGFlowClient) CEList(cmd *Command) (ResponseIf, error) {
  	// Get path from command params, default to "datasets"
  	path, _ := cmd.Params["path"].(string)
  	if path == "" {
  		path = "datasets"
  	}
  
  	// Parse options
  	opts := &ce.ListOptions{}
  	if recursive, ok := cmd.Params["recursive"].(bool); ok {
  		opts.Recursive = recursive
  	}
  	if limit, ok := cmd.Params["limit"].(int); ok {
  		opts.Limit = limit
  	}
  	if offset, ok := cmd.Params["offset"].(int); ok {
  		opts.Offset = offset
  	}
  
  	// Execute list command through Context Engine
  	ctx := context.Background()
  	result, err := c.ContextEngine.List(ctx, path, opts)
  	if err != nil {
  		return nil, err
  	}
  
  	// Convert to response
  	var response ContextListResponse
  	response.OutputFormat = c.OutputFormat
  	response.Code = 0
  	response.Data = ce.FormatNodes(result.Nodes, string(c.OutputFormat))
  
  	return &response, nil
  }
  
  // CESearch handles the search command using Context Engine
  func (c *RAGFlowClient) CESearch(cmd *Command) (ResponseIf, error) {
  	// Get path and query from command params
  	path, _ := cmd.Params["path"].(string)
  	if path == "" {
  		path = "datasets"
  	}
  	query, _ := cmd.Params["query"].(string)
  
  	// Parse options
  	opts := &ce.SearchOptions{
  		Query: query,
  	}
  	if limit, ok := cmd.Params["limit"].(int); ok {
  		opts.Limit = limit
  	}
  	if offset, ok := cmd.Params["offset"].(int); ok {
  		opts.Offset = offset
  	}
  	if recursive, ok := cmd.Params["recursive"].(bool); ok {
  		opts.Recursive = recursive
  	}
  
  	// Execute search command through Context Engine
  	ctx := context.Background()
  	result, err := c.ContextEngine.Search(ctx, path, opts)
  	if err != nil {
  		return nil, err
  	}
  
  	// Convert to response
  	var response ContextSearchResponse
  	response.OutputFormat = c.OutputFormat
  	response.Code = 0
  	response.Total = result.Total
  	response.Data = ce.FormatNodes(result.Nodes, string(c.OutputFormat))
  
  	return &response, nil
  }
  
  // InsertDatasetFromFile inserts dataset chunks from a JSON file
  func (c *RAGFlowClient) InsertDatasetFromFile(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  	filePath, ok := cmd.Params["file_path"].(string)
  	if !ok {
  		return nil, fmt.Errorf("file_path not provided")
  	}
  
  	payload := map[string]interface{}{
  		"file_path": filePath,
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/kb/insert_from_file", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to insert dataset from file: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to insert dataset from file: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = fmt.Sprintf("Success to insert dataset from file: %s", filePath)
  	} else {
  		result.Message = fmt.Sprintf("Failed to insert dataset from file: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // InsertMetadataFromFile inserts metadata from a JSON file
  func (c *RAGFlowClient) InsertMetadataFromFile(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	filePath, ok := cmd.Params["file_path"].(string)
  	if !ok {
  		return nil, fmt.Errorf("file_path not provided")
  	}
  
  	payload := map[string]interface{}{
  		"file_path": filePath,
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/tenant/insert_metadata_from_file", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to insert metadata from file: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to insert metadata from file: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = fmt.Sprintf("Success to insert metadata from file: %s", filePath)
  	} else {
  		result.Message = fmt.Sprintf("Failed to insert metadata from file: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // UpdateChunk updates a chunk in a dataset
  func (c *RAGFlowClient) UpdateChunk(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	chunkID, ok := cmd.Params["chunk_id"].(string)
  	if !ok {
  		return nil, fmt.Errorf("chunk_id not provided")
  	}
  
  	datasetName, ok := cmd.Params["dataset_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("dataset_name not provided")
  	}
  
  	jsonBody, ok := cmd.Params["json_body"].(string)
  	if !ok {
  		return nil, fmt.Errorf("json_body not provided")
  	}
  
  	// Look up dataset_id from dataset_name
  	datasetID, err := c.getDatasetID(datasetName)
  	if err != nil {
  		return nil, fmt.Errorf("failed to get dataset ID: %w", err)
  	}
  
  	// Try to get doc_id from the chunk retrieval endpoint
  	getResp, err := c.HTTPClient.Request("GET", "/chunk/get?chunk_id="+chunkID, false, "web", nil, nil)
  	if err != nil {
  		return nil, fmt.Errorf("failed to get chunk info: %w", err)
  	}
  
  	var docID string
  	if getResp.StatusCode == 200 {
  		getJSON, err := getResp.JSON()
  		if err == nil {
  			if data, ok := getJSON["data"].(map[string]interface{}); ok {
  				if d, ok := data["doc_id"].(string); ok {
  					docID = d
  				}
  			}
  		}
  	}
  
  	if docID == "" {
  		return nil, fmt.Errorf("could not find document_id for chunk %s. Please provide document_id explicitly", chunkID)
  	}
  
  	// Parse the JSON body
  	var payload map[string]interface{}
  	if err := json.Unmarshal([]byte(jsonBody), &payload); err != nil {
  		return nil, fmt.Errorf("invalid JSON body: %w", err)
  	}
  
  	// Add IDs to payload
  	payload["dataset_id"] = datasetID
  	payload["document_id"] = docID
  	payload["chunk_id"] = chunkID
  
  	resp, err := c.HTTPClient.Request("POST", "/chunk/update", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to update chunk: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to update chunk: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = fmt.Sprintf("Success to update chunk: %s", chunkID)
  	} else {
  		result.Message = fmt.Sprintf("Failed to update chunk: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // SetMeta sets metadata for a document
  func (c *RAGFlowClient) SetMeta(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	docID, ok := cmd.Params["doc_id"].(string)
  	if !ok {
  		return nil, fmt.Errorf("doc_id not provided")
  	}
  
  	metaJSON, ok := cmd.Params["meta"].(string)
  	if !ok {
  		return nil, fmt.Errorf("meta not provided")
  	}
  
  	payload := map[string]interface{}{
  		"doc_id": docID,
  		"meta":   metaJSON,
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/document/set_meta", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to set metadata: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to set metadata: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = fmt.Sprintf("Success to set metadata for document: %s", docID)
  	} else {
  		result.Message = fmt.Sprintf("Failed to set metadata: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // RmTags removes tags from chunks in a dataset
  func (c *RAGFlowClient) RmTags(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	datasetName, ok := cmd.Params["dataset_name"].(string)
  	if !ok {
  		return nil, fmt.Errorf("dataset_name not provided")
  	}
  
  	kbID, err := c.getDatasetID(datasetName)
  	if err != nil {
  		return nil, err
  	}
  
  	tags, ok := cmd.Params["tags"].([]string)
  	if !ok {
  		return nil, fmt.Errorf("tags not provided")
  	}
  
  	payload := map[string]interface{}{
  		"tags": tags,
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/kb/"+kbID+"/rm_tags", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to remove tags: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to remove tags: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		result.Message = fmt.Sprintf("Success to remove tags from dataset: %s", kbID)
  	} else {
  		result.Message = fmt.Sprintf("Failed to remove tags: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  
  // RemoveChunks removes chunks from a document
  func (c *RAGFlowClient) RemoveChunks(cmd *Command) (ResponseIf, error) {
  	if c.ServerType != "user" {
  		return nil, fmt.Errorf("this command is only allowed in USER mode")
  	}
  
  	docID, ok := cmd.Params["doc_id"].(string)
  	if !ok {
  		return nil, fmt.Errorf("doc_id not provided")
  	}
  
  	payload := map[string]interface{}{
  		"doc_id": docID,
  	}
  
  	// Check if delete_all is set
  	if deleteAll, ok := cmd.Params["delete_all"].(bool); ok && deleteAll {
  		payload["delete_all"] = true
  	} else if chunkIDs, ok := cmd.Params["chunk_ids"].([]string); ok {
  		payload["chunk_ids"] = chunkIDs
  	}
  
  	resp, err := c.HTTPClient.Request("POST", "/chunk/rm", false, "web", nil, payload)
  	if err != nil {
  		return nil, fmt.Errorf("failed to remove chunks: %w", err)
  	}
  
  	if resp.StatusCode != 200 {
  		return nil, fmt.Errorf("failed to remove chunks: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
  	}
  
  	resJSON, err := resp.JSON()
  	if err != nil {
  		return nil, fmt.Errorf("invalid JSON response: %w", err)
  	}
  
  	code, ok := resJSON["code"].(float64)
  	if !ok {
  		return nil, fmt.Errorf("invalid response format: code is not a number")
  	}
  
  	var result SimpleResponse
  	result.Code = int(code)
  	if result.Code == 0 {
  		deletedCount := int64(0)
  		switch data := resJSON["data"].(type) {
  		case float64:
  			deletedCount = int64(data)
  		case map[string]interface{}:
  			if count, ok := data["deleted_count"].(float64); ok {
  				deletedCount = int64(count)
  			}
  		}
  		result.Message = fmt.Sprintf("Success to remove chunks from document %s: %d chunks deleted", docID, deletedCount)
  	} else {
  		result.Message = fmt.Sprintf("Failed to remove chunks: %v", resJSON)
  	}
  	result.Duration = 0
  	return &result, nil
  }
  