Skip to content

feat: Add image support for vision-capable models #110

Description

@CarGDev

Summary

Enable users to include images in conversations for vision-capable models.

Why It's Needed

  • UI/UX Feedback: "What's wrong with this screenshot?"
  • Diagram Understanding: Analyze architecture diagrams
  • Error Screenshots: Debug from error screenshots
  • Design Implementation: "Implement this design mockup"
  • Competitor Parity: Both OpenCode and Claude Code support images

Features

Image Input Methods

  1. File Path: @screenshot.png or --files image.jpg
  2. Paste from Clipboard: Ctrl+V in TUI
  3. Drag and Drop: Drop image file onto TUI
  4. URL: @https://example.com/image.png

Supported Formats

  • PNG, JPG, JPEG, GIF, WebP
  • Max size: 20MB (configurable)
  • Auto-resize if too large

Implementation

Message Format

interface ImageMessage {
  role: "user"
  content: [
    { type: "text", text: "What's in this image?" },
    { 
      type: "image_url", 
      image_url: { 
        url: "data:image/png;base64,iVBORw0KGgo...",
        detail: "auto"  // or "low" | "high"
      } 
    }
  ]
}

Image Processing

async function processImage(input: string): Promise<ImageContent> {
  let buffer: Buffer
  
  if (input.startsWith("http")) {
    // Fetch from URL
    const response = await fetch(input)
    buffer = Buffer.from(await response.arrayBuffer())
  } else {
    // Read from file
    buffer = await readFile(input)
  }
  
  // Resize if too large
  if (buffer.length > MAX_SIZE) {
    buffer = await resizeImage(buffer, MAX_DIMENSIONS)
  }
  
  const base64 = buffer.toString("base64")
  const mimeType = detectMimeType(buffer)
  
  return {
    type: "image_url",
    image_url: {
      url: \`data:\${mimeType};base64,\${base64}\`
    }
  }
}

Clipboard Support (TUI)

// On Ctrl+V, check for image in clipboard
import clipboard from "clipboardy"

async function handlePaste() {
  // Check for image data
  const imageData = await getClipboardImage()
  if (imageData) {
    addImageToContext(imageData)
    showImagePreview(imageData)
  }
}

Provider Support

Provider Vision Support
Copilot (GPT-4o)
Copilot (GPT-4)
Copilot (Claude)
Ollama (llava)
Ollama (bakllava)
Ollama (others)

TUI Display

┌─────────────────────────────────────┐
│ You:                                │
│ What's wrong with this UI?          │
│                                     │
│ ┌─────────────┐                     │
│ │ 📷 image.png │                    │
│ │   (256x128)  │                    │
│ └─────────────┘                     │
└─────────────────────────────────────┘

Configuration

{
  "images": {
    "enabled": true,
    "maxSize": 20971520,
    "autoResize": true,
    "maxDimensions": 2048,
    "detail": "auto"
  }
}

Acceptance Criteria

  • Support @image.png syntax
  • Support --files with images
  • Clipboard paste support (Ctrl+V)
  • Auto-resize large images
  • Image preview in TUI
  • Provider capability detection
  • Graceful fallback if vision not supported
  • Multiple images per message

Effort Estimate

3 days

Dependencies

  • sharp (image processing)
  • clipboardy (clipboard access)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions