本地文件系统

Local Backend

Package: github.com/cloudwego/eino-ext/adk/backend/local

注意:如果 eino 版本是 v0.8.0 及以上,需要使用 local backend 的 adk/backend/local/v0.2.1 版本。

概述

Local Backend 是 EINO ADK FileSystem 的本地文件系统实现,直接操作本机文件系统,提供原生性能和零配置体验。

核心特性

  • 零配置 - 开箱即用
  • 原生性能 - 直接文件系统访问,无网络开销
  • 路径安全 - 强制使用绝对路径
  • 流式执行 - 支持命令输出实时流
  • 命令验证 - 可选的安全验证钩子

安装

go get github.com/cloudwego/eino-ext/adk/backend/local

配置

type Config struct {
    // 可选: 命令验证函数,用于 Execute() 安全控制
    ValidateCommand func(string) error
}

快速开始

基本用法

import (
    "context"

    "github.com/cloudwego/eino-ext/adk/backend/local"
    "github.com/cloudwego/eino/adk/filesystem"
)

func main() {
    ctx := context.Background()

    backend, err := local.NewBackend(ctx, &local.Config{})
    if err != nil {
        panic(err)
    }

    // 写入文件(必须是绝对路径)
    err = backend.Write(ctx, &filesystem.WriteRequest{
        FilePath: "/tmp/hello.txt",
        Content:  "Hello, Local Backend!",
    })

    // 读取文件
    fcontent, err := backend.Read(ctx, &filesystem.ReadRequest{
        FilePath: "/tmp/hello.txt",
    })
    fmt.Println(fcontent.Content)
}

带命令验证

func validateCommand(cmd string) error {
    allowed := map[string]bool{"ls": true, "cat": true, "grep": true}
    parts := strings.Fields(cmd)
    if len(parts) == 0 || !allowed[parts[0]] {
        return fmt.Errorf("command not allowed: %s", parts[0])
    }
    return nil
}

backend, _ := local.NewBackend(ctx, &local.Config{
    ValidateCommand: validateCommand,
})

与 Agent 集成

import (
    "github.com/cloudwego/eino/adk"
    fsMiddleware "github.com/cloudwego/eino/adk/middlewares/filesystem"
)

// 创建 Backend
backend, _ := local.NewBackend(ctx, &local.Config{})

// 创建 Middleware
middleware, _ := fsMiddleware.New(ctx, &fsMiddleware.Config{
    Backend: backend,
    StreamingShell: backend,
})

// 创建 Agent
agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
    Name:        "LocalFileAgent",
    Description: "具有本地文件系统访问能力的 AI Agent",
    Model:       chatModel,
    Handlers:    []adk.ChatModelAgentMiddleware{middleware},
})

API 参考

方法描述
LsInfo列出目录内容
Read读取文件内容(支持分页,默认 200 行)
Write创建新文件(已存在则报错)
Edit替换文件内容
GrepRaw搜索文件内容(字面量匹配)
GlobInfo按模式查找文件
Execute执行 shell 命令
ExecuteStreaming流式执行命令

示例

// 列出目录
files, _ := backend.LsInfo(ctx, &filesystem.LsInfoRequest{
    Path: "/home/user",
})

// 读取文件(分页)
fcontent, _ := backend.Read(ctx, &filesystem.ReadRequest{
    FilePath: "/path/to/file.txt",
    Offset:   0,
    Limit:    50,
})

// 搜索内容(字面量匹配,非正则)
matches, _ := backend.GrepRaw(ctx, &filesystem.GrepRequest{
    Path:    "/home/user/project",
    Pattern: "TODO",
    Glob:    "*.go",
})

// 查找文件
files, _ := backend.GlobInfo(ctx, &filesystem.GlobInfoRequest{
    Path:    "/home/user",
    Pattern: "**/*.go",
})

// 编辑文件
backend.Edit(ctx, &filesystem.EditRequest{
    FilePath:   "/tmp/file.txt",
    OldString:  "old",
    NewString:  "new",
    ReplaceAll: true,
})

// 执行命令
result, _ := backend.Execute(ctx, &filesystem.ExecuteRequest{
    Command: "ls -la /tmp",
})

// 流式执行
reader, _ := backend.ExecuteStreaming(ctx, &filesystem.ExecuteRequest{
    Command: "tail -f /var/log/app.log",
})
for {
    resp, err := reader.Recv()
    if err == io.EOF {
        break
    }
    fmt.Print(resp.Stdout)
}

路径要求

所有路径必须是绝对路径(以 / 开头):

// 正确
backend.Read(ctx, &filesystem.ReadRequest{FilePath: "/home/user/file.txt"})

// 错误
backend.Read(ctx, &filesystem.ReadRequest{FilePath: "./file.txt"})

转换相对路径:

absPath, _ := filepath.Abs("./relative/path")

与 Agentkit Backend 对比

特性LocalAgentkit
执行模型本地直接远程沙箱
网络依赖需要
配置复杂度零配置需要凭证
安全模型OS 权限隔离沙箱
流式输出支持不支持
平台支持Unix/Linux/macOS任意
适用场景开发/本地环境多租户/生产环境

常见问题

**Q: 为什么运行 grep 命令报错 ripgrep (rg) is not installed or not in PATH. Please install it: **https://github.com/BurntSushi/ripgrep#installation

local 的 Grep 命令默认依赖** ripgrep **指令,如系统没有预装 ripgrep 则需要通过文档安装 ripgrep

Q: GrepRaw 支持正则吗?

支持正则匹配,GrepRaw 底层使用的是 ripgrep 命令做的 Grep 操作

Q: Windows 支持吗?

不支持,依赖 /bin/sh