# ElizaOS Developer Update - July 18, 2025

## 1. Core Framework

This week marked significant architectural advancements for ElizaOS with the introduction of standardized service types and interfaces, providing greater modularity and abstraction in the plugin ecosystem.

### Service Types Implementation
The long-awaited service types system has been implemented in PR #5565, introducing a powerful `getServicesByType()` method that allows plugins to discover and interact with services based on their capabilities rather than specific implementations. This architectural change enables:
- Multiple providers for the same service type
- More flexible service discovery
- Improved testability with mock service implementations

### Event System Modernization
The platform's event system has been completely refactored, migrating from Node.js EventEmitter to Bun's native EventTarget API (PR #5609). This change:
- Improves performance and type safety
- Reduces external dependencies
- Maintains backward compatibility through adapter methods
- Adds comprehensive test coverage for compatibility (PR #5613)

### Action Chaining System
A powerful new action chaining mechanism has been introduced in PR #5436, enabling sequential action execution with state management:

```typescript
// Define a chain of actions
const actionChain = [
  {
    type: "getWeather",
    params: { location: "New York" }
  },
  {
    type: "formatReport",
    params: { template: "daily" }
  }
];

// Access previous action result in state
const formatReport = async (params, state) => {
  const weatherData = state.actionResults.getWeather;
  // Format using data from previous action...
};
```

## 2. New Features

### Auto-Resizing ChatInput
The ChatInput component now dynamically adjusts its height based on content, improving user experience (PR #5546):

```typescript
// Implementation highlights
const resizeTextarea = () => {
  if (!textareaRef.current) return;
  
  textareaRef.current.style.height = 'auto';
  const scrollHeight = textareaRef.current.scrollHeight;
  
  // Apply with max height constraint
  const newHeight = Math.min(scrollHeight, MAX_HEIGHT);
  textareaRef.current.style.height = `${newHeight}px`;
};

// Auto-resize on input
const handleInput = (e) => {
  resizeTextarea();
  onChange?.(e);
};
```

### V1 to V2 Character Conversion
A seamless character conversion system was implemented in PR #5536, enabling automatic upgrading of V1 character configurations during import:

```typescript
// Usage in character-form.tsx
const { convertCharacterIfNeeded } = useConvertCharacter();

const handleFileUpload = async (file) => {
  try {
    const text = await file.text();
    const characterData = JSON.parse(text);
    
    // Automatically detects and converts V1 format to V2
    const convertedData = convertCharacterIfNeeded(characterData);
    
    // Rest of import logic...
  } catch (error) {
    toast.error(`Error importing character: ${error.message}`);
  }
};
```

### Image Generation Action
The Agent pipeline now supports generating images based on conversational context (PR #5446):

```typescript
// In plugin-bootstrap/src/actions/imageGeneration.ts
export const generateImageAction: Action = {
  name: "GENERATE_IMAGE",
  description: "Generates an image based on the conversation",
  execute: async (params, runtime) => {
    const { prompt } = params;
    
    try {
      const result = await runtime.useModel(ModelType.IMAGE, {
        prompt,
        model: "dall-e-3",
      });
      
      return {
        success: true,
        result: {
          imageURL: result.url,
          altText: prompt
        }
      };
    } catch (error) {
      return { success: false, error: error.message };
    }
  }
};
```

### Backend-Only Plugin Template
A streamlined `plugin-quick-starter` template was added for developers creating backend-only plugins, reducing boilerplate and complexity compared to the full-stack template (PR #5589).

## 3. Bug Fixes

### MessageBusService Cache Issue
Fixed a critical failure where agents couldn't reload channel information after restart, preventing proper communication in group chats (found in Discord discussions):

```typescript
// Root cause: Channel participation not correctly reloaded after restart
// Fix in MessageBusService ensures channels are always correctly resubscribed
this.adapter.on('agentStart', async (agentId: string) => {
  const participations = await this.getChannelParticipations(agentId);
  await Promise.all(participations.map(async channel => {
    await this.subscribeAgentToChannel(agentId, channel.id);
  }));
});
```

### Windows Plugin Loading
Resolved persistent issues with plugin loading on Windows (PR #5416, PR #5437), fixing path normalization issues that prevented plugins from loading correctly:

```typescript
// Before
const pluginPath = path.join(dir, pluginName);

// After - Normalize paths for cross-platform compatibility
const pluginPath = path.normalize(path.join(dir, pluginName));
```

### EventTarget Migration Fixes
Fixed method chaining support that was broken during the EventEmitter to EventTarget migration (PR #5612):

```typescript
// Before
on(event: string, handler: Function): void {
  this.addEventListener(event, handler);
}

// After - Fixed to return 'this' for chaining
on(event: string, handler: Function): this {
  this.addEventListener(event, handler);
  return this;
}
```

### CLI Stability Improvements
Multiple fixes for CLI reliability were implemented:
- Fixed dev server not shutting down gracefully on Ctrl+C (PR #5562)
- Added auto-build support for `elizaos start` command (PR #5504)
- Fixed path resolution issues for globally installed CLI (PR #5479)

## 4. API Changes

### Service Types API
New service type interfaces have been standardized providing consistent patterns for service discovery and interaction:

```typescript
// Get all services of a specific type
const searchServices = runtime.getServicesByType<WebSearchService>('web-search');

// Use the first available service of a type
const pdfService = runtime.getServicesByType<PdfService>('pdf')[0];
if (pdfService) {
  const content = await pdfService.extractText(fileUrl);
}
```

### Event Handling Updates
The platform now uses the standard web EventTarget API for events:

```typescript
// Old EventEmitter pattern (still supported)
bus.on('message', handleMessage);
bus.removeListener('message', handleMessage);

// New EventTarget pattern (recommended)
bus.addEventListener('message', handleMessage);
bus.removeEventListener('message', handleMessage);

// Custom event dispatching
bus.dispatchEvent(new CustomEvent('message', { 
  detail: { content, sender }
}));
```

### WebSocket API Clarification
Documentation was updated to match the actual implementation, addressing a discrepancy discovered in Discord discussions around channel creation parameters:

```typescript
// Correct format for channel creation
socket.emit('createChannel', {
  serverId: 'server-123', // Not server_id as previously documented
  name: 'my-channel',
  private: true
});
```

## 5. Social Media Integrations

### Twitter Account Suspension
The ElizaOS Twitter accounts have been suspended for approximately one month, as discussed extensively in Discord. The team is actively working with Twitter to recover the accounts rather than creating new ones, as this approach has the best chance of preserving the project's social media presence.

### Twitter Plugin Updates
The Twitter plugin was updated to version 1.2.16 with the following improvements:
- New discovery service for finding and connecting with relevant accounts
- Fixed auto-posting issues that were causing content duplication
- Implemented a weighted discovery algorithm for better content relevance
- Addressed rate limiting errors (issue #38) through improved request batching

## 6. Model Provider Updates

### Local Model Handling
The platform has been updated to prioritize Ollama over legacy local-ai implementations:
- The `@elizaos/plugin-ollama` package now automatically maps from legacy `llama_local` provider references
- Environment-based conditional loading of Ollama has been implemented to reduce unnecessary dependencies
- Installation processes have been streamlined with improved error handling and logging

Code example for the improved model selection and fallback logic:
```typescript
// Updated character configuration logic
export function getElizaCharacter() {
  const plugins = ["@elizaos/plugin-bootstrap", "@elizaos/plugin-sql"];
  
  // Only include Ollama if specifically configured
  if (process.env.OLLAMA_API_ENDPOINT) {
    plugins.push("@elizaos/plugin-ollama");
  }
  
  // Add model plugins based on API keys
  if (process.env.OPENAI_API_KEY) {
    plugins.push("@elizaos/plugin-openai");
  } else if (process.env.ANTHROPIC_API_KEY) {
    plugins.push("@elizaos/plugin-anthropic");
  }
  
  return { /* character config */ };
}
```

### Prompt Improvements
Enhanced LLM prompts to reduce unnecessary provider usage and improve reply speed:
- More explicit guidance for code block formatting in LLM replies
- Refined provider selection to avoid selecting KNOWLEDGE provider when unnecessary
- Clarified exclusivity requirements for the IGNORE action

## 7. Breaking Changes

### Migration from EventEmitter to EventTarget
While backward compatibility is maintained, developers should be aware of the following differences when migrating code:
- EventTarget uses `addEventListener`/`removeEventListener` rather than `on`/`off`/`removeListener`
- Event handlers receive an Event object with data in the `detail` property
- Custom events must be dispatched using the `CustomEvent` constructor

Migration example:
```typescript
// Old code
myService.on('data', (data) => {
  console.log(data);
});

// New code
myService.addEventListener('data', (event) => {
  console.log(event.detail);
});
```

### CLI Command Updates
The `--dir` flag has been removed from the `create` command to simplify the interface (PR #5443). Projects are now always created in the current directory:

```bash
# Old usage (no longer supported)
elizaos create myProject --dir ./projects

# New usage
cd ./projects
elizaos create myProject
```

### Plugin Structure Changes
Plugins now require standardized service type declarations to be properly discoverable:
```typescript
// Required structure for services
export class MySearchService implements WebSearchService {
  readonly type = 'web-search'; // Must match the interface type
  
  async search(query: string): Promise<SearchResult[]> {
    // Implementation
  }
}
```

The Core team recommends testing all custom plugins, especially those defining services, to ensure compatibility with these new patterns.