Kode-cli/docs/develop/tools-system.md
CrazyBoyM 7a3c4a7baa Refactor project structure and update documentation
- Update project branding from claude-cli to Kode
- Reorganize documentation with new development guides
- Add CONTRIBUTING.md and Chinese README
- Remove worktree_merge command and relocate system-design.md
- Update dependencies and package configuration
- Improve custom commands service with better error handling
- Clean up storage utilities and debug logging
2025-08-11 21:31:18 +08:00

12 KiB

Tool System Documentation

Overview

The Tool System is the heart of Kode's functionality, providing a standardized interface for all operations that the AI can perform. Every capability - from reading files to executing commands - is implemented as a Tool.

Tool Interface

Core Tool Class

export abstract class Tool {
  abstract name: string
  abstract description: string
  abstract inputSchema: z.ZodTypeAny
  
  // Permission checking
  abstract needsPermissions(input: unknown): boolean
  
  // Input validation
  validateInput(input: unknown): unknown
  
  // Main execution method
  abstract call(
    input: unknown, 
    context: ToolUseContext
  ): AsyncGenerator<ToolCallEvent>
  
  // Format results for AI
  abstract renderResultForAssistant(
    input: unknown,
    result: unknown
  ): string
}

Tool Lifecycle

1. Tool Registration
   ↓
2. AI Requests Tool Use
   ↓
3. Input Validation (Zod Schema)
   ↓
4. Permission Check
   ↓
5. User Approval (if needed)
   ↓
6. Tool Execution
   ↓
7. Progress Updates (via generator)
   ↓
8. Result Formatting
   ↓
9. Return to AI

Tool Categories

1. File Operation Tools

FileReadTool

  • Purpose: Read file contents with encoding detection
  • Key Features:
    • Automatic encoding detection (UTF-8, UTF-16, etc.)
    • Binary file handling
    • Large file support with offset/limit
    • Freshness tracking to detect external changes
  • Security: Checks file access permissions

FileEditTool

  • Purpose: Make precise edits to existing files
  • Key Features:
    • String replacement with exact matching
  • File freshness validation
    • Prevents editing without reading first
    • Multiple edit support (MultiEditTool)
  • Security: Requires file write permissions

FileWriteTool

  • Purpose: Create or overwrite entire files
  • Key Features:
    • Full file replacement
    • Directory creation if needed
    • Encoding specification
  • Security: Requires explicit write permissions

NotebookEditTool

  • Purpose: Edit Jupyter notebook cells
  • Key Features:
    • Cell-level operations (replace, insert, delete)
    • Code and markdown cell support
    • Preserves notebook metadata

2. Search and Discovery Tools

GrepTool

  • Purpose: Search file contents using regular expressions
  • Key Features:
    • Ripgrep integration for speed
    • Multiple output modes (content, files, count)
    • Context lines support (-A, -B, -C)
    • File type filtering
  • Implementation: Uses ripgrep binary for performance

GlobTool

  • Purpose: Find files by name patterns
  • Key Features:
    • Glob pattern matching
    • Hidden file support
    • Result sorting by modification time
    • Symlink following options

LSTool

  • Purpose: List directory contents
  • Key Features:
    • Recursive listing
    • Hidden file display
    • Size and permission information
    • Pattern filtering

3. System Execution Tools

BashTool

  • Purpose: Execute shell commands
  • Key Features:
    • Persistent shell sessions
    • Working directory management
    • Environment variable handling
    • Timeout support (default 2 minutes)
    • Output streaming
  • Security:
    • Command approval in safe mode
    • Restricted commands blacklist
    • Environment sanitization

4. AI Enhancement Tools

TaskTool (Architect)

  • Purpose: Launch sub-agents for complex tasks
  • Key Features:
    • Autonomous multi-step execution
    • Specialized agent types
    • Context preservation
    • Parallel task execution
  • Use Cases: Complex refactoring, system design

ThinkTool

  • Purpose: Allow AI to reason through problems
  • Key Features:
    • Structured thinking blocks
    • Problem decomposition
    • Hidden from user output
  • Implementation: Special message formatting

TodoWriteTool

  • Purpose: Task management and tracking
  • Key Features:
    • Persistent todo lists
    • Status tracking (pending, in_progress, completed)
    • Progress visualization
    • Automatic task breakdown

5. External Integration Tools

MCPTool

  • Purpose: Bridge to Model Context Protocol servers
  • Key Features:
    • Dynamic tool discovery
    • Protocol translation
    • Server lifecycle management
    • Error propagation
  • Implementation: JSON-RPC over stdio/SSE

WebFetchTool

  • Purpose: Fetch and process web content
  • Key Features:
    • HTML to markdown conversion
    • Content extraction
    • Caching support
    • Redirect handling

Tool Implementation Guide

Creating a New Tool

export class MyCustomTool extends Tool {
  name = 'my_custom_tool'
  description = 'Does something custom'
  
  inputSchema = z.object({
    param1: z.string(),
    param2: z.number().optional()
  })
  
  needsPermissions(input: unknown): boolean {
    // Return true if this operation needs user approval
    return true
  }
  
  async *call(
    input: z.infer<typeof this.inputSchema>,
    context: ToolUseContext
  ): AsyncGenerator<ToolCallEvent> {
    // Yield progress updates
    yield {
      type: 'progress',
      message: 'Starting operation...'
    }
    
    // Check abort signal
    if (context.abortSignal.aborted) {
      throw new Error('Operation cancelled')
    }
    
    // Perform operation
    const result = await this.performOperation(input)
    
    // Yield final result
    yield {
      type: 'result',
      result: result
    }
  }
  
