返回知识库
0

第六章:工具与数据类能力

本章目标:帮助你理解工具注册机制、工具执行管道、以及 Shell Subprocess FS LSP Web / Skill 等能力插件的实现细节。阅读本章后,你应该能回答"一个工具是如何被模型调用的"以及"如何添加一个新的能力插件"。


6.1 工具注册机制

6.1.1 工具的三角色模式

每个工具能力遵循能力接缝模式:

预览
源码

Consumer

Service Provider

Service Definition

Service 定义
接口声明

Provider 实现
具体功能

工具 Schema
面向模型

graph TB
    subgraph "Service Definition"
        A["Service 定义<br/>接口声明"]
    end

    subgraph "Service Provider"
        B["Provider 实现<br/>具体功能"]
    end

    subgraph "Consumer"
        C["工具 Schema<br/>面向模型"]
    end

    A --> B
    B --> C

6.1.2 ctx.tools 的角色

ctx.toolscore/tools)是工具注册的核心服务:

// 来自 packages/core/tools/src/index.ts
declare module '@deepseek-ai/cordis' {
  interface Context {
    tools: ToolRuntime
  }
}

interface ToolRuntime {
  /** 注册工具 */
  register(tool: ToolRegistration): Disposable
  
  /** 获取所有工具 schema */
  schemas(): ToolSchema[]
  
  /** 获取 SDK 工具 schema */
  sdkSchemas(): ToolSchema[]
}

6.1.3 工具注册

// 注册一个工具
const disposable = ctx.tools.register({
  name: 'my_tool',
  description: '我的自定义工具',
  parameters: {
    type: 'object',
    properties: {
      input: { type: 'string', description: '输入参数' }
    },
    required: ['input']
  },
  async execute(input, context) {
    // 执行工具逻辑
    return { result: `处理了: ${input.input}` }
  }
})

// 之后可以注销
disposable.dispose()

6.1.4 工具 Schema 生成

工具 schema 会被自动添加到模型请求中:

预览
源码

ctx.tools.register()

工具注册表

schemas()

Prompt Assembly

模型请求中的 tools 字段

graph LR
    A["ctx.tools.register()"] --> B["工具注册表"]
    B --> C["schemas()"]
    C --> D["Prompt Assembly"]
    D --> E["模型请求中的 tools 字段"]

6.2 工具执行管道

6.2.1 执行流程

预览
源码
sequenceDiagram
    participant Model as LLM
    participant Loop as Agent Loop
    participant Pre as tools/pre-execute
    participant Exec as tools/execute
    participant Post as tools/post-execute
    participant Tool as 实际工具

    Model->>Loop: tool_call(name, args)
    Loop->>Pre: waterfall('tools/pre-execute', input)
    Note over Pre: 预处理、验证、拦截
    Pre-->>Loop: modified input
    Loop->>Exec: waterfall('tools/execute', input)
    Exec->>Tool: 实际执行
    Tool-->>Exec: result
    Exec-->>Loop: result
    Loop->>Post: waterfall('tools/post-execute', result)
    Note over Post: 后处理、审计
    Post-->>Loop: final result
    Loop->>Model: tool_result
sequenceDiagram
    participant Model as LLM
    participant Loop as Agent Loop
    participant Pre as tools/pre-execute
    participant Exec as tools/execute
    participant Post as tools/post-execute
    participant Tool as 实际工具

    Model->>Loop: tool_call(name, args)
    Loop->>Pre: waterfall('tools/pre-execute', input)
    Note over Pre: 预处理、验证、拦截
    Pre-->>Loop: modified input
    Loop->>Exec: waterfall('tools/execute', input)
    Exec->>Tool: 实际执行
    Tool-->>Exec: result
    Exec-->>Loop: result
    Loop->>Post: waterfall('tools/post-execute', result)
    Note over Post: 后处理、审计
    Post-->>Loop: final result
    Loop->>Model: tool_result

6.2.2 工具执行事件

// 三个 waterfall 事件
'tools/pre-execute'   // 工具执行前
'tools/execute'       // 工具执行
'tools/post-execute'  // 工具执行后

