Files
ragflow/internal/cli/client.go
Jin Hai d02eb6b596 Go: refactor CLI (#15728)
### What problem does this PR solve?

```
RAGFlow(user)> add api server 'ccc' host '127.0.0.1:9980';
SUCCESS
RAGFlow(user)> list api server;
+------------+---------------+-----------------+---------+-------------+---------------+
| api_server | api_server_ip | api_server_port | auth    | user_name   | user_password |
+------------+---------------+-----------------+---------+-------------+---------------+
| ccc        | 127.0.0.1     | 9980            | no auth |             |               |
| default    | 127.0.0.1     | 9384            | login   | aaa@aaa.com | ***           |
+------------+---------------+-----------------+---------+-------------+---------------+
RAGFlow(user)> delete api server 'ccc';
SUCCESS
RAGFlow(user)> list api server;
+------------+---------------+-----------------+---------+
| api_server | api_server_ip | api_server_port | auth    |
+------------+---------------+-----------------+---------+
| default    | 127.0.0.1     | 9384            | no auth |
+------------+---------------+-----------------+---------+

RAGFlow(user)> show admin server;
+--------------+-------+
| field        | value |
+--------------+-------+
| admin_server | N/A   |
+--------------+-------+
RAGFlow(user)> add admin server host '127.0.0.1:9880';
SUCCESS
RAGFlow(user)> show admin server;
+-------------------+-----------+
| field             | value     |
+-------------------+-----------+
| admin_server_ip   | 127.0.0.1 |
| admin_server_port | 9880      |
| auth              | no auth   |
+-------------------+-----------+
RAGFlow(user)> delete admin server;
SUCCESS
RAGFlow(user)> show admin server;
+--------------+-------+
| field        | value |
+--------------+-------+
| admin_server | N/A   |
+--------------+-------+

RAGFlow(user)> show current
+-----------------+-------------+
| field           | value       |
+-----------------+-------------+
| api_server_port | 9384        |
| user_name       | aaa@aaa.com |
| user_password   | ***         |
| mode            | api         |
| verbose         | false       |
| api_server      | default     |
| api_server_ip   | 127.0.0.1   |
| auth            | login       |
| output          | table       |
| interactive     | true        |
+-----------------+-------------+
```
### Type of change

- [x] Refactoring

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2026-06-09 15:22:50 +08:00

119 lines
3.8 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 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 != nil {
authKind = "api"
} else if a.client.LoginToken != nil {
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)
}
// 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")
}