You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.4 KiB
Go

/*
* Copyright 2025 CloudWeGo Authors
*
* 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 open
import (
"context"
"fmt"
"os"
"os/exec"
"strings"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/components/tool/utils"
)
type OpenFileToolImpl struct {
config *OpenFileToolConfig
}
type OpenFileToolConfig struct {
}
func defaultOpenFileToolConfig(ctx context.Context) (*OpenFileToolConfig, error) {
config := &OpenFileToolConfig{}
return config, nil
}
func NewOpenFileTool(ctx context.Context, config *OpenFileToolConfig) (tn tool.BaseTool, err error) {
if config == nil {
config, err = defaultOpenFileToolConfig(ctx)
if err != nil {
return nil, err
}
}
t := &OpenFileToolImpl{config: config}
tn, err = t.ToEinoTool()
if err != nil {
return nil, err
}
return tn, nil
}
func (of *OpenFileToolImpl) ToEinoTool() (tool.InvokableTool, error) {
return utils.InferTool("open", "open a file/dir/web url in the system by default application", of.Invoke)
}
func (of *OpenFileToolImpl) Invoke(ctx context.Context, req OpenReq) (res OpenRes, err error) {
if req.URI == "" {
res.Message = "uri is required"
return res, nil
}
// if is file or dir, check if exists
if isFilePath(req.URI) {
if _, err := os.Stat(req.URI); os.IsNotExist(err) {
res.Message = fmt.Sprintf("file not exists: %s", req.URI)
return res, nil
}
}
err = exec.Command("open", req.URI).Run()
if err != nil {
res.Message = fmt.Sprintf("failed to open %s: %s", req.URI, err.Error())
return res, nil
}
res.Message = fmt.Sprintf("success, open %s", req.URI)
return res, nil
}
type OpenReq struct {
URI string `json:"uri" jsonschema:"description=The uri of the file/dir/web url to open"`
}
type OpenRes struct {
Message string `json:"message" jsonschema:"description=The message of the operation"`
}
func isFilePath(path string) bool {
return strings.HasPrefix(path, "file://") && !strings.Contains(path, "://")
}