# ElizaOS Developer Update - July 28, 2025

## Core Framework

The ElizaOS framework has undergone significant architectural enhancements this week, focusing on stability, security, and developer experience.

### EventEmitter to EventTarget Migration

We've completed a major migration from Node.js's `EventEmitter` to Bun's native `EventTarget` API in core messaging components. This change improves runtime performance and compatibility:

```typescript
// Old approach with EventEmitter
class InternalMessageBus extends EventEmitter {
  emit(event: string, ...args: any[]): boolean {
    return super.emit(event, ...args);
  }
}

// New approach with EventTarget
class InternalMessageBus extends EventTarget {
  dispatch(eventName: string, detail?: unknown): boolean {
    const event = new CustomEvent(eventName, { detail });
    return this.dispatchEvent(event);
  }
}
```

This change affects both the `InternalMessageBus` in the server package and the `SimpleMigrationAgent` in the CLI, with full backward compatibility maintained. We've added comprehensive test coverage to ensure method chaining and event handling work as expected.

### Service Types and Interface Standardization

We've implemented a standardized service interface system with a new `getServicesByType()` method. This allows plugins to register multiple services of the same type and have them discovered consistently:

```typescript
// Register a browser service
runtime.registerService({
  name: "chrome-browser",
  type: "browser",
  capabilities: ["javascript", "cookies"],
  browse: async (url) => { /* implementation */ }
});

// Later retrieve all browser services
const browsers = runtime.getServicesByType<BrowserService>("browser");
const supportedBrowsers = browsers.filter(b => 
  b.capabilities.includes("javascript"));
```

This enables more flexible plugin compositions and better service discovery.

### Local-First Module Resolution

We've enhanced the `ModuleLoader` with consistent local-first guarantees for module resolution, ensuring plugins and dependencies load from the correct locations across package managers and installation methods:

```typescript
const server = await moduleLoader.loadModule<ElizaServer>({
  packageName: "@elizaos/server",
  resolveOrder: ["local", "global"],
  fallbackPath: path.join(__dirname, "../../../server/dist/index.js")
});
```

This fixes critical issues with module path resolution that were causing inconsistencies between development and production environments.

## New Features

### XML Prompt Migration

All JSON-based prompts have been migrated to XML format across the codebase to enhance the reliability of responses from Large Language Models:

```typescript
// Old JSON format
const prompt = `
{
  "thoughts": "Consider user's request carefully",
  "actions": ["REPLY", "SEARCH"],
  "text": "I'll help you with that!"
}`;

// New XML format
const prompt = `
<response>
  <thought>Consider user's request carefully</thought>
  <actions>REPLY,SEARCH</actions>
  <text>I'll help you with that!</text>
</response>`;
```

This change affects all core entities and the bootstrap plugin, with particular improvements to action handlers in the plugin-bootstrap package.

### Action Chaining

We've implemented a powerful action chaining capability that allows agents to plan and execute multiple actions in sequence:

```typescript
// Example of action chaining in plugin code
export const myAction: ActionHandler = async (context, runtime, state) => {
  // First action result stored in state
  const result1 = await doSomething(context);
  state.set('firstResult', result1);
  
  // Second action references the first result
  const result2 = await doSomethingElse(context, state.get('firstResult'));
  
  // Chain multiple actions with a callback to user
  await state.callback("Processing your request...");
  
  return {
    success: true,
    result: `Completed with ${result2}`
  };
};
```

This enables more complex, stateful agent behaviors with intermediate user feedback.

### Browser Extension Support

Development is underway on an Eliza browser extension to overcome automation limitations with puppeteer/playwright. This approach:

- Simplifies browser automation without Google Cloud API dependencies
- Overcomes authentication challenges in browser integration
- Provides more stable interaction with web content

In parallel, we're planning to implement a core `/extension` package that will expose global services to all plugins.

## Bug Fixes

### Critical SQL Plugin Fixes

Fixed a JSON string handling issue in the SQL base plugin that was causing failures when storing complex objects:

```typescript
// Before: Raw objects were implicitly stringified
await sql`INSERT INTO memories VALUES (${content}::jsonb)`;

// After: Explicit JSON.stringify for consistent behavior
await sql`INSERT INTO memories VALUES (${JSON.stringify(content)}::jsonb)`;
```

This change ensures consistent handling of objects and arrays in database operations.

### Windows Compatibility Improvements

Multiple Windows-specific fixes have been implemented:

1. Resolved path normalization issues in plugin loading on Windows
2. Fixed localhost resolution problems with the dev command
3. Improved error handling for Windows-specific file operations

Windows users should now have a much more reliable experience across all CLI commands.

### CLI Enhancement

