|
| 1 | +# @elizaos/plugin-di - Dependency Injection Plugin for Eliza |
| 2 | + |
| 3 | +This plugin provides a dependency injection system for Eliza plugins. |
| 4 | + |
| 5 | +## What is Dependency Injection? |
| 6 | + |
| 7 | +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. |
| 8 | + |
| 9 | +## Examples of How to build a Plugin using Dependency Injection |
| 10 | + |
| 11 | +Check the [example](./src/_examples/) folder for a simple example of how to create a plugin using Dependency Injection. |
| 12 | + |
| 13 | +## Decorators for Dependency Injection |
| 14 | + |
| 15 | +This plugin provides a set of decorators that you can use to inject dependencies into your classes or functions. |
| 16 | + |
| 17 | +### From inversify |
| 18 | + |
| 19 | +We use the [inversify](https://inversify.io/) library to provide the dependency injection system. |
| 20 | +The following decorators are provided by the [inversify](https://inversify.io/) library. |
| 21 | + |
| 22 | +#### `@injectable` |
| 23 | + |
| 24 | +> Category: Class Decorator |
| 25 | +
|
| 26 | +This decorator marks a class as injectable. This means that you can inject this class into other classes using the `@inject` decorator. |
| 27 | + |
| 28 | +```typescript |
| 29 | +import { injectable } from "inversify"; |
| 30 | + |
| 31 | +@injectable() |
| 32 | +class SampleClass { |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +Remember to register the class with the container before injecting it into other classes. |
| 37 | + |
| 38 | +```typescript |
| 39 | +import { globalContainer } from "@elizaos/plugin-di"; |
| 40 | + |
| 41 | +// Register the class with the container as a singleton, this means that the class will be instantiated only once. |
| 42 | +globalContainer.bind(SingletonClass).toSelf().inSingletonScope(); |
| 43 | +// 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). |
| 44 | +globalContainer.bind(CharactorContextClass).toSelf().inRequestScope(); |
| 45 | +``` |
| 46 | + |
| 47 | +#### `@inject` |
| 48 | + |
| 49 | +> Category: Parameter Decorator |
| 50 | +
|
| 51 | +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. |
| 52 | + |
| 53 | +```typescript |
| 54 | +import { injectable, inject } from "inversify"; |
| 55 | + |
| 56 | +@injectable() |
| 57 | +class SampleClass { |
| 58 | + constructor( |
| 59 | + // Inject the SampleDependency as a public property of the class. |
| 60 | + @inject("SampleDependency") public sampleDependency: SampleDependency |
| 61 | + ) {} |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +### From di plugin |
| 66 | + |
| 67 | +DI plugin provides abstract classes that you can extend to create Injectable actions or evaluators. |
| 68 | +And that provides the following decorators to improve the readability of the code. |
| 69 | + |
| 70 | +#### `@property` |
| 71 | + |
| 72 | +> Category: Property Decorator |
| 73 | +
|
| 74 | +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. |
| 75 | + |
| 76 | +```typescript |
| 77 | +import { z } from 'zod'; |
| 78 | +import { property } from "@elizaos/plugin-di"; |
| 79 | + |
| 80 | +class SampleActionContent { |
| 81 | + @property({ |
| 82 | + description: "Sample property description", |
| 83 | + schema: z.string(), |
| 84 | + }) |
| 85 | + sampleProperty: string; |
| 86 | +} |
| 87 | +``` |
| 88 | + |
| 89 | +## Abstract Classes for Injaectable Actions and Evaluators |
| 90 | + |
| 91 | +This plugin provides abstract classes that you can extend to create Injectable actions or evaluators. |
| 92 | + |
| 93 | +### `BaseInjectableAction` |
| 94 | + |
| 95 | +This abstract class simplify the creation of injectable actions. |
| 96 | +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. |
| 97 | +What you need to implement is the `execute` method. |
| 98 | + |
| 99 | +```typescript |
| 100 | +import { injectable } from "inversify"; |
| 101 | +import { BaseInjectableAction } from "@elizaos/plugin-di"; |
| 102 | + |
| 103 | +class SampleActionContent { |
| 104 | + @property({ |
| 105 | + description: "Sample property description", |
| 106 | + schema: z.string(), |
| 107 | + }) |
| 108 | + property1: string; |
| 109 | +} |
| 110 | + |
| 111 | +@injectable() |
| 112 | +class SampleAction extends BaseInjectableAction<SampleActionContent> { |
| 113 | + constructor() { |
| 114 | + super({ |
| 115 | + /** general action constent options */ |
| 116 | + contentClass: SampleActionContent, |
| 117 | + }); |
| 118 | + } |
| 119 | + |
| 120 | + /** |
| 121 | + * It will be called by `handler` function when the action is triggered. |
| 122 | + */ |
| 123 | + async execute( |
| 124 | + content: SampleActionContent | null, |
| 125 | + runtime: IAgentRuntime, |
| 126 | + message: Memory, |
| 127 | + state: State, |
| 128 | + callback?: HandlerCallback |
| 129 | + ): Promise<void> { |
| 130 | + // Your action logic here |
| 131 | + } |
| 132 | +} |
| 133 | +``` |
| 134 | + |
| 135 | +### `BaseInjectableEvaluator` |
| 136 | + |
| 137 | +This abstract class simplify the creation of injectable evaluators. |
| 138 | + |
| 139 | +Please refer to the [sampleEvaluator](./src/_examples/sampleEvaluator.ts) for an example of how to create an evaluator. |
0 commit comments