This plugin provides a dependency injection system for Eliza plugins.
Dependency Injection is a design pattern that allows you to inject dependencies into a class or function. This pattern is useful for decoupling components and making your code more modular and testable.
To enable Dependency Injection in your Eliza plugin, you need to install the @elizaos-plugins/plugin-di plugin and add it to the postProcessors field in your character configuration.
# Install the plugin
npx elizaos plugins add @elizaos-plugins/plugin-di// character.json
{
"postProcessors": [
"@elizaos-plugins/plugin-di"
]
}To ensure all your plugins are using the same instance of the container, you can use the global container provided by this plugin.
And use peerDependencies instead of dependencies in your plugin package.json to avoid version conflicts and use the same version of the @elizaos-plugins/plugin-di plugin.
// package.json
{
"peerDependencies": {
"@elizaos-plugins/plugin-di": "workspace:*"
}
}import { globalContainer } from "@elizaos-plugins/plugin-di";Then all your plugins will be able to use Dependency Injection.
You can use Dependency Injection in any part of your Eliza plugin, including actions, evaluators, providers, services, and clients.
- Actions: Inject services or providers to interact with external APIs or services.
- Evaluators: Inject services or providers to evaluate conditions or perform calculations.
- Providers: Inject services or providers to provide data or resources.
- Services: Inject other services to perform business logic.
- Clients: Inject services to interact with external APIs or services.
This plugin provides a set of decorators that you can use to inject dependencies into your classes or functions.
We use the inversify library to provide the dependency injection system. The following decorators are provided by the inversify library.
Category: Class Decorator
This decorator marks a class as injectable. This means that you can inject this class into other classes using the @inject decorator.
import { injectable } from "inversify";
@injectable()
class SampleClass {
}Remember to register the class with the container before injecting it into other classes.
import { globalContainer } from "@elizaos-plugins/plugin-di";
// Register the class with the container as a singleton, this means that the class will be instantiated only once.
globalContainer.bind(SingletonClass).toSelf().inSingletonScope();
// Register the class with the container as a request context, this means that the class will be instantiated for each request(in this case means each Character).
globalContainer.bind(CharactorContextClass).toSelf().inRequestScope();Category: Parameter Decorator
This decorator marks a parameter as an injection target. This means that the parameter will be injected with the appropriate dependency when the class is instantiated.
import { injectable, inject } from "inversify";
@injectable()
class SampleClass {
constructor(
// Inject the SampleDependency as a public property of the class.
@inject("SampleDependency") public sampleDependency: SampleDependency
) {}
}DI plugin provides abstract classes that you can extend to create Injectable actions. And that provides the following decorators to improve the readability of the code.
Category: Property Decorator
This decorator is used to define a property in an action content class which will be used to generate the action content object Schema and content description template for LLM object generation.
import { z } from 'zod';
import { property } from "@elizaos-plugins/plugin-di";
class SampleActionContent {
@property({
description: "Sample property description",
schema: z.string(),
})
sampleProperty: string;
}This plugin provides the following abstract classes that you can extend to create Injectable classes:
BaseInjectableActionBaseInjectableEvaluator
Note: This is optional, you can create your own classes to create injectable actions.
This abstract class simplify the creation of injectable actions.
You don't need to think about the template for content generation, it will be generated automatically based on the properties of the content Class.
What you need to implement is the execute method.
import { injectable } from "inversify";
import { BaseInjectableAction } from "@elizaos-plugins/plugin-di";
class SampleActionContent {
@property({
description: "Sample property description",
schema: z.string(),
})
property1: string;
}
@injectable()
class SampleAction extends BaseInjectableAction<SampleActionContent> {
constructor() {
super({
/** general action constent options */
contentClass: SampleActionContent,
});
}
/**
* It will be called by `handler` function when the action is triggered.
*/
async execute(
content: SampleActionContent | null,
runtime: IAgentRuntime,
message: Memory,
state: State,
callback?: HandlerCallback
): Promise<void> {
// Your action logic here
}
}