Fixed a critical bug where `elizaos update` was creating unwanted project files (package.json, node_modules) when run outside of ElizaOS project directories. The command now properly checks if it's in a project context before attempting updates.

## API Changes

### Enhanced Module Loader API

The ModuleLoader API has been reworked to provide more consistent module resolution:

```typescript
import { ModuleLoader } from '@elizaos/cli/utils/module-loader';

// New API with explicit loading strategies
const loader = new ModuleLoader();
const result = await loader.loadModule({
  packageName: 'package-name',
  resolveOrder: ['local', 'global', 'path'],
  localDirectory: process.cwd(),
  fallbackPath: '/optional/fallback/path.js'
});
```

This API is used internally by the CLI but may be useful for plugins that need to dynamically load dependencies.

### Service Types Interface

New standardized service interfaces have been added to the core package:

```typescript
// Example service interface definition
export interface BrowserService extends Service {
  type: 'browser';
  capabilities: string[];
  browse(url: string, options?: BrowseOptions): Promise<BrowseResult>;
  screenshot(options?: ScreenshotOptions): Promise<Buffer>;
}

// Usage
const browsers = runtime.getServicesByType<BrowserService>('browser');
```

Plugins can now implement these standard interfaces to ensure compatibility and discoverability.

## Social Media Integrations

### Twitter Plugin Updates

Updated the default Eliza character with new examples to support Twitter posting functionality:

```typescript
// Added to default character examples
{
  role: "example",
  content: {
    input: "Can you post a tweet about the weather?",
    response: {
      thought: "I should create a friendly, engaging tweet about the weather.",
      actions: ["POST"],
      providers: ["TWITTER"],
      text: "The sun is shining today! ☀️ Perfect weather for a walk or outdoor activity. What's the weather like where you are? #Weather #SunnyDay",
      post: {
        text: "The sun is shining today! ☀️ Perfect weather for a walk or outdoor activity. What's the weather like where you are? #Weather #SunnyDay",
        platform: "twitter"
      }
    }
  }
}
```

Additionally, the Twitter plugin documentation has been updated to provide more clarity on API requirements and authentication methods.

## Model Provider Updates

### Provider Selection Refinements

Refined the LLM provider selection prompt to reduce unnecessary provider activation and improve reply speed:

```xml
<providers>
  <!-- Only included when needed for specific capabilities -->
  <!-- Example: KNOWLEDGE only when search/retrieval is required -->
</providers>
```

The prompt now explicitly asks the LLM to be selective about which providers are chosen, avoiding unnecessary provider activations.

### Ollama Integration Improvements

Made Ollama plugin conditional based on `OLLAMA_API_ENDPOINT` configuration rather than being included by default:

```typescript
// Before: Always included Ollama
plugins: ["bootstrap", "@elizaos/plugin-ollama"]

// After: Conditional inclusion based on environment
plugins: [
  "bootstrap", 
  ...(process.env.OLLAMA_API_ENDPOINT ? ["@elizaos/plugin-ollama"] : [])
]
```

This change reduces unnecessary dependencies and improves startup time when Ollama is not being used.

## Breaking Changes

### V1 to V2 Migration Considerations

Added automatic V1 → V2 character conversion during JSON import for seamless backward compatibility:

```typescript
// Example conversion from V1 to V2 format
const convertV1ToV2 = (v1Character: any): Character => {
  return {
    name: v1Character.name,
    description: v1Character.description || "",
    avatar: v1Character.baseImg || "",
    // Map V1 plugins to V2 equivalent plugins
    plugins: mapPluginsToV2Format(v1Character.providers || []),
    // Convert other properties...
  };
};
```

This simplifies migrating from V1 to V2 character formats and includes plugin matching to map old provider names to new plugin names.

### Plugin Interface Changes

Action handlers now must return `Promise<ActionResult>` for proper type compliance:

```typescript
// Before (incorrect)
const myAction: ActionHandler = async (context, runtime) => {
  return { success: true }; 
};

// After (correct)
const myAction: ActionHandler = async (context, runtime): Promise<ActionResult> => {
  return { success: true, result: "Completed successfully" };
};
```

This ensures strict type safety throughout the action chain and improves error handling.

---

For more information, see the relevant PRs:
- [#5609](https://github.com/elizaOS/eliza/pull/5609): Migrate from EventEmitter to Bun native EventTarget API
- [#5565](https://github.com/elizaOS/eliza/pull/5565): Implement service types and standardized interfaces
- [#5623](https://github.com/elizaOS/eliza/pull/5623): Refactor JSON prompts to XML format
- [#5436](https://github.com/elizaOS/eliza/pull/5436): Add action chaining
- [#5628](https://github.com/elizaOS/eliza/pull/5628): Fix JSON string handling in SQL base