diff --git a/.env.example b/.env.example index e60b16885c..d48705fe82 100644 --- a/.env.example +++ b/.env.example @@ -540,6 +540,10 @@ AWS_REGION= AWS_S3_BUCKET= AWS_S3_UPLOAD_PATH= +# Deva Configuration +DEVA_API_KEY= # You can get the API key from the created application in deva.me/settings/apps +DEVA_API_BASE_URL=https://api.deva.me # Default server url is production https://api-staging.deva.me + # Deepgram DEEPGRAM_API_KEY= diff --git a/agent/package.json b/agent/package.json index 73cd235caa..0d490f2483 100644 --- a/agent/package.json +++ b/agent/package.json @@ -92,6 +92,7 @@ "@elizaos/plugin-obsidian": "workspace:*", "@elizaos/plugin-arthera": "workspace:*", "@elizaos/plugin-allora": "workspace:*", + "@elizaos/client-deva": "workspace:*", "@elizaos/plugin-opacity": "workspace:*", "@elizaos/plugin-hyperliquid": "workspace:*", "@elizaos/plugin-akash": "workspace:*", diff --git a/agent/src/index.ts b/agent/src/index.ts index 056685593f..fee41e65ae 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -10,6 +10,7 @@ import { LensAgentClient } from "@elizaos/client-lens"; import { SlackClientInterface } from "@elizaos/client-slack"; import { TelegramClientInterface } from "@elizaos/client-telegram"; import { TwitterClientInterface } from "@elizaos/client-twitter"; +import { DevaClientInterface } from "@elizaos/client-deva"; // import { ReclaimAdapter } from "@elizaos/plugin-reclaim"; import { PrimusAdapter } from "@elizaos/plugin-primus"; @@ -631,6 +632,11 @@ export async function initializeClients( if (slackClient) clients.slack = slackClient; // Use object property instead of push } + if (clientTypes.includes("deva")) { + const devaClients = await DevaClientInterface.start(runtime); + clients.push(devaClients); + } + function determineClientType(client: Client): string { // Check if client has a direct type identifier if ("type" in client) { diff --git a/docs/api/enumerations/Clients.md b/docs/api/enumerations/Clients.md index 5d746ad1c0..6a3a78e1a7 100644 --- a/docs/api/enumerations/Clients.md +++ b/docs/api/enumerations/Clients.md @@ -83,3 +83,14 @@ Available client platforms #### Defined in [packages/core/src/types.ts:627](https://github.com/elizaOS/eliza/blob/main/packages/core/src/types.ts#L627) + +--- + +### DEVA + +> **DEVA**: `"deva"` + +#### Defined in + +[packages/core/src/types.ts:643](https://github.com/elizaOS/eliza/blob/main/packages/core/src/types.ts#L643) + diff --git a/docs/docs/packages/clients.md b/docs/docs/packages/clients.md index 24fa4bfb28..31579a1f51 100644 --- a/docs/docs/packages/clients.md +++ b/docs/docs/packages/clients.md @@ -18,6 +18,7 @@ graph TD CI --> TC["Telegram Client"] CI --> TWC["Twitter Client"] CI --> AC["Auto Client"] + CI --> DEVA["Deva Client"] %% Key Features - one per client for clarity DC --> |"REST API"| DC1["Messages & Images"] @@ -25,6 +26,7 @@ graph TD TC --> |"Bot API"| TC1["Commands & Media"] TWC --> |"Social"| TWC1["Posts & Interactions"] AC --> |"Trading"| AC1["Analysis & Execution"] + DEVA --> |"Social"| DEVA1["Messages & Execution"] %% Simple styling with better contrast and black text classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px,color:black @@ -35,6 +37,12 @@ graph TD ## Available Clients +- **Discord** (`@eliza/client-discord`) - Full Discord bot integration +- **Twitter** (`@eliza/client-twitter`) - Twitter bot and interaction handling +- **Telegram** (`@eliza/client-telegram`) - Telegram bot integration +- **Direct** (`@eliza/client-direct`) - Direct API interface for custom integrations +- **Auto** (`@eliza/client-auto`) - Automated trading and interaction client +- # **Deva** (`@eliza/client-deva`) - Client for integrating with Deva.me - **Discord** (`@elizaos/client-discord`) - Full Discord bot integration - **Twitter** (`@elizaos/client-twitter`) - Twitter bot and interaction handling - **Telegram** (`@elizaos/client-telegram`) - Telegram bot integration @@ -60,6 +68,9 @@ pnpm add @elizaos/client-direct # Auto Client pnpm add @elizaos/client-auto + +# Deva Client +pnpm add @eliza/client-deva ``` --- @@ -293,6 +304,80 @@ class AutoClient { } ``` +## Deva Client + +The Deva client allows fetching user-related data and making posts based on it. + +### Client setup + +```typescript +export const DevaClientInterface: Client = { + async start(runtime: IAgentRuntime) { + await validateDevaConfig(runtime); + + const deva = new DevaClient( + runtime, + runtime.getSetting("DEVA_API_KEY"), + runtime.getSetting("DEVA_API_BASE_URL"), + ); + + await deva.start(); + + elizaLogger.success( + `✅ Deva client successfully started for character ${runtime.character.name}`, + ); + + return deva; + }, +}; +``` + +### Fetch personal user data + +```typescript +public async getMe(): Promise { + return await fetch(`${this.apiBaseUrl}/persona`, { + headers: { ...this.defaultHeaders }, + }) + .then((res) => res.json()) + .catch(() => null); +} +``` + +### Fetch user posts + +```typescript +public async getPersonaPosts(personaId: string): Promise { + const res = await fetch( + `${this.apiBaseUrl}/post?filter_persona_id=${personaId}`, + { + headers: { + Authorization: `Bearer ${this.accessToken}`, + "Content-Type": "application/json", + }, + } + ).then((res) => res.json()); + return res.items; +} +``` + +### Create and publish a post on behalf of the user + +```typescript +public async makePost({ text, in_reply_to_id }: { text: string; in_reply_to_id: string }): Promise { + const res = await fetch(`${this.apiBaseUrl}/post`, { + method: "POST", + headers: { + Authorization: `Bearer ${this.accessToken}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ text, in_reply_to_id, author_type: "BOT" }), + }).then((res) => res.json()); + + console.log(res); + return res; +``` + ## Common Features ### Message Handling @@ -302,7 +387,9 @@ All clients implement standard message handling: ```typescript interface ClientInterface { async handleMessage(message: Message): Promise; + async generateResponse(context: Context): Promise; + async sendMessage(destination: string, content: Content): Promise; } ``` @@ -312,7 +399,9 @@ interface ClientInterface { ```typescript interface MediaProcessor { async processImage(image: Image): Promise; + async processVideo(video: Video): Promise; + async processAudio(audio: Audio): Promise; } ``` @@ -462,8 +551,8 @@ class MessageQueue { ```typescript // Implement token refresh async refreshAuth() { - const newToken = await this.requestNewToken(); - await this.updateToken(newToken); + const newToken = await this.requestNewToken(); + await this.updateToken(newToken); } ``` @@ -472,9 +561,9 @@ async refreshAuth() { ```typescript // Handle rate limiting async handleRateLimit(error) { - const delay = this.calculateBackoff(error); - await wait(delay); - return this.retryRequest(); + const delay = this.calculateBackoff(error); + await wait(delay); + return this.retryRequest(); } ``` @@ -483,10 +572,10 @@ async handleRateLimit(error) { ```typescript // Implement reconnection logic async handleDisconnect() { - await this.reconnect({ - maxAttempts: 5, - backoff: 'exponential' - }); + await this.reconnect({ + maxAttempts: 5, + backoff: "exponential", + }); } ``` @@ -494,14 +583,14 @@ async handleDisconnect() { ```typescript async processMessage(message) { - try { - return await this.messageProcessor(message); - } catch (error) { - if (error.code === "INVALID_FORMAT") { - return this.handleInvalidFormat(message); - } - throw error; - } + try { + return await this.messageProcessor(message); + } catch (error) { + if (error.code === "INVALID_FORMAT") { + return this.handleInvalidFormat(message); + } + throw error; + } } ``` diff --git a/packages/client-deva/.npmignore b/packages/client-deva/.npmignore new file mode 100644 index 0000000000..078562ecea --- /dev/null +++ b/packages/client-deva/.npmignore @@ -0,0 +1,6 @@ +* + +!dist/** +!package.json +!readme.md +!tsup.config.ts \ No newline at end of file diff --git a/packages/client-deva/eslint.config.mjs b/packages/client-deva/eslint.config.mjs new file mode 100644 index 0000000000..92fe5bbebe --- /dev/null +++ b/packages/client-deva/eslint.config.mjs @@ -0,0 +1,3 @@ +import eslintGlobalConfig from "../../eslint.config.mjs"; + +export default [...eslintGlobalConfig]; diff --git a/packages/client-deva/package.json b/packages/client-deva/package.json new file mode 100644 index 0000000000..882a5c9108 --- /dev/null +++ b/packages/client-deva/package.json @@ -0,0 +1,23 @@ +{ + "name": "@elizaos/client-deva", + "version": "0.1.7-alpha.1", + "main": "dist/index.js", + "type": "module", + "types": "dist/index.d.ts", + "dependencies": { + "@elizaos/core": "workspace:*", + "glob": "11.0.0", + "zod": "3.23.8" + }, + "devDependencies": { + "tsup": "8.3.5" + }, + "scripts": { + "build": "tsup --format esm --dts", + "dev": "tsup --watch", + "lint": "eslint . --fix" + }, + "peerDependencies": { + "whatwg-url": "7.1.0" + } +} diff --git a/packages/client-deva/src/base.ts b/packages/client-deva/src/base.ts new file mode 100644 index 0000000000..8b53cf8f55 --- /dev/null +++ b/packages/client-deva/src/base.ts @@ -0,0 +1,60 @@ +import { elizaLogger, IAgentRuntime } from "@elizaos/core"; +import { DevaPersona, DevaPost } from "./types"; + +export class ClientBase { + private readonly runtime: IAgentRuntime; + private readonly accessToken: string; + private readonly apiBaseUrl: string; + private readonly defaultHeaders: Record; + + constructor(runtime: IAgentRuntime, accessToken: string, baseUrl: string) { + this.runtime = runtime; + this.accessToken = accessToken; + this.apiBaseUrl = baseUrl; + this.defaultHeaders = { + Authorization: `Bearer ${this.accessToken}`, + "Content-Type": "application/json", + }; + } + + public async getMe(): Promise { + return await fetch(`${this.apiBaseUrl}/persona`, { + headers: { ...this.defaultHeaders }, + }) + .then((res) => res.json()) + .catch(() => null); + } + + public async getPersonaPosts(personaId: string): Promise { + const res = await fetch( + `${this.apiBaseUrl}/post?filter_persona_id=${personaId}`, + { + headers: { + Authorization: `Bearer ${this.accessToken}`, + "Content-Type": "application/json", + }, + } + ).then((res) => res.json()); + return res.items; + } + + public async makePost({ + text, + in_reply_to_id, + }: { + text: string; + in_reply_to_id: string; + }): Promise { + const res = await fetch(`${this.apiBaseUrl}/post`, { + method: "POST", + headers: { + Authorization: `Bearer ${this.accessToken}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ text, in_reply_to_id, author_type: "BOT" }), + }).then((res) => res.json()); + + console.log(res); + return res; + } +} diff --git a/packages/client-deva/src/controller.ts b/packages/client-deva/src/controller.ts new file mode 100644 index 0000000000..aa7245a48c --- /dev/null +++ b/packages/client-deva/src/controller.ts @@ -0,0 +1,242 @@ +import { + composeContext, + Content, + elizaLogger, + generateText, + getEmbeddingZeroVector, + IAgentRuntime, + ModelClass, + parseBooleanFromText, + State, + stringToUuid, +} from "@elizaos/core"; +import { ClientBase } from "./base"; +import { DevaPersona, DevaPost } from "./types"; +import { DEVA_POST_TEMPLATE } from "./templates.ts"; + +export class DevaController { + private readonly runtime: IAgentRuntime; + private readonly client: ClientBase; + + private persona: DevaPersona; + private posts: DevaPost[]; + + constructor(runtime: IAgentRuntime, client: ClientBase) { + this.runtime = runtime; + this.client = client; + } + + public async init() { + await this.populatePersona(); + await this.populatePosts(); + await this.startPosting(); + } + + private async populatePersona() { + this.persona = await this.client.getMe(); + + if (!this.persona && !this.persona.id) { + elizaLogger.error("❌ Deva Client failed to fetch Persona"); + throw new Error("❌ Deva Client failed to fetch Persona"); + } + + elizaLogger.log( + `✨ Deva Client successfully fetched Persona: ${this.persona.username} ID: ${this.persona.id}` + ); + } + + private async populatePosts() { + this.posts = await this.client.getPersonaPosts(this.persona.id); + + // Get the existing memories from the database + const existingMemories = + await this.runtime.messageManager.getMemoriesByRoomIds({ + roomIds: this.posts.map((post) => + stringToUuid( + post.in_reply_to_id + "-" + this.runtime.agentId + ) + ), + }); + + // Create a Set to store the IDs of existing memories + const existingMemoryIds = new Set( + existingMemories.map((memory) => memory.id.toString()) + ); + + // Check if any of the posts don't exist in the existing memories + const notExistingPostsInMemory = this.posts.filter( + (post) => + !existingMemoryIds.has( + stringToUuid(post.id + "-" + this.runtime.agentId) + ) + ); + + for (const post of notExistingPostsInMemory) { + elizaLogger.log("Saving Post", post.id); + + const roomId = stringToUuid( + post.in_reply_to_id + "-" + this.runtime.agentId + ); + + const userId = + post.persona_id === this.persona.id + ? this.runtime.agentId + : stringToUuid(post.persona_id); + + if (post.persona_id === this.persona.id) { + await this.runtime.ensureConnection( + this.runtime.agentId, + roomId, + this.persona.username, + this.persona.display_name, + "deva" + ); + } else { + await this.runtime.ensureConnection( + userId, + roomId, + post.persona.username, + post.persona.display_name, + "deva" + ); + } + + const content = { + text: post.text, + inReplyTo: stringToUuid( + post.in_reply_to_id + "-" + this.runtime.agentId + ), + source: "deva", + } as Content; + + elizaLogger.log("Creating memory for post", post.id); + + // check if it already exists + const memory = await this.runtime.messageManager.getMemoryById( + stringToUuid(post.id + "-" + this.runtime.agentId) + ); + + if (memory) { + elizaLogger.log( + "Memory already exists, skipping timeline population" + ); + break; + } + + await this.runtime.messageManager.createMemory({ + id: stringToUuid(post.id + "-" + this.runtime.agentId), + userId, + content: content, + agentId: this.runtime.agentId, + roomId, + embedding: getEmbeddingZeroVector(), + createdAt: new Date(post.created_at).getTime(), + }); + + elizaLogger.log("Created memory for post", post.id); + } + + elizaLogger.log( + `✨ Deva Client successfully fetched Persona Posts: ${this.posts.length}` + ); + } + + private async startPosting() { + const shouldPostImmediately = + this.runtime.getSetting("POST_IMMEDIATELY") != null && + this.runtime.getSetting("POST_IMMEDIATELY") != "" && + parseBooleanFromText(this.runtime.getSetting("POST_IMMEDIATELY")); + + if (shouldPostImmediately) { + this.generateNewPost(); + } + + return this.setupPostAwaiter(); + } + + private async setupPostAwaiter() { + // since new updates can happen meanwhile, we should check new posts + await this.populatePosts(); + const lastPost: DevaPost | null = + this.posts.length > 0 ? this.posts[this.posts.length - 1] : null; + + const lastPostTimestamp = lastPost + ? new Date(lastPost.updated_at).getTime() + : 0; + + const minMinutes = + parseInt(this.runtime.getSetting("POST_INTERVAL_MIN")) || 90; + const maxMinutes = + parseInt(this.runtime.getSetting("POST_INTERVAL_MAX")) || 180; + const randomMinutes = + Math.floor(Math.random() * (maxMinutes - minMinutes + 1)) + + minMinutes; + const delay = randomMinutes * 60 * 1000; + + if (Date.now() > lastPostTimestamp + delay) { + await this.generateNewPost(); + } + + setTimeout(() => { + this.setupPostAwaiter(); + }, delay); + + elizaLogger.log(`Next post scheduled in ${randomMinutes} minutes`); + } + + private async generateNewPost() { + elizaLogger.log("Generating new Deva Post"); + + const roomId = stringToUuid( + "deva_generate_room-" + this.persona.username + ); + + await this.runtime.ensureUserExists( + this.runtime.agentId, + this.persona.username, + this.persona.display_name, + "deva" + ); + + const topics = this.runtime.character.topics.join(", "); + const state = await this.runtime.composeState({ + userId: this.runtime.agentId, + roomId: roomId, + agentId: this.runtime.agentId, + content: { + text: topics, + action: "", + }, + }); + const customState: State = { + ...state, + agentName: this.persona.display_name, + twitterUserName: this.persona.username, + }; + + const context = composeContext({ + state: customState, + template: + this.runtime.character.templates?.devaPostTemplate || + DEVA_POST_TEMPLATE, + }); + + const newPostContent = await generateText({ + runtime: this.runtime, + context, + modelClass: ModelClass.SMALL, + }); + + // Replace \n with proper line breaks and trim excess spaces + // const formattedPost = newPostContent.replaceAll(/\\n/g, "\n").trim(); + + await this.client.makePost({ + text: newPostContent, + in_reply_to_id: null, + }); + + console.log(newPostContent); + + elizaLogger.log(`New Post published:\n ${newPostContent}`); + } +} diff --git a/packages/client-deva/src/devaClient.ts b/packages/client-deva/src/devaClient.ts new file mode 100644 index 0000000000..f3cbee469f --- /dev/null +++ b/packages/client-deva/src/devaClient.ts @@ -0,0 +1,30 @@ +import { IAgentRuntime, elizaLogger } from "@elizaos/core"; +import { ClientBase } from "./base.ts"; +import { DevaController } from "./controller"; + +export class DevaClient { + private readonly runtime: IAgentRuntime; + private readonly clientBase: ClientBase; + private readonly controller: DevaController; + + constructor(runtime: IAgentRuntime, accessToken: string, baseUrl: string) { + elizaLogger.log("📱 Constructing new DevaClient..."); + this.runtime = runtime; + this.clientBase = new ClientBase(runtime, accessToken, baseUrl); + this.controller = new DevaController(runtime, this.clientBase); + elizaLogger.log("✅ DevaClient constructor completed"); + } + + public async start(): Promise { + elizaLogger.log("🚀 Starting DevaClient..."); + try { + await this.controller.init(); + elizaLogger.log( + "✨ DevaClient successfully launched and is running!" + ); + } catch (error) { + elizaLogger.error("❌ Failed to launch DevaClient:", error); + throw error; + } + } +} diff --git a/packages/client-deva/src/enviroment.ts b/packages/client-deva/src/enviroment.ts new file mode 100644 index 0000000000..2de524ea92 --- /dev/null +++ b/packages/client-deva/src/enviroment.ts @@ -0,0 +1,31 @@ +import { IAgentRuntime } from "@elizaos/core"; +import { z } from "zod"; + +export const devaEnvSchema = z.object({ + DEVA_API_KEY: z.string().min(1, "Deva api key is required"), +}); + +export type DevaConfig = z.infer; + +export async function validateDevaConfig( + runtime: IAgentRuntime +): Promise { + try { + const config = { + DEVA_API_KEY: + runtime.getSetting("DEVA_API_KEY") || process.env.DEVA_API_KEY, + }; + + return devaEnvSchema.parse(config); + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessages = error.errors + .map((err) => `${err.path.join(".")}: ${err.message}`) + .join("\n"); + throw new Error( + `Deva configuration validation failed:\n${errorMessages}` + ); + } + throw error; + } +} diff --git a/packages/client-deva/src/index.ts b/packages/client-deva/src/index.ts new file mode 100644 index 0000000000..f022010a5e --- /dev/null +++ b/packages/client-deva/src/index.ts @@ -0,0 +1,28 @@ +import { IAgentRuntime, Client, elizaLogger } from "@elizaos/core"; +import { DevaClient } from "./devaClient.ts"; +import { validateDevaConfig } from "./enviroment.ts"; + +export const DevaClientInterface: Client = { + async start(runtime: IAgentRuntime) { + await validateDevaConfig(runtime); + + const deva = new DevaClient( + runtime, + runtime.getSetting("DEVA_API_KEY"), + runtime.getSetting("DEVA_API_BASE_URL") + ); + + await deva.start(); + + elizaLogger.success( + `✅ Deva client successfully started for character ${runtime.character.name}` + ); + + return deva; + }, + async stop(_runtime: IAgentRuntime) { + elizaLogger.warn("Deva client does not support stopping yet"); + }, +}; + +export default DevaClientInterface; diff --git a/packages/client-deva/src/templates.ts b/packages/client-deva/src/templates.ts new file mode 100644 index 0000000000..78cb0332a1 --- /dev/null +++ b/packages/client-deva/src/templates.ts @@ -0,0 +1,24 @@ +export const DEVA_POST_TEMPLATE = ` +# Areas of Expertise +{{knowledge}} + +# About {{agentName}} (!{{twitterUserName}}): +{{bio}} +{{lore}} +{{topics}} + +{{providers}} + +{{characterPostExamples}} + +{{postDirections}} + +{{recentMessages}} + +# Task: Generate a post in the voice and style and perspective of {{agentName}}. +Write a 1-3 sentence post that is {{adjective}} about {{topic}} (without mentioning {{topic}} directly), from the perspective of {{agentName}}. Do not add commentary or acknowledge this request, just write the post. +Your response should not contain any questions. Brief, concise statements only. The total character count MUST be less than 280. No emojis. Use \\n\\n (double spaces) between statements. + +# Main Rule: +You must be curious and ask questions mentioning @deva_support to get help. +`; diff --git a/packages/client-deva/src/types.ts b/packages/client-deva/src/types.ts new file mode 100644 index 0000000000..545dd6d10a --- /dev/null +++ b/packages/client-deva/src/types.ts @@ -0,0 +1,21 @@ +export type DevaPersona = { + id: string; + user_id: string; + display_name: string; + username: string; + description: string; + avatar: number; + cover_image: number; +}; + +export type DevaPost = { + id: string; + author_type: string; + text: string; + persona_id: string; + in_reply_to_id: string; + mentioned_profile_persona_id: string; + persona: DevaPersona; + created_at: string; + updated_at: string; +}; diff --git a/packages/client-deva/tsconfig.json b/packages/client-deva/tsconfig.json new file mode 100644 index 0000000000..005fbac9d3 --- /dev/null +++ b/packages/client-deva/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../core/tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/client-deva/tsup.config.ts b/packages/client-deva/tsup.config.ts new file mode 100644 index 0000000000..e42bf4efea --- /dev/null +++ b/packages/client-deva/tsup.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + sourcemap: true, + clean: true, + format: ["esm"], // Ensure you're targeting CommonJS + external: [ + "dotenv", // Externalize dotenv to prevent bundling + "fs", // Externalize fs to use Node.js built-in module + "path", // Externalize other built-ins if necessary + "@reflink/reflink", + "@node-llama-cpp", + "https", + "http", + "agentkeepalive", + // Add other modules you want to externalize + ], +}); diff --git a/packages/core/src/defaultCharacter.ts b/packages/core/src/defaultCharacter.ts index 8faaa64f2b..d8d728633d 100644 --- a/packages/core/src/defaultCharacter.ts +++ b/packages/core/src/defaultCharacter.ts @@ -1,11 +1,11 @@ -import { Character, ModelProviderName } from "./types.ts"; +import { Character, Clients, ModelProviderName } from "./types.ts"; export const defaultCharacter: Character = { name: "Eliza", username: "eliza", plugins: [], - clients: [], - modelProvider: ModelProviderName.LLAMALOCAL, + clients: [Clients.DEVA], + modelProvider: ModelProviderName.OPENAI, settings: { secrets: {}, voice: { diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index ff2151e93f..4bbcea08b8 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -649,6 +649,7 @@ export enum Clients { AUTO = "auto", SLACK = "slack", GITHUB = "github", + DEVA = "deva", } export interface IAgentConfig { @@ -745,6 +746,7 @@ export type Character = { discordMessageHandlerTemplate?: TemplateType; slackMessageHandlerTemplate?: TemplateType; slackShouldRespondTemplate?: TemplateType; + devaPostTemplate?: string; }; /** Character biography */ @@ -1579,4 +1581,4 @@ export enum TranscriptionProvider { export enum ActionTimelineType { ForYou = "foryou", Following = "following", -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a252b4b0d0..5142021233 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -133,6 +133,9 @@ importers: '@elizaos/client-auto': specifier: workspace:* version: link:../packages/client-auto + '@elizaos/client-deva': + specifier: workspace:* + version: link:../packages/client-deva '@elizaos/client-direct': specifier: workspace:* version: link:../packages/client-direct @@ -744,6 +747,25 @@ importers: specifier: 8.3.5 version: 8.3.5(@swc/core@1.10.7(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.5.0)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0) + packages/client-deva: + dependencies: + '@elizaos/core': + specifier: workspace:* + version: link:../core + glob: + specifier: 11.0.0 + version: 11.0.0 + whatwg-url: + specifier: 7.1.0 + version: 7.1.0 + zod: + specifier: 3.23.8 + version: 3.23.8 + devDependencies: + tsup: + specifier: 8.3.5 + version: 8.3.5(@swc/core@1.10.1(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.4.49)(typescript@5.6.3)(yaml@2.6.1) + packages/client-direct: dependencies: '@elizaos/core':