  renderResultForAssistant(input: unknown, result: unknown): string {
    // Format result for AI consumption
    return `Operation completed: ${JSON.stringify(result)}`
  }
}

Tool Registration

// In tools.ts
export async function getTools(): Promise<Tool[]> {
  const tools = [
    new FileReadTool(),
    new FileEditTool(),
    new BashTool(),
    new MyCustomTool(), // Add your tool here
    // ... other tools
  ]
  
  // Add MCP tools dynamically
  const mcpTools = await getMCPTools()
  tools.push(...mcpTools)
  
  return tools
}

Permission System Integration

Permission Types

  1. No Permission Required: Read-only operations
  2. Session Permission: Temporary approval for current session
  3. Persistent Permission: Saved approval for future use
  4. Always Ask: Critical operations requiring explicit approval

Permission Flow

async function checkPermissionsAndCallTool(
  tool: Tool,
  input: unknown,
  context: ToolUseContext
): Promise<ToolResult> {
  if (!tool.needsPermissions(input)) {
    // No permission needed
    return await tool.call(input, context)
  }
  
  const permission = await requestPermission({
    tool: tool.name,
    operation: describeOperation(input)
  })
  
  if (permission.approved) {
    if (permission.saveForSession) {
      saveSessionPermission(tool.name, input)
    }
    return await tool.call(input, context)
  } else {
    throw new PermissionDeniedError()
  }
}

Tool Context

ToolUseContext Interface

interface ToolUseContext {
  // Cancellation support
  abortSignal: AbortSignal
  
  // Current working directory
  cwd: string
  
  // Permission helpers
  hasPermission: (operation: string) => boolean
  requestPermission: (operation: string) => Promise<boolean>
  
  // Logging and metrics
  logEvent: (event: string, data: any) => void
  
  // UI helpers
  showProgress: (message: string) => void
  
  // Configuration access
  config: Configuration
}

Tool Best Practices

1. Input Validation

  • Use Zod schemas for type-safe validation
  • Provide clear error messages for invalid input
  • Validate file paths and command arguments

2. Error Handling

  • Throw descriptive errors with actionable messages
  • Handle common failure cases gracefully
  • Provide recovery suggestions

3. Progress Reporting

  • Yield progress updates for long operations
  • Include percentage or step information
  • Update at reasonable intervals (not too frequent)

4. Cancellation Support

  • Check abort signal regularly
  • Clean up resources on cancellation
  • Save partial progress when possible

5. Result Formatting

  • Provide human-readable output for users
  • Include structured data for AI parsing
  • Summarize large results appropriately

6. Security Considerations

  • Always validate and sanitize inputs
  • Check permissions before operations
  • Limit resource consumption
  • Prevent path traversal attacks

Tool Testing

Unit Testing

describe('MyCustomTool', () => {
  it('should validate input correctly', () => {
    const tool = new MyCustomTool()
    const validInput = { param1: 'test' }
    expect(() => tool.validateInput(validInput)).not.toThrow()
  })
  
  it('should handle cancellation', async () => {
    const tool = new MyCustomTool()
    const abortController = new AbortController()
    abortController.abort()
    
    const context = {
      abortSignal: abortController.signal,
      // ... other context
    }
    
    await expect(
      tool.call(input, context)
    ).rejects.toThrow('Operation cancelled')
  })
})

Integration Testing

it('should integrate with permission system', async () => {
  const tool = new MyCustomTool()
  const context = createTestContext({
    permissions: ['my_custom_tool']
  })
  
  const result = await tool.call(input, context)
  expect(result).toBeDefined()
})

Advanced Tool Patterns

Composite Tools

Tools that orchestrate multiple other tools:

class CompositeAnalysisTool extends Tool {
  async *call(input, context) {
    // First, search for files
    const files = await this.globTool.call(
      { pattern: input.pattern },
      context
    )
    
    // Then grep each file
    for (const file of files) {
      const results = await this.grepTool.call(
        { file, pattern: input.search },
        context
      )
      yield { type: 'progress', file, results }
    }
  }
}

Streaming Tools

Tools that process data incrementally:

class StreamingFileTool extends Tool {
  async *call(input, context) {
    const stream = createReadStream(input.file)
    
    for await (const chunk of stream) {
      const processed = processChunk(chunk)
      yield { type: 'partial', data: processed }
      
      if (context.abortSignal.aborted) break
    }
    
    yield { type: 'complete' }
  }
}

Stateful Tools

Tools that maintain state across calls:

class SessionTool extends Tool {
  private session: Session
  
  async *call(input, context) {
    if (!this.session) {
      this.session = await createSession()
    }
    
    const result = await this.session.execute(input.command)
    yield { type: 'result', result }
  }
  
  cleanup() {
    this.session?.close()
  }
}

Tool Metrics and Monitoring

Performance Tracking

class InstrumentedTool extends Tool {
  async *call(input, context) {
    const startTime = Date.now()
    
    try {
      yield* super.call(input, context)
    } finally {
      const duration = Date.now() - startTime
      context.logEvent('tool_execution', {
        tool: this.name,
        duration,
        success: true
      })
    }
  }
}

Error Tracking

class MonitoredTool extends Tool {
  async *call(input, context) {
    try {
      yield* super.call(input, context)
    } catch (error) {
      context.logEvent('tool_error', {
        tool: this.name,
        error: error.message,
        stack: error.stack
      })
      throw error
    }
  }
}

The Tool System provides the foundation for all of Kode's capabilities, enabling safe, efficient, and extensible operations while maintaining a consistent interface for both AI and human users.