diff --git a/packages/plugin-asterai/.npmignore b/packages/plugin-asterai/.npmignore new file mode 100644 index 00000000000..0468b4b3648 --- /dev/null +++ b/packages/plugin-asterai/.npmignore @@ -0,0 +1,6 @@ +* + +!dist/** +!package.json +!readme.md +!tsup.config.ts diff --git a/packages/plugin-asterai/README.md b/packages/plugin-asterai/README.md new file mode 100644 index 00000000000..c84bf32f3a5 --- /dev/null +++ b/packages/plugin-asterai/README.md @@ -0,0 +1,80 @@ +# @elizaos/plugin-asterai + +A plugin for interacting with [asterai](https://asterai.io) plugins and agents. + +## Description + +This plugin provides functionality to allow Eliza agents to interact with +asterai plugins and agents. + +This will expand your Eliza character's utility by giving it access to all +the functionality of asterai's ecosystem of marketplace and private plugins +and agents. + +## Installation + +```bash +pnpm install @elizaos/plugin-asterai +``` + +## Configuration + +The plugin requires the following environment variables to be set: + +```typescript +ASTERAI_AGENT_ID= +ASTERAI_PUBLIC_QUERY_KEY= +``` + +## Usage + +### Basic Integration + +```typescript +import { asteraiPlugin } from '@elizaos/plugin-asterai'; +``` + +### Example Usage + +The plugin supports natural language for interacting with the asterai agent +through your Eliza character. + +For example, if your asterai agent can fetch weather data: + +```typescript +"Hey Eliza, how's the weather in LA?" +``` + +Eliza will then query the asterai agent to fetch the information. + +## Development Guide + +### Setting Up Development Environment + +1. Clone the repository +2. Install dependencies: + +```bash +pnpm install +``` + +3. Build the plugin: + +```bash +pnpm run build +``` + +4. Run tests: + +```bash +pnpm run test +``` + +## Contributing + +Contributions are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information. + +## License + +This plugin is part of the Eliza project. See the main project repository for license information. + diff --git a/packages/plugin-asterai/eslint.config.mjs b/packages/plugin-asterai/eslint.config.mjs new file mode 100644 index 00000000000..92fe5bbebef --- /dev/null +++ b/packages/plugin-asterai/eslint.config.mjs @@ -0,0 +1,3 @@ +import eslintGlobalConfig from "../../eslint.config.mjs"; + +export default [...eslintGlobalConfig]; diff --git a/packages/plugin-asterai/package.json b/packages/plugin-asterai/package.json new file mode 100644 index 00000000000..b7b02acb851 --- /dev/null +++ b/packages/plugin-asterai/package.json @@ -0,0 +1,46 @@ +{ + "name": "@elizaos/plugin-asterai", + "version": "0.1.0", + "type": "module", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + "./package.json": "./package.json", + ".": { + "import": { + "@elizaos/source": "./src/index.ts", + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + }, + "files": [ + "dist" + ], + "dependencies": { + "@asterai/client": "0.1.6", + "@elizaos/core": "workspace:*", + "bignumber.js": "9.1.2", + "bs58": "6.0.0", + "elliptic": "6.6.1", + "node-cache": "5.1.2", + "sha3": "2.1.4", + "uuid": "11.0.3", + "zod": "3.23.8" + }, + "devDependencies": { + "@types/elliptic": "6.4.18", + "@types/uuid": "10.0.0", + "tsup": "8.3.5" + }, + "scripts": { + "lines": "find . \\( -name '*.cdc' -o -name '*.ts' \\) -not -path '*/node_modules/*' -not -path '*/tests/*' -not -path '*/deps/*' -not -path '*/dist/*' -not -path '*/imports*' | xargs wc -l", + "build": "tsup --format esm --dts", + "dev": "tsup --format esm --dts --watch", + "lint": "eslint --fix --cache ." + }, + "peerDependencies": { + "whatwg-url": "7.1.0" + } +} diff --git a/packages/plugin-asterai/src/actions/query.ts b/packages/plugin-asterai/src/actions/query.ts new file mode 100644 index 00000000000..c59fbbe632c --- /dev/null +++ b/packages/plugin-asterai/src/actions/query.ts @@ -0,0 +1,72 @@ +import { + elizaLogger, + type Action, + type ActionExample, + type HandlerCallback, + type IAgentRuntime, + type Memory, + type State, +} from "@elizaos/core"; +import { validateAsteraiConfig } from "../environment"; +import {getInitAsteraiClient} from "../index.ts"; + +export const queryAction = { + name: "QUERY_ASTERAI_AGENT", + similes: [ + "MESSAGE_ASTERAI_AGENT", + "TALK_TO_ASTERAI_AGENT", + "SEND_MESSAGE_TO_ASTERAI_AGENT", + "COMMUNICATE_WITH_ASTERAI_AGENT", + ], + description: + "Call this action to send a message to the asterai agent which " + + "has access to external plugins and functionality to answer " + + "the user you are assisting, to help perform a workflow task, etc.", + validate: async (runtime: IAgentRuntime, _message: Memory) => { + const config = await validateAsteraiConfig(runtime); + getInitAsteraiClient( + config.ASTERAI_AGENT_ID, + config.ASTERAI_PUBLIC_QUERY_KEY + ); + return true; + }, + handler: async ( + runtime: IAgentRuntime, + message: Memory, + _state: State, + _options: { [key: string]: unknown }, + callback?: HandlerCallback + ): Promise => { + const config = await validateAsteraiConfig(runtime); + const asteraiClient = getInitAsteraiClient( + config.ASTERAI_AGENT_ID, + config.ASTERAI_PUBLIC_QUERY_KEY + ); + elizaLogger.debug("called QUERY_ASTERAI_AGENT action with message:", message.content); + const response = await asteraiClient.query({ + query: message.content.text + }); + const textResponse = await response.text(); + callback({ + text: textResponse + }); + return true; + }, + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "How's the weather in LA?", + }, + }, + { + user: "{{user2}}", + content: { + text: "Let me check that for you, just a moment.", + action: "QUERY_ASTERAI_AGENT", + }, + }, + ], + ] as ActionExample[][], +} as Action; diff --git a/packages/plugin-asterai/src/environment.ts b/packages/plugin-asterai/src/environment.ts new file mode 100644 index 00000000000..a15c6f919bf --- /dev/null +++ b/packages/plugin-asterai/src/environment.ts @@ -0,0 +1,39 @@ +import { IAgentRuntime } from "@elizaos/core"; +import { z } from "zod"; + +const envSchema = z.object({ + ASTERAI_AGENT_ID: z + .string() + .min(1, "ASTERAI_AGENT_ID is required"), + ASTERAI_PUBLIC_QUERY_KEY: z + .string() + .min(1, "ASTERAI_PUBLIC_QUERY_KEY is required"), +}); + +export type AsteraiConfig = z.infer; + +export async function validateAsteraiConfig( + runtime: IAgentRuntime +): Promise { + try { + const config = { + ASTERAI_AGENT_ID: + runtime.getSetting("ASTERAI_AGENT_ID") || + process.env.ASTERAI_AGENT_ID, + ASTERAI_PUBLIC_QUERY_KEY: + runtime.getSetting("ASTERAI_PUBLIC_QUERY_KEY") || process.env.ASTERAI_PUBLIC_QUERY_KEY, + }; + + return envSchema.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( + `Asterai plugin configuration validation failed:\n${errorMessages}` + ); + } + throw error; + } +} diff --git a/packages/plugin-asterai/src/index.ts b/packages/plugin-asterai/src/index.ts new file mode 100644 index 00000000000..7f77f154b26 --- /dev/null +++ b/packages/plugin-asterai/src/index.ts @@ -0,0 +1,33 @@ +import {asteraiProvider} from "./providers/asterai.provider.ts"; +import type { Plugin } from "@elizaos/core"; +import { queryAction } from "./actions/query"; +import { AsteraiClient } from "@asterai/client"; + +export * from "./environment"; +export * from "./providers/asterai.provider"; + +let asteraiClient: AsteraiClient | null = null; + +export const getInitAsteraiClient = ( + agentId: string, + publicQueryKey: string +): AsteraiClient => { + if (!asteraiClient) { + asteraiClient = new AsteraiClient({ + appId: agentId, + queryKey: publicQueryKey, + }) + } + return asteraiClient; +}; + +export const asteraiPlugin: Plugin = { + name: "asterai", + description: "asterai Plugin for Eliza", + providers: [asteraiProvider], + actions: [queryAction], + evaluators: [], + services: [], +}; + +export default asteraiPlugin; diff --git a/packages/plugin-asterai/src/providers/asterai.provider.ts b/packages/plugin-asterai/src/providers/asterai.provider.ts new file mode 100644 index 00000000000..f8bfc0084a6 --- /dev/null +++ b/packages/plugin-asterai/src/providers/asterai.provider.ts @@ -0,0 +1,63 @@ +import { + elizaLogger, + IAgentRuntime, + Memory, + Provider, + State, UUID, +} from "@elizaos/core"; +import {validateAsteraiConfig} from "../environment.ts"; +import {getInitAsteraiClient} from "../index.ts"; + +const asteraiProvider: Provider = { + get: async ( + runtime: IAgentRuntime, + message: Memory, + _state?: State + ): Promise => { + const hasConfiguredEnv = + !!runtime.getSetting("ASTERAI_AGENT_ID") && + !!runtime.getSetting("ASTERAI_PUBLIC_QUERY_KEY"); + if (!hasConfiguredEnv) { + elizaLogger.error( + "ASTERAI_AGENT_ID or ASTERAI_PUBLIC_QUERY_KEY " + + "not configured, skipping provider" + ); + return null; + } + const config = await validateAsteraiConfig(runtime); + const asteraiClient = getInitAsteraiClient( + config.ASTERAI_AGENT_ID, + config.ASTERAI_PUBLIC_QUERY_KEY + ); + if (!asteraiClient) { + elizaLogger.error("asteraiClient is not initialised"); + return null; + } + const agentId = runtime.getSetting("ASTERAI_AGENT_ID") as UUID; + let agentSummaryMemory = await runtime.knowledgeManager.getMemoryById(agentId); + if (!agentSummaryMemory) { + // Fetch & set summary memory. + const summary = await asteraiClient.fetchSummary(); + elizaLogger.debug("asterai agent summary fetched:", summary); + await runtime.knowledgeManager.createMemory({ + id: agentId, + userId: message.userId, + agentId: message.agentId, + roomId: message.roomId, + createdAt: Date.now(), + content: { + text: summary + } + }); + agentSummaryMemory = await runtime.knowledgeManager.getMemoryById(agentId); + } + if (!agentSummaryMemory) { + elizaLogger.error("failed to initialise agent's summary memory"); + return null; + } + return agentSummaryMemory.content.text; + }, +}; + +// Module exports +export { asteraiProvider }; diff --git a/packages/plugin-asterai/tsconfig.json b/packages/plugin-asterai/tsconfig.json new file mode 100644 index 00000000000..73993deaaf7 --- /dev/null +++ b/packages/plugin-asterai/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../core/tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": [ + "src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/plugin-asterai/tsup.config.ts b/packages/plugin-asterai/tsup.config.ts new file mode 100644 index 00000000000..7f072ccb784 --- /dev/null +++ b/packages/plugin-asterai/tsup.config.ts @@ -0,0 +1,35 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + sourcemap: true, + clean: true, + format: ["esm"], // Ensure you're targeting CommonJS + loader: { + ".cdc": "text", + }, + 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", + "safe-buffer", + "base-x", + "bs58", + "borsh", + "stream", + "buffer", + "querystring", + "amqplib", + // Add other modules you want to externalize + "@onflow/fcl", + "@onflow/types", + "sha3", + "elliptic", + ], +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 87ad1658f82..3d3ab181a84 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1362,6 +1362,49 @@ importers: specifier: 7.1.0 version: 7.1.0 + packages/plugin-asterai: + dependencies: + '@asterai/client': + specifier: 0.1.6 + version: 0.1.6 + '@elizaos/core': + specifier: workspace:* + version: link:../core + bignumber.js: + specifier: 9.1.2 + version: 9.1.2 + bs58: + specifier: 6.0.0 + version: 6.0.0 + elliptic: + specifier: 6.6.1 + version: 6.6.1 + node-cache: + specifier: 5.1.2 + version: 5.1.2 + sha3: + specifier: 2.1.4 + version: 2.1.4 + uuid: + specifier: 11.0.3 + version: 11.0.3 + whatwg-url: + specifier: 7.1.0 + version: 7.1.0 + zod: + specifier: 3.23.8 + version: 3.23.8 + devDependencies: + '@types/elliptic': + specifier: 6.4.18 + version: 6.4.18 + '@types/uuid': + specifier: 10.0.0 + version: 10.0.0 + tsup: + specifier: 8.3.5 + version: 8.3.5(@swc/core@1.10.7(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0) + packages/plugin-autonome: dependencies: '@coral-xyz/anchor': @@ -1566,18 +1609,6 @@ importers: specifier: 7.1.0 version: 7.1.0 - packages/plugin-defillama: - dependencies: - '@elizaos/core': - specifier: workspace:* - version: link:../core - axios: - specifier: ^1.6.0 - version: 1.7.9(debug@4.4.0) - tsup: - specifier: ^8.3.5 - version: 8.3.5(@swc/core@1.10.6(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.4.49)(tsx@4.19.2)(typescript@5.7.2)(yaml@2.7.0) - packages/plugin-depin: dependencies: '@elizaos/core': @@ -2480,6 +2511,9 @@ importers: '@elizaos/core': specifier: workspace:* version: link:../core + '@elizaos/plugin-trustdb': + specifier: workspace:* + version: link:../plugin-trustdb '@uniswap/sdk-core': specifier: 6.0.0 version: 6.0.0 @@ -3159,6 +3193,9 @@ packages: '@asamuzakjp/css-color@2.8.2': resolution: {integrity: sha512-RtWv9jFN2/bLExuZgFFZ0I3pWWeezAHGgrmjqGGWclATl1aDe3yhCUaI0Ilkp6OCk9zX7+FjvDasEX8Q9Rxc5w==} + '@asterai/client@0.1.6': + resolution: {integrity: sha512-Kz2FEg9z3U8G9F8F/87h7szE9i8gHdIM2dCgl2gtqTgiLdgtqaDEk3cGnbL4D67Q9bsciPb/toHFWIUv/QNRJQ==} + '@avnu/avnu-sdk@2.1.1': resolution: {integrity: sha512-y/r/pVT2pU33fGHNVE7A5UIAqQhjEXYQhUh7EodY1s5H7mhRd5U8zHOtI5z6vmpuSnUv0hSvOmmgz8HTuwZ7ew==} engines: {node: '>=18'} @@ -13522,6 +13559,10 @@ packages: resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==} engines: {node: '>=14.18'} + eventsource-parser@2.0.1: + resolution: {integrity: sha512-gMaRLm5zejEH9mNXC54AnIteFI9YwL/q5JKMdBnoG+lEI1JWVGFVk0Taaj9Xb5SKgzIBDZoQX5IzMe44ILWODg==} + engines: {node: '>=18.0.0'} + eventsource-parser@3.0.0: resolution: {integrity: sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==} engines: {node: '>=18.0.0'} @@ -22854,6 +22895,13 @@ snapshots: '@csstools/css-tokenizer': 3.0.3 lru-cache: 11.0.2 + '@asterai/client@0.1.6': + dependencies: + buffer: 6.0.3 + eventsource-parser: 2.0.1 + protobufjs: 7.4.0 + typescript: 5.6.3 + '@avnu/avnu-sdk@2.1.1(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(qs@6.13.1)(starknet@6.18.0(encoding@0.1.13))': dependencies: ethers: 6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) @@ -38906,6 +38954,8 @@ snapshots: eventsource-parser@1.1.2: {} + eventsource-parser@2.0.1: {} + eventsource-parser@3.0.0: {} eventsource@2.0.2: {}