Skip to content

sub(#250) Phase 1: ToolResultRenderer extension point and default renderers #273

@mmogr

Description

@mmogr

Summary

Add a ToolResultRenderer extension point to the tool registry so each tool can declare how its results should be rendered in the chat UI. Implement default renderers for built-in tools.

Context

Currently, all tool results are rendered as plain JSON text in the chat UI. The summarizeToolResult function in agentLoop.ts simply stringifies res.data and truncates it. There's no per-tool rendering — a web search result, a file listing, and a model info response all look the same.

Proposed Changes

1. Define ToolResultRenderer interface

// src/services/tools/types.ts

export interface ToolResultRenderer {
  /** Render tool result into a React node for display in chat */
  renderResult(data: unknown, toolName: string): React.ReactNode;
  /** Optional: render a compact inline summary (for collapsed view) */
  renderSummary?(data: unknown, toolName: string): string;
}

2. Extend ToolRegistration to accept a renderer

// src/services/tools/types.ts - extend existing ToolRegistration
export interface ToolRegistration {
  // ... existing fields ...
  renderer?: ToolResultRenderer;
}

3. Extend ToolRegistry to store/retrieve renderers

// src/services/tools/registry.ts

class ToolRegistry {
  // ... existing code ...
  
  getRenderer(toolName: string): ToolResultRenderer | undefined {
    return this.tools.get(toolName)?.renderer;
  }
}

4. Implement default renderers for built-in tools

Create renderers for the core tools:

Tool Renderer
web_search Card list with title, URL, snippet
fetch_url Content preview with domain badge
read_file Syntax-highlighted code block with filename header
list_directory File tree view
execute_command Terminal-style output block with exit code badge
Generic fallback Pretty-printed JSON with collapsible sections

5. Create src/services/tools/renderers/ directory

src/services/tools/renderers/
├── index.ts              # Re-exports all renderers
├── FallbackRenderer.tsx  # Generic JSON renderer (default)
├── WebSearchRenderer.tsx # web_search results
├── FileRenderer.tsx      # read_file results  
├── CommandRenderer.tsx   # execute_command results
└── DirectoryRenderer.tsx # list_directory results

Files to Create/Modify

File Change
src/services/tools/types.ts Add ToolResultRenderer interface
src/services/tools/registry.ts Add getRenderer() method
src/services/tools/renderers/ Create renderer directory with implementations
src/services/tools/builtinTools.ts (or equivalent) Attach renderers when registering built-in tools

Acceptance Criteria

  • ToolResultRenderer interface defined with renderResult and optional renderSummary
  • ToolRegistration extended with optional renderer field
  • ToolRegistry.getRenderer() method available
  • At least 3 built-in tool renderers implemented (web_search, read_file, execute_command)
  • Fallback renderer handles any unknown tool result as pretty-printed JSON
  • Renderers are tree-shakeable (lazy-loaded or conditionally imported)
  • Unit tests for each renderer with sample tool result data

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions