@elizaos/cli 1.2.12 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -176,6 +176,23 @@ var baseCharacter = {
176
176
  }
177
177
  ]
178
178
  ],
179
+ postExamples: [
180
+ "Sometimes the best debugging tool is a fresh cup of coffee and a walk around the block.",
181
+ "The magic happens when developers stop competing and start collaborating. Build together, grow together.",
182
+ "Reminder: Your code doesn't have to be perfect on the first try. Progress over perfection.",
183
+ "Community tip: The person asking 'obvious' questions today might solve your toughest problem tomorrow. Be kind.",
184
+ "Hot take: Good documentation is more valuable than clever code.",
185
+ "The best feature you can add to your project? A welcoming community.",
186
+ "Debugging is just a conversation with your past self. Make it easier by leaving good comments.",
187
+ "Your daily reminder that impostor syndrome affects even the most experienced developers. You belong here.",
188
+ "Pro tip: Read the error message. Then read it again. The answer is usually there.",
189
+ "Building in public isn't about showing off. It's about learning together and helping others avoid your mistakes.",
190
+ "The difference between junior and senior developers? Seniors know when NOT to write code.",
191
+ "Community > Competition. Always.",
192
+ "Remember: Every expert was once a beginner who refused to give up.",
193
+ "Code reviews aren't personal attacks. They're opportunities to level up together.",
194
+ "The most powerful tool in development? Asking for help when you need it."
195
+ ],
179
196
  style: {
180
197
  all: [
181
198
  "Keep responses concise but informative",
@@ -194,6 +211,20 @@ var baseCharacter = {
194
211
  "Engage with the topic at hand",
195
212
  "Be helpful and informative",
196
213
  "Show personality and warmth"
214
+ ],
215
+ post: [
216
+ "Keep it concise and punchy - every word counts",
217
+ "Share insights, not platitudes",
218
+ "Be authentic and conversational, not corporate",
219
+ "Use specific examples over generic advice",
220
+ "Add value with each post - teach, inspire, or entertain",
221
+ "One clear thought per post",
222
+ "Avoid excessive hashtags or mentions",
223
+ "Write like you are talking to a friend",
224
+ "Share personal observations and hot takes",
225
+ "Be helpful without being preachy",
226
+ "Use emojis sparingly and purposefully",
227
+ "End with something thought-provoking when appropriate"
197
228
  ]
198
229
  }
199
230
  };
@@ -9,7 +9,7 @@ import {
9
9
  selectEmbeddingModel,
10
10
  validateCreateOptions,
11
11
  validateProjectName
12
- } from "./chunk-OXCJTWT3.js";
12
+ } from "./chunk-2CUIHNPL.js";
13
13
  import {
14
14
  displayBanner,
15
15
  handleError
@@ -8,7 +8,7 @@ import {
8
8
  setupAIModelConfig,
9
9
  setupEmbeddingModelConfig,
10
10
  setupProjectEnvironment
11
- } from "../../../chunk-OXCJTWT3.js";
11
+ } from "../../../chunk-2CUIHNPL.js";
12
12
  import "../../../chunk-2ALAPQLV.js";
13
13
  import "../../../chunk-FDEDLANP.js";
14
14
  import "../../../chunk-4O6EZU37.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  create
3
- } from "../../chunk-WEAYAAIM.js";
4
- import "../../chunk-OXCJTWT3.js";
3
+ } from "../../chunk-I77ZRNYO.js";
4
+ import "../../chunk-2CUIHNPL.js";
5
5
  import "../../chunk-2ALAPQLV.js";
6
6
  import "../../chunk-FDEDLANP.js";
7
7
  import "../../chunk-4O6EZU37.js";
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env bun
2
2
  import {
3
3
  create
4
- } from "./chunk-WEAYAAIM.js";
4
+ } from "./chunk-I77ZRNYO.js";
5
5
  import {
6
6
  getElizaCharacter
7
- } from "./chunk-OXCJTWT3.js";
7
+ } from "./chunk-2CUIHNPL.js";
8
8
  import {
9
9
  TestRunner,
10
10
  UserEnvironment,
@@ -284,6 +284,9 @@ function setupEnvironment() {
284
284
  env2.PATH = localBinPath;
285
285
  }
286
286
  env2.FORCE_COLOR = "1";
287
+ if (process.env.ELIZA_TEST_MODE) {
288
+ env2.ELIZA_TEST_MODE = process.env.ELIZA_TEST_MODE;
289
+ }
287
290
  return env2;
288
291
  }
289
292
  async function startServerProcess(args = []) {
@@ -299,13 +302,40 @@ async function startServerProcess(args = []) {
299
302
  scriptPath = process.argv[1];
300
303
  }
301
304
  const env2 = setupEnvironment();
302
- const childProcess = Bun.spawn([nodeExecutable, scriptPath, "start", ...args], {
303
- stdio: ["inherit", "inherit", "inherit"],
305
+ const isTestMode = process.env.ELIZA_TEST_MODE === "true";
306
+ const commandArgs = [nodeExecutable, scriptPath, "start", ...args];
307
+ if (isTestMode) {
308
+ console.info(`Executing command: ${commandArgs.join(" ")}`);
309
+ }
310
+ const childProcess = Bun.spawn(commandArgs, {
311
+ stdio: isTestMode ? ["inherit", "pipe", "pipe"] : ["inherit", "inherit", "inherit"],
304
312
  env: env2,
305
313
  cwd: process.cwd()
306
314
  });
307
315
  serverState.process = childProcess;
308
316
  serverState.isRunning = true;
317
+ if (isTestMode && childProcess.stdout && childProcess.stderr) {
318
+ childProcess.stdout.pipeTo(
319
+ new WritableStream({
320
+ write(chunk) {
321
+ process.stdout.write(chunk);
322
+ return Promise.resolve();
323
+ }
324
+ })
325
+ ).catch((error) => {
326
+ console.error("Error piping stdout:", error);
327
+ });
328
+ childProcess.stderr.pipeTo(
329
+ new WritableStream({
330
+ write(chunk) {
331
+ process.stderr.write(chunk);
332
+ return Promise.resolve();
333
+ }
334
+ })
335
+ ).catch((error) => {
336
+ console.error("Error piping stderr:", error);
337
+ });
338
+ }
309
339
  childProcess.exited.then((exitCode) => {
310
340
  if (exitCode !== 0) {
311
341
  console.warn(`Server process exited with code ${exitCode}`);
@@ -455,6 +485,9 @@ async function startDevMode(options) {
455
485
  console.info(`Running in ${modeDescription} mode`);
456
486
  await performInitialBuild(context);
457
487
  }
488
+ if (process.env.ELIZA_TEST_MODE === "true") {
489
+ console.info(`[DEV] Starting server with args: ${cliArgs.join(" ")}`);
490
+ }
458
491
  await serverManager2.start(cliArgs);
459
492
  if (isProject || isPlugin2 || isMonorepo) {
460
493
  await watchDirectory(context.watchDirectory, rebuildAndRestart);
@@ -40,7 +40,7 @@
40
40
  "tsup.config.ts"
41
41
  ],
42
42
  "dependencies": {
43
- "@elizaos/core": "1.2.12",
43
+ "@elizaos/core": "1.3.0",
44
44
  "zod": "^3.24.4"
45
45
  },
46
46
  "devDependencies": {
@@ -266,7 +266,7 @@ export const starterPlugin: Plugin = {
266
266
  services: [StarterService],
267
267
  actions: [helloWorldAction],
268
268
  providers: [helloWorldProvider],
269
- // dependencies: ['@elizaos/plugin-knowledge'], <--- plugin dependecies go here (if requires another plugin)
269
+ // dependencies: ['@elizaos/plugin-knowledge'], <--- plugin dependencies go here (if requires another plugin)
270
270
  };
271
271
 
272
272
  export default starterPlugin;
@@ -0,0 +1,465 @@
1
+ # ElizaOS Plugin Development Guide for Claude
2
+
3
+ > **Optimized for Claude LLM** - Complete reference for building ElizaOS plugins
4
+
5
+ ## 📋 Project Overview
6
+
7
+ | Property | Value |
8
+ | ------------------- | --------------------- |
9
+ | **Project Type** | ElizaOS Plugin |
10
+ | **Package Manager** | `bun` (REQUIRED) |
11
+ | **Language** | TypeScript (Required) |
12
+ | **Testing** | Bun test |
13
+ | **Runtime** | ElizaOS Agent Runtime |
14
+
15
+ ## 🏗️ Plugin Architecture
16
+
17
+ ElizaOS plugins follow a **component-based architecture** with four main types:
18
+
19
+ ### 🔄 **Services** (Required for External APIs)
20
+
21
+ **Purpose:** Handle stateful operations and external integrations
22
+
23
+ ```typescript
24
+ export class ExampleService extends Service {
25
+ static serviceType = 'example';
26
+ private apiClient: ExternalAPI;
27
+
28
+ constructor() {
29
+ super();
30
+ }
31
+
32
+ async initialize(runtime: IAgentRuntime): Promise<void> {
33
+ // Initialize SDK connections, databases, etc.
34
+ this.apiClient = new ExternalAPI(process.env.API_KEY);
35
+ }
36
+
37
+ async processData(data: any): Promise<any> {
38
+ // Your business logic here
39
+ return await this.apiClient.process(data);
40
+ }
41
+ }
42
+ ```
43
+
44
+ **Services are for:**
45
+
46
+ - ✅ API connections and SDK management
47
+ - ✅ Database operations
48
+ - ✅ State management
49
+ - ✅ Authentication handling
50
+ - ❌ NOT for simple data formatting (use Providers)
51
+
52
+ ### ⚡ **Actions** (Required for User Interactions)
53
+
54
+ **Purpose:** Handle user commands and generate responses
55
+
56
+ ```typescript
57
+ import { Action, ActionResult } from '@elizaos/core';
58
+
59
+ export const exampleAction: Action = {
60
+ name: 'EXAMPLE_ACTION',
61
+ description: 'Processes user requests for example functionality',
62
+
63
+ validate: async (runtime: IAgentRuntime, message: Memory) => {
64
+ const text = message.content.text.toLowerCase();
65
+ return text.includes('example') || text.includes('demo');
66
+ },
67
+
68
+ handler: async (runtime, message, state, options, callback): Promise<ActionResult> => {
69
+ try {
70
+ const service = runtime.getService<ExampleService>('example');
71
+ const result = await service.processData(message.content);
72
+
73
+ await callback({
74
+ text: `Here's your result: ${result}`,
75
+ action: 'EXAMPLE_ACTION',
76
+ });
77
+
78
+ return {
79
+ success: true,
80
+ text: `Successfully processed: ${result}`,
81
+ values: {
82
+ lastProcessed: result,
83
+ processedAt: Date.now(),
84
+ },
85
+ data: {
86
+ actionName: 'EXAMPLE_ACTION',
87
+ result,
88
+ },
89
+ };
90
+ } catch (error) {
91
+ await callback({
92
+ text: 'I encountered an error processing your request.',
93
+ error: true,
94
+ });
95
+
96
+ return {
97
+ success: false,
98
+ text: 'Failed to process request',
99
+ error: error instanceof Error ? error : new Error(String(error)),
100
+ data: {
101
+ actionName: 'EXAMPLE_ACTION',
102
+ errorMessage: error instanceof Error ? error.message : 'Unknown error',
103
+ },
104
+ };
105
+ }
106
+ },
107
+ };
108
+ ```
109
+
110
+ **Actions handle:**
111
+
112
+ - ✅ User input validation
113
+ - ✅ Command parsing and routing
114
+ - ✅ Service coordination
115
+ - ✅ Response generation
116
+ - ❌ NOT direct API calls (use Services)
117
+
118
+ **Important: Callbacks vs ActionResult:**
119
+
120
+ - **`callback()`** → Sends messages to the user in chat
121
+ - **`ActionResult` return** → Passes data/state to next action in chain
122
+ - Both are used together: callback for user communication, return for action chaining
123
+
124
+ ### 📊 **Providers** (Optional - Context Supply)
125
+
126
+ **Purpose:** Supply read-only contextual information
127
+
128
+ ```typescript
129
+ export const exampleProvider: Provider = {
130
+ get: async (runtime: IAgentRuntime, message: Memory) => {
131
+ const service = runtime.getService<ExampleService>('example');
132
+ const status = await service.getStatus();
133
+
134
+ return `Current system status: ${status.state}
135
+ Available features: ${status.features.join(', ')}
136
+ Last updated: ${status.timestamp}`;
137
+ },
138
+ };
139
+ ```
140
+
141
+ **Providers supply:**
142
+
143
+ - ✅ Formatted contextual data
144
+ - ✅ Real-time information
145
+ - ✅ System state summaries
146
+ - ❌ NOT for state modification
147
+
148
+ ### 🧠 **Evaluators** (Optional - Post-Processing)
149
+
150
+ **Purpose:** Learn from interactions and analyze outcomes
151
+
152
+ ```typescript
153
+ export const exampleEvaluator: Evaluator = {
154
+ name: 'EXAMPLE_EVALUATOR',
155
+
156
+ evaluate: async (runtime: IAgentRuntime, message: Memory, state?: any) => {
157
+ // Analyze the interaction outcome
158
+ const success = state?.lastActionSuccess || false;
159
+
160
+ if (success) {
161
+ // Store successful patterns
162
+ await runtime.addMemory({
163
+ content: { text: 'Successful example interaction pattern' },
164
+ type: 'learning',
165
+ });
166
+ }
167
+
168
+ return { success, confidence: 0.8 };
169
+ },
170
+ };
171
+ ```
172
+
173
+ ## 📁 Project Structure
174
+
175
+ ```
176
+ src/
177
+ ├── 📂 actions/ # User command handlers
178
+ │ ├── exampleAction.ts
179
+ │ └── index.ts
180
+ ├── 📂 services/ # External integrations (REQUIRED)
181
+ │ ├── ExampleService.ts
182
+ │ └── index.ts
183
+ ├── 📂 providers/ # Context suppliers (optional)
184
+ │ ├── exampleProvider.ts
185
+ │ └── index.ts
186
+ ├── 📂 evaluators/ # Learning components (optional)
187
+ │ ├── exampleEvaluator.ts
188
+ │ └── index.ts
189
+ ├── 📂 types/ # TypeScript definitions
190
+ │ └── index.ts
191
+ ├── 📄 index.ts # Plugin export
192
+ └── 📄 package.json # Dependencies and metadata
193
+ ```
194
+
195
+ ## 📦 Plugin Export Pattern
196
+
197
+ ```typescript
198
+ // src/index.ts
199
+ import { Plugin } from '@elizaos/core';
200
+ import { ExampleService } from './services';
201
+ import { exampleAction } from './actions';
202
+ import { exampleProvider } from './providers';
203
+ import { exampleEvaluator } from './evaluators';
204
+
205
+ export const plugin: Plugin = {
206
+ name: 'example-plugin',
207
+ description: 'Demonstrates ElizaOS plugin patterns',
208
+
209
+ // Core components
210
+ services: [ExampleService],
211
+ actions: [exampleAction],
212
+
213
+ // Optional components
214
+ providers: [exampleProvider],
215
+ evaluators: [exampleEvaluator],
216
+ };
217
+
218
+ export default plugin;
219
+
220
+ // Re-export components for external use
221
+ export { ExampleService } from './services';
222
+ export * from './types';
223
+ ```
224
+
225
+ ## 🚀 Development Workflow
226
+
227
+ ### Quick Start Commands
228
+
229
+ ```bash
230
+ # Install dependencies
231
+ bun install
232
+
233
+ # Start development with hot reload
234
+ elizaos dev
235
+
236
+ # Run tests
237
+ bun test
238
+
239
+ # Build for production
240
+ bun run build
241
+ ```
242
+
243
+ ### 🧪 Testing Your Plugin
244
+
245
+ #### **Method 1: Dev Mode (Recommended)**
246
+
247
+ ```bash
248
+ elizaos dev
249
+ ```
250
+
251
+ This automatically:
252
+
253
+ - Loads your plugin from current directory
254
+ - Creates a test character with your plugin
255
+ - Starts interactive chat interface
256
+ - Enables hot reloading
257
+
258
+ #### **Method 2: Unit Testing**
259
+
260
+ ```typescript
261
+ // tests/actions.test.ts
262
+ import { describe, it, expect } from 'bun:test';
263
+ import { exampleAction } from '../src/actions';
264
+
265
+ describe('ExampleAction', () => {
266
+ it('validates trigger words correctly', async () => {
267
+ const mockMessage = {
268
+ content: { text: 'show me an example' },
269
+ };
270
+
271
+ const isValid = await exampleAction.validate(mockRuntime, mockMessage);
272
+
273
+ expect(isValid).toBe(true);
274
+ });
275
+ });
276
+ ```
277
+
278
+ ## 🎯 Best Practices
279
+
280
+ ### ✅ **DO**
281
+
282
+ - **Use Services for APIs**: All external calls go through services
283
+ - **Validate User Input**: Always validate in action handlers
284
+ - **Handle Errors Gracefully**: Provide meaningful error messages
285
+ - **Follow TypeScript**: Use strict typing throughout
286
+ - **Test Thoroughly**: Write tests for core functionality
287
+
288
+ ### ❌ **DON'T**
289
+
290
+ - **API Calls in Actions**: Use services instead
291
+ - **State in Providers**: Keep providers read-only
292
+ - **Parse Input in Evaluators**: Use actions for input handling
293
+ - **Hardcode Credentials**: Use environment variables
294
+ - **Skip Error Handling**: Always handle potential failures
295
+
296
+ ### 🔧 **Common Patterns**
297
+
298
+ #### Error Handling Pattern
299
+
300
+ ```typescript
301
+ export const robustAction: Action = {
302
+ name: 'ROBUST_ACTION',
303
+ description: 'Demonstrates robust error handling',
304
+
305
+ validate: async (runtime: IAgentRuntime, message: Memory) => {
306
+ // Validate user input before processing
307
+ const text = message.content.text.toLowerCase();
308
+ return text.includes('process') || text.includes('execute');
309
+ },
310
+
311
+ handler: async (runtime, message, state, options, callback): Promise<ActionResult> => {
312
+ try {
313
+ const service = runtime.getService<YourService>('yourService');
314
+ if (!service) {
315
+ throw new Error('Service not available');
316
+ }
317
+
318
+ const result = await service.performOperation();
319
+
320
+ await callback({
321
+ text: `Operation completed: ${result}`,
322
+ action: 'ROBUST_ACTION',
323
+ });
324
+
325
+ return {
326
+ success: true,
327
+ text: `Successfully completed operation`,
328
+ values: {
329
+ operationResult: result,
330
+ processedAt: Date.now(),
331
+ },
332
+ data: {
333
+ actionName: 'ROBUST_ACTION',
334
+ result,
335
+ },
336
+ };
337
+ } catch (error) {
338
+ console.error(`Action failed: ${error instanceof Error ? error.message : String(error)}`);
339
+
340
+ await callback({
341
+ text: "I'm sorry, I couldn't complete that request. Please try again.",
342
+ error: true,
343
+ });
344
+
345
+ return {
346
+ success: false,
347
+ text: 'Failed to complete operation',
348
+ error: error instanceof Error ? error : new Error(String(error)),
349
+ data: {
350
+ actionName: 'ROBUST_ACTION',
351
+ errorMessage: error instanceof Error ? error.message : String(error),
352
+ },
353
+ };
354
+ }
355
+ },
356
+ };
357
+ ```
358
+
359
+ #### Service Initialization Pattern
360
+
361
+ ```typescript
362
+ export class RobustService extends Service {
363
+ private client: ExternalClient;
364
+ private isInitialized = false;
365
+
366
+ async initialize(runtime: IAgentRuntime): Promise<void> {
367
+ try {
368
+ this.client = new ExternalClient({
369
+ apiKey: process.env.EXTERNAL_API_KEY,
370
+ timeout: 30000,
371
+ });
372
+
373
+ await this.client.authenticate();
374
+ this.isInitialized = true;
375
+
376
+ console.log('Service initialized successfully');
377
+ } catch (error) {
378
+ console.error('Service initialization failed:', error);
379
+ throw error;
380
+ }
381
+ }
382
+
383
+ private ensureInitialized(): void {
384
+ if (!this.isInitialized) {
385
+ throw new Error('Service not initialized');
386
+ }
387
+ }
388
+
389
+ async performOperation(): Promise<any> {
390
+ this.ensureInitialized();
391
+ return await this.client.operation();
392
+ }
393
+ }
394
+ ```
395
+
396
+ ## 🐛 Debugging Guide
397
+
398
+ ### Environment Variables
399
+
400
+ ```bash
401
+ # Enable detailed logging
402
+ LOG_LEVEL=debug elizaos dev
403
+
404
+ # Test specific components
405
+ elizaos test --filter "action-name"
406
+ ```
407
+
408
+ ### Common Issues & Solutions
409
+
410
+ | Issue | Cause | Solution |
411
+ | ----------------------- | ------------------------------ | ---------------------------- |
412
+ | "Service not found" | Service not registered | Add to plugin services array |
413
+ | "Action not triggering" | Validation function too strict | Check validate() logic |
414
+ | "Provider not updating" | Provider has state | Make provider stateless |
415
+ | "Memory errors" | Database connection issues | Check database adapter setup |
416
+
417
+ ## 📋 Package.json Template
418
+
419
+ ```json
420
+ {
421
+ "name": "@your-org/elizaos-plugin-example",
422
+ "version": "1.0.0",
423
+ "description": "ElizaOS plugin for example functionality",
424
+ "type": "module",
425
+ "main": "dist/index.js",
426
+ "types": "dist/index.d.ts",
427
+ "files": ["dist"],
428
+
429
+ "scripts": {
430
+ "build": "bun run build:types && bun run build:js",
431
+ "build:types": "tsc",
432
+ "build:js": "bun build src/index.ts --outdir dist",
433
+ "test": "bun test",
434
+ "dev": "elizaos dev"
435
+ },
436
+
437
+ "peerDependencies": {
438
+ "@elizaos/core": "*"
439
+ },
440
+
441
+ "devDependencies": {
442
+ "@types/bun": "latest",
443
+ "typescript": "^5.0.0"
444
+ },
445
+
446
+ "keywords": ["elizaos", "plugin", "ai-agent"]
447
+ }
448
+ ```
449
+
450
+ ## 🎯 Final Checklist
451
+
452
+ Before publishing your plugin:
453
+
454
+ - [ ] All services have proper initialization
455
+ - [ ] Actions validate user input correctly
456
+ - [ ] Error handling covers edge cases
457
+ - [ ] Tests pass for core functionality
458
+ - [ ] TypeScript compiles without errors
459
+ - [ ] Plugin exports are correct
460
+ - [ ] Documentation is complete
461
+ - [ ] Environment variables are documented
462
+
463
+ ---
464
+
465
+ **🎉 Ready to build your ElizaOS plugin!** Start with the dev mode and iterate based on real testing.