关键规则:每个监听者必须调用 next() 来委托。

6.2.3 ToolExecutionInput

interface ToolExecutionInput {
  /** 工具名称 */
  name: string
  /** 工具参数 */
  parameters: Record<string, unknown>
  /** 关联的 Agent */
  agent: Agent
  /** 关联的会话 */
  session: Session
}

6.2.4 ToolRunContext

interface ToolRunContext {
  /** 取消信号 */
  signal: AbortSignal
  /** 超时设置 */
  timeout?: number
  /** 日志记录器 */
  logger: Logger
}

6.3 Shell 能力

6.3.1 架构

预览
源码

依赖

Shell 能力

shell/ (Service Definition)

shell-local/ (Provider)

shell-pwsh/ (Provider)

tool-shell/ (Consumer)

subprocess/

graph TB
    subgraph "Shell 能力"
        A["shell/ (Service Definition)"]
        B["shell-local/ (Provider)"]
        C["shell-pwsh/ (Provider)"]
        D["tool-shell/ (Consumer)"]
    end

    subgraph "依赖"
        E["subprocess/"]
    end

    A --> B
    A --> C
    B --> E
    C --> E
    D --> A

6.3.2 本地 Shell Provider

// 来自 packages/shell/shell-local/src/index.ts(概念性)
class LocalShellProvider implements ShellProvider {
  /** 执行命令 */
  async execute(command: string, options: ShellOptions): Promise<ShellResult> {
    // 1. 解析命令
    const [cmd, ...args] = this.parseCommand(command)
    
    // 2. 通过 subprocess 执行
    const process = await this.subprocess.spawn(cmd, args, {
      cwd: options.cwd,
      env: options.env,
      timeout: options.timeout
    })
    
    // 3. 收集输出
    const stdout = await process.stdout.read()
    const stderr = await process.stderr.read()
    const exitCode = await process.wait()
    
    return { stdout, stderr, exitCode }
  }
}

6.3.3 工具集成

// tool-shell 将 Shell 能力暴露为模型工具
ctx.tools.register({
  name: 'bash',
  description: 'Execute a bash command',
  parameters: {
    type: 'object',
    properties: {
      command: { type: 'string', description: 'The command to execute' }
    },
    required: ['command']
  },
  async execute(input) {
    const result = await ctx.shell.execute(input.command)
    return result
  }
})

6.4 Subprocess 能力

6.4.1 架构

预览
源码
graph TB
    subgraph "Subprocess 能力"
        A["subprocess/ (Service Definition)"]
        B["subprocess-local/ (Provider)"]
        C["消费者: shell, terminal, code-runtime"]
    end

    A --> B
    A --> C
graph TB
    subgraph "Subprocess 能力"
        A["subprocess/ (Service Definition)"]
        B["subprocess-local/ (Provider)"]
        C["消费者: shell, terminal, code-runtime"]
    end

    A --> B
    A --> C

6.4.2 本地 Subprocess Provider

// 来自 packages/subprocess/subprocess-local/src/index.ts(概念性)
class LocalSubprocessProvider implements SubprocessProvider {
  /** 启动进程 */
  async spawn(command: string, args: string[], options: SpawnOptions): Promise<RunningProcess> {
    const child = spawn(command, args, {
      cwd: options.cwd,
      env: options.env,
      stdio: ['pipe', 'pipe', 'pipe']
    })
    
    return {
      pid: child.pid,
      stdout: child.stdout,
      stderr: child.stderr,
      async wait() {
        return new Promise(resolve => {
          child.on('close', code => resolve(code))
        })
      },
      kill() {
        child.kill()
      }
    }
  }
}

6.5 FS(文件系统)能力

6.5.1 架构

预览
源码
graph TB
    subgraph "FS 能力"
        A["fs/ (Service Definition)"]
        B["fs-local/ (Provider)"]
        C["tool-fs-search/ (Consumer)"]
        D["tool-fs-read/ (Consumer)"]
        E["tool-fs-write/ (Consumer)"]
    end

    subgraph "策略"
        F["fs-policy/"]
    end

    A --> B
    A --> C
    A --> D
    A --> E
    F --> A
