Files
AutoGPT/autogpt_platform
Bently 905373a712 fix(frontend): use singleton Shiki highlighter for code syntax highlighting (#12144)
## Summary
Addresses SENTRY-1051: Shiki warning about multiple highlighter
instances.

## Problem
The `@streamdown/code` package creates a **new Shiki highlighter for
each language** encountered. When users view AI chat responses with code
blocks in multiple languages (JavaScript, Python, JSON, YAML, etc.),
this creates 10+ highlighter instances, triggering Shiki's warning:

> "10 instances have been created. Shiki is supposed to be used as a
singleton, consider refactoring your code to cache your highlighter
instance"

This causes memory bloat and performance degradation.

## Solution
Introduced a custom code highlighting plugin that properly implements
the singleton pattern:

### New files:
- `src/lib/shiki-highlighter.ts` - Singleton highlighter management
- `src/lib/streamdown-code-plugin.ts` - Drop-in replacement for
`@streamdown/code`

### Key features:
- **Single shared highlighter** - One instance serves all code blocks
- **Preloaded common languages** - JS, TS, Python, JSON, Bash, YAML,
etc.
- **Lazy loading** - Additional languages loaded on demand
- **Result caching** - Avoids re-highlighting identical code blocks

### Changes:
- Added `shiki` as direct dependency
- Updated `message.tsx` to use the new plugin

## Testing
- [ ] Verify code blocks render correctly in AI chat
- [ ] Confirm no Shiki singleton warnings in console
- [ ] Test with multiple languages in same conversation

## Related
- Linear: SENTRY-1051
- Sentry: Multiple Shiki instances warning

<!-- greptile_comment -->

<details><summary><h3>Greptile Summary</h3></summary>

Replaced `@streamdown/code` with a custom singleton-based Shiki
highlighter implementation to resolve memory bloat from creating
multiple highlighter instances per language. The new implementation
creates a single shared highlighter with preloaded common languages (JS,
TS, Python, JSON, etc.) and lazy-loads additional languages on demand.
Results are cached to avoid re-highlighting identical code blocks.

**Key changes:**
- Added `shiki` v3.21.0 as a direct dependency
- Created `shiki-highlighter.ts` with singleton pattern and language
management utilities
- Created `streamdown-code-plugin.ts` as a drop-in replacement for
`@streamdown/code`
- Updated `message.tsx` to import from the new plugin instead of
`@streamdown/code`

The implementation follows React best practices with async highlighting
and callback-based notifications. The cache key uses code length +
prefix/suffix for efficient lookups on large code blocks.
</details>


<details><summary><h3>Confidence Score: 4/5</h3></summary>

- Safe to merge with minor considerations for edge cases
- The implementation is solid with proper singleton pattern, caching,
and async handling. The code is well-structured and addresses the stated
problem. However, there's a subtle potential race condition in the
callback handling where multiple concurrent requests for the same cache
key could trigger duplicate highlight operations before the first
completes. The cache key generation using prefix/suffix could
theoretically cause false cache hits for large files with identical
prefixes and suffixes. Despite these edge cases, the implementation
should work correctly for the vast majority of use cases.
- No files require special attention
</details>


<details><summary><h3>Sequence Diagram</h3></summary>

```mermaid
sequenceDiagram
    participant UI as Streamdown Component
    participant Plugin as Custom Code Plugin
    participant Cache as Token Cache
    participant Singleton as Shiki Highlighter (Singleton)
    participant Callbacks as Pending Callbacks

    UI->>Plugin: highlight(code, lang)
    Plugin->>Cache: Check cache key
    
    alt Cache hit
        Cache-->>Plugin: Return cached result
        Plugin-->>UI: Return highlighted tokens
    else Cache miss
        Plugin->>Callbacks: Register callback
        Plugin->>Singleton: Get highlighter instance
        
        alt First call
            Singleton->>Singleton: Create highlighter with preloaded languages
        end
        
        Singleton-->>Plugin: Return highlighter
        
        alt Language not loaded
            Plugin->>Singleton: Load language dynamically
        end
        
        Plugin->>Singleton: codeToTokens(code, lang, themes)
        Singleton-->>Plugin: Return tokens
        Plugin->>Cache: Store result
        Plugin->>Callbacks: Notify all waiting callbacks
        Callbacks-->>UI: Async callback with result
    end
```
</details>


<sub>Last reviewed commit: 96c793b</sub>

<!-- greptile_other_comments_section -->

<!-- /greptile_comment -->
2026-02-17 12:15:53 +00:00
..

AutoGPT Platform

Welcome to the AutoGPT Platform - a powerful system for creating and running AI agents to solve business problems. This platform enables you to harness the power of artificial intelligence to automate tasks, analyze data, and generate insights for your organization.

Getting Started

Prerequisites

  • Docker
  • Docker Compose V2 (comes with Docker Desktop, or can be installed separately)

Running the System

To run the AutoGPT Platform, follow these steps:

  1. Clone this repository to your local machine and navigate to the autogpt_platform directory within the repository:

    git clone <https://github.com/Significant-Gravitas/AutoGPT.git | git@github.com:Significant-Gravitas/AutoGPT.git>
    cd AutoGPT/autogpt_platform
    
  2. Run the following command:

    cp .env.default .env
    

    This command will copy the .env.default file to .env. You can modify the .env file to add your own environment variables.

  3. Run the following command:

    docker compose up -d
    

    This command will start all the necessary backend services defined in the docker-compose.yml file in detached mode.

  4. After all the services are in ready state, open your browser and navigate to http://localhost:3000 to access the AutoGPT Platform frontend.

Running Just Core services

You can now run the following to enable just the core services.

# For help
make help

# Run just Supabase + Redis + RabbitMQ
make start-core

# Stop core services
make stop-core

# View logs from core services 
make logs-core

# Run formatting and linting for backend and frontend
make format

# Run migrations for backend database
make migrate

# Run backend server
make run-backend

# Run frontend development server
make run-frontend

Docker Compose Commands

Here are some useful Docker Compose commands for managing your AutoGPT Platform:

  • docker compose up -d: Start the services in detached mode.
  • docker compose stop: Stop the running services without removing them.
  • docker compose rm: Remove stopped service containers.
  • docker compose build: Build or rebuild services.
  • docker compose down: Stop and remove containers, networks, and volumes.
  • docker compose watch: Watch for changes in your services and automatically update them.

Sample Scenarios

Here are some common scenarios where you might use multiple Docker Compose commands:

  1. Updating and restarting a specific service:

    docker compose build api_srv
    docker compose up -d --no-deps api_srv
    

    This rebuilds the api_srv service and restarts it without affecting other services.

  2. Viewing logs for troubleshooting:

    docker compose logs -f api_srv ws_srv
    

    This shows and follows the logs for both api_srv and ws_srv services.

  3. Scaling a service for increased load:

    docker compose up -d --scale executor=3
    

    This scales the executor service to 3 instances to handle increased load.

  4. Stopping the entire system for maintenance:

    docker compose stop
    docker compose rm -f
    docker compose pull
    docker compose up -d
    

    This stops all services, removes containers, pulls the latest images, and restarts the system.

  5. Developing with live updates:

    docker compose watch
    

    This watches for changes in your code and automatically updates the relevant services.

  6. Checking the status of services:

    docker compose ps
    

    This shows the current status of all services defined in your docker-compose.yml file.

These scenarios demonstrate how to use Docker Compose commands in combination to manage your AutoGPT Platform effectively.

Persisting Data

To persist data for PostgreSQL and Redis, you can modify the docker-compose.yml file to add volumes. Here's how:

  1. Open the docker-compose.yml file in a text editor.

  2. Add volume configurations for PostgreSQL and Redis services:

    services:
      postgres:
        # ... other configurations ...
        volumes:
          - postgres_data:/var/lib/postgresql/data
    
      redis:
        # ... other configurations ...
        volumes:
          - redis_data:/data
    
    volumes:
      postgres_data:
      redis_data:
    
  3. Save the file and run docker compose up -d to apply the changes.

This configuration will create named volumes for PostgreSQL and Redis, ensuring that your data persists across container restarts.

API Client Generation

The platform includes scripts for generating and managing the API client:

  • pnpm fetch:openapi: Fetches the OpenAPI specification from the backend service (requires backend to be running on port 8006)
  • pnpm generate:api-client: Generates the TypeScript API client from the OpenAPI specification using Orval
  • pnpm generate:api: Runs both fetch and generate commands in sequence

Manual API Client Updates

If you need to update the API client after making changes to the backend API:

  1. Ensure the backend services are running:

    docker compose up -d
    
  2. Generate the updated API client:

    pnpm generate:api
    

This will fetch the latest OpenAPI specification and regenerate the TypeScript client code.