graph TB
    subgraph "FS 能力"
        A["fs/ (Service Definition)"]
        B["fs-local/ (Provider)"]
        C["tool-fs-search/ (Consumer)"]
        D["tool-fs-read/ (Consumer)"]
        E["tool-fs-write/ (Consumer)"]
    end

    subgraph "策略"
        F["fs-policy/"]
    end

    A --> B
    A --> C
    A --> D
    A --> E
    F --> A

6.5.2 文件系统 Provider

// 来自 packages/fs/fs-local/src/index.ts(概念性)
class LocalFileSystemProvider implements FileSystemProvider {
  /** 读取文件 */
  async readBytes(path: string): Promise<Buffer> {
    return readFile(path)
  }
  
  /** 写入文件 */
  async writeBytes(path: string, data: Buffer): Promise<void> {
    await writeFile(path, data)
  }
  
  /** 列出目录 */
  async listDir(path: string): Promise<DirEntry[]> {
    return readdir(path, { withFileTypes: true })
  }
  
  /** 搜索文件 */
  async search(pattern: string, root: string): Promise<SearchResult[]> {
    // 使用 glob 模式匹配
  }
}

6.5.3 FS 策略

// 来自 packages/fs/fs-policy(概念性)
interface FileSystemPolicy {
  /** 检查路径是否可访问 */
  canAccess(path: string, mode: 'read' | 'write'): boolean
  
  /** 检查路径是否在允许的范围内 */
  isInScope(path: string): boolean
}

6.6 LSP(语言服务器)能力

6.6.1 架构

预览
源码
graph TB
    subgraph "LSP 能力"
        A["lsp/ (Service Definition)"]
        B["lsp-stdio/ (Provider)"]
        C["tool-lsp/ (Consumer)"]
    end

    A --> B
    C --> A
graph TB
    subgraph "LSP 能力"
        A["lsp/ (Service Definition)"]
        B["lsp-stdio/ (Provider)"]
        C["tool-lsp/ (Consumer)"]
    end

    A --> B
    C --> A

6.6.2 LSP Provider

// 来自 packages/lsp/lsp-stdio/src/index.ts(概念性)
class StdioLspProvider implements LspProvider {
  /** 启动 LSP 服务器 */
  async startServer(language: string): Promise<LspConnection> {
    const serverPath = this.resolveServerPath(language)
    const process = spawn(serverPath, ['--stdio'])
    
    return {
      async sendRequest(method, params) {
        // 发送 JSON-RPC 请求
        const request = { jsonrpc: '2.0', id: nextId++, method, params }
        process.stdin.write(JSON.stringify(request) + '\n')
        
        // 等待响应
        return waitForResponse(request.id)
      },
      
      async sendNotification(method, params) {
        const notification = { jsonrpc: '2.0', method, params }
        process.stdin.write(JSON.stringify(notification) + '\n')
      }
    }
  }
}

6.7 Web 能力

6.7.1 架构

预览
源码
graph TB
    subgraph "Web 能力"
        A["web/ (Service Definition)"]
        B["web-search/ (Provider)"]
        C["web-fetch/ (Provider)"]
        D["tool-web/ (Consumer)"]
    end

    A --> B
    A --> C
    D --> A
graph TB
    subgraph "Web 能力"
        A["web/ (Service Definition)"]
        B["web-search/ (Provider)"]
        C["web-fetch/ (Provider)"]
        D["tool-web/ (Consumer)"]
    end

    A --> B
    A --> C
    D --> A

6.7.2 Web 搜索 Provider

// 来自 packages/web/web-search/src/index.ts(概念性)
class WebSearchProvider implements WebSearchProvider {
  /** 搜索网页 */
  async search(query: string, options: SearchOptions): Promise<SearchResult[]> {
    const response = await fetch(`https://api.search.example/search`, {
      method: 'POST',
      body: JSON.stringify({ query, ...options })
    })
    
    return response.json()
  }
}

6.7.3 Web Fetch Provider

// 来自 packages/web/web-fetch/src/index.ts(概念性)
class WebFetchProvider implements WebFetchProvider {
  /** 获取网页内容 */
  async fetch(url: string, options: FetchOptions): Promise<FetchResult> {
    const response = await fetch(url)
    const content = await response.text()
    
    return {
      url,
      title: extractTitle(content),
      content: extractText(content),
      links: extractLinks(content)
    }
  }
}

6.8 Skill 能力

6.8.1 架构

预览
源码
graph TB
    subgraph "Skill 能力"
        A["skill/ (Service Definition)"]
        B["skill-local/ (Provider)"]
        C["tool-skill/ (Consumer)"]
    end

    A --> B
    C --> A
graph TB
    subgraph "Skill 能力"
        A["skill/ (Service Definition)"]
        B["skill-local/ (Provider)"]
        C["tool-skill/ (Consumer)"]
    end

    A --> B
    C --> A

6.8.2 SkillRegistry

// 来自 packages/skill/skill/src/index.ts
class SkillRegistry {
  /** 注册 Skill */
  register(skill: Skill): Disposable
  
  /** 获取 Skill */
  get(name: string): Skill | undefined
  
  /** 列出所有 Skill */
  list(): Skill[]
}

6.8.3 Skill 定义

interface Skill {
  /** Skill 名称 */
  name: string
  /** 描述 */
  description: string
  /** 执行函数 */
  execute(input: unknown, context: SkillContext): Promise<unknown>
}

6.9 工具能力总结

能力Service DefinitionProviderConsumer
Shellshell/shell-local/, shell-pwsh/tool-shell/
Subprocesssubprocess/subprocess-local/shell, terminal, code-runtime
FSfs/fs-local/tool-fs-search/, tool-fs-read/, tool-fs-write/
LSPlsp/lsp-stdio/tool-lsp/
Webweb/web-search/, web-fetch/tool-web/
Skillskill/skill-local/tool-skill/

6.10 添加新的能力插件

6.10.1 步骤

  1. 定义 Service 接口:声明能力的接口

  2. 实现 Provider:提供具体功能

  3. 创建 Consumer 工具:将能力暴露为模型工具

  4. 注册到 Profile:在 cordis.patch.yml 中配置

6.10.2 示例:添加图像处理能力

// 1. Service Definition
interface ImageProcessingService {
  resize(image: Buffer, width: number, height: number): Promise<Buffer>
  compress(image: Buffer, quality: number): Promise<Buffer>
}

// 2. Provider
class LocalImageProcessingProvider implements ImageProcessingService {
  async resize(image: Buffer, width: number, height: number): Promise<Buffer> {
    // 使用 sharp 或其他库处理
    return sharp(image).resize(width, height).toBuffer()
  }
}

// 3. Consumer 工具
ctx.tools.register({
  name: 'image_resize',
  description: 'Resize an image',
  parameters: {
    type: 'object',
    properties: {
      image_path: { type: 'string' },
      width: { type: 'number' },
      height: { type: 'number' }
    }
  },
  async execute(input) {
    const image = await ctx.fs.readBytes(input.image_path)
    const resized = await ctx.imageProcessing.resize(image, input.width, input.height)
    return { path: '/tmp/resized.jpg' }
  }
})

6.11 小结

概念一句话解释
ToolRuntime工具注册表,管理工具 schema 和执行
三角色模式Service Definition Provider Consumer
工具管道pre-execute → execute → post-execute
能力接缝可替换的能力设计模式
Shell命令执行能力
FS文件系统访问能力
LSP语言服务器协议能力
Web网页搜索和获取能力

下一步第七章:Agent 编排——深入理解 Subagent 委托、Worker Thread、Workflow 和 Preset 编排。

DeepSeek-Harness / 06-工具与数据类能力 0 0 iliuqi
2026-09-04T07:48:53.210224569Z 2026-09-04T07:57:15.367078387Z