Skip to content

Commit

Permalink
news plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
ileana-pr committed Dec 19, 2024
1 parent 8989bfc commit 54af42b
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 838 deletions.
202 changes: 111 additions & 91 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,62 @@
import { PostgresDatabaseAdapter } from "@ai16z/adapter-postgres";
import { SqliteDatabaseAdapter } from "@ai16z/adapter-sqlite";
import { AutoClientInterface } from "@ai16z/client-auto";
import { DirectClientInterface } from "@ai16z/client-direct";
import { DiscordClientInterface } from "@ai16z/client-discord";
import { FarcasterAgentClient } from "@ai16z/client-farcaster";
import { LensAgentClient } from "@ai16z/client-lens";
import { SlackClientInterface } from "@ai16z/client-slack";
import { TelegramClientInterface } from "@ai16z/client-telegram";
import { TwitterClientInterface } from "@ai16z/client-twitter";
import { FarcasterAgentClient } from "@ai16z/client-farcaster";
import {
AgentRuntime,
CacheManager,
Character,
Clients,
DbCacheAdapter,
defaultCharacter,
elizaLogger,
FsCacheAdapter,
IAgentRuntime,
ICacheManager,
IDatabaseAdapter,
IDatabaseCacheAdapter,
ModelProviderName,
defaultCharacter,
elizaLogger,
settings,
stringToUuid,
validateCharacterConfig,
} from "@ai16z/eliza";
import { zgPlugin } from "@ai16z/plugin-0g";
import createGoatPlugin from "@ai16z/plugin-goat";
import { bootstrapPlugin } from "@ai16z/plugin-bootstrap";
import { helloWorldPlugin } from "@ai16z/plugin-helloworld";
import createGoatPlugin from "@ai16z/plugin-goat";
// import { intifacePlugin } from "@ai16z/plugin-intiface";
import { DirectClient } from "@ai16z/client-direct";
import { aptosPlugin } from "@ai16z/plugin-aptos";
import {
advancedTradePlugin,
coinbaseCommercePlugin,
coinbaseMassPaymentsPlugin,
tradePlugin,
tokenContractPlugin,
tradePlugin,
webhookPlugin,
advancedTradePlugin,
} from "@ai16z/plugin-coinbase";
import { confluxPlugin } from "@ai16z/plugin-conflux";
import { imageGenerationPlugin } from "@ai16z/plugin-image-generation";
import { evmPlugin } from "@ai16z/plugin-evm";
import { storyPlugin } from "@ai16z/plugin-story";
import { flowPlugin } from "@ai16z/plugin-flow";
import { imageGenerationPlugin } from "@ai16z/plugin-image-generation";
import { multiversxPlugin } from "@ai16z/plugin-multiversx";
import { nearPlugin } from "@ai16z/plugin-near";
import { nftGenerationPlugin } from "@ai16z/plugin-nft-generation";
import { createNodePlugin } from "@ai16z/plugin-node";
import { solanaPlugin } from "@ai16z/plugin-solana";
import { teePlugin, TEEMode } from "@ai16z/plugin-tee";
import { aptosPlugin, TransferAptosToken } from "@ai16z/plugin-aptos";
import { flowPlugin } from "@ai16z/plugin-flow";
import { suiPlugin } from "@ai16z/plugin-sui";
import { TEEMode, teePlugin } from "@ai16z/plugin-tee";
import { tonPlugin } from "@ai16z/plugin-ton";
import { zksyncEraPlugin } from "@ai16z/plugin-zksync-era";
import Database from "better-sqlite3";
import fs from "fs";
import path from "path";
import readline from "readline";
import { fileURLToPath } from "url";
import yargs from "yargs";

Expand All @@ -61,8 +70,8 @@ export const wait = (minTime: number = 1000, maxTime: number = 3000) => {
};

const logFetch = async (url: string, options: any) => {
elizaLogger.info(`Fetching ${url}`);
elizaLogger.info(options);
elizaLogger.debug(`Fetching ${url}`);
elizaLogger.debug(JSON.stringify(options, null, 2));
return fetch(url, options);
};

Expand Down Expand Up @@ -291,6 +300,11 @@ export function getTokenForProvider(
character.settings?.secrets?.VENICE_API_KEY ||
settings.VENICE_API_KEY
);
case ModelProviderName.AKASH_CHAT_API:
return (
character.settings?.secrets?.AKASH_CHAT_API_KEY ||
settings.AKASH_CHAT_API_KEY
);
}
}

Expand Down Expand Up @@ -331,41 +345,57 @@ export async function initializeClients(
// each client can only register once
// and if we want two we can explicitly support it
const clients: Record<string, any> = {};
const clientTypes:string[] =
const clientTypes: string[] =
character.clients?.map((str) => str.toLowerCase()) || [];
elizaLogger.log('initializeClients', clientTypes, 'for', character.name)
elizaLogger.log("initializeClients", clientTypes, "for", character.name);

if (clientTypes.includes("auto")) {
if (clientTypes.includes(Clients.DIRECT)) {
const autoClient = await AutoClientInterface.start(runtime);
if (autoClient) clients.auto = autoClient;
}

if (clientTypes.includes("discord")) {
if (clientTypes.includes(Clients.DISCORD)) {
const discordClient = await DiscordClientInterface.start(runtime);
if (discordClient) clients.discord = discordClient;
}

if (clientTypes.includes("telegram")) {
if (clientTypes.includes(Clients.TELEGRAM)) {
const telegramClient = await TelegramClientInterface.start(runtime);
if (telegramClient) clients.telegram = telegramClient;
}

if (clientTypes.includes("twitter")) {
TwitterClientInterface.enableSearch = !isFalsish(getSecret(character, "TWITTER_SEARCH_ENABLE"));
if (clientTypes.includes(Clients.TWITTER)) {
const twitterClient = await TwitterClientInterface.start(runtime);
if (twitterClient) clients.twitter = twitterClient;

if (twitterClient) {
clients.twitter = twitterClient;
(twitterClient as any).enableSearch = !isFalsish(
getSecret(character, "TWITTER_SEARCH_ENABLE")
);
}
}

if (clientTypes.includes("farcaster")) {
if (clientTypes.includes(Clients.FARCASTER)) {
// why is this one different :(
const farcasterClient = new FarcasterAgentClient(runtime);
if (farcasterClient) {
farcasterClient.start();
clients.farcaster = farcasterClient;
farcasterClient.start();
clients.farcaster = farcasterClient;
}
}
if (clientTypes.includes("lens")) {
const lensClient = new LensAgentClient(runtime);
lensClient.start();
clients.lens = lensClient;
}

elizaLogger.log('client keys', Object.keys(clients));
elizaLogger.log("client keys", Object.keys(clients));

// TODO: Add Slack client to the list
if (clientTypes.includes("slack")) {
const slackClient = await SlackClientInterface.start(runtime);
if (slackClient) clients.push(slackClient);
}

if (character.plugins?.length > 0) {
for (const plugin of character.plugins) {
Expand All @@ -388,10 +418,19 @@ function isFalsish(input: any): boolean {
}

// Convert input to a string if it's not null or undefined
const value = input == null ? '' : String(input);
const value = input == null ? "" : String(input);

// List of common falsish string representations
const falsishValues = ['false', '0', 'no', 'n', 'off', 'null', 'undefined', ''];
const falsishValues = [
"false",
"0",
"no",
"n",
"off",
"null",
"undefined",
"",
];

// Check if the value (trimmed and lowercased) is in the falsish list
return falsishValues.includes(value.trim().toLowerCase());
Expand Down Expand Up @@ -453,17 +492,33 @@ export async function createAgent(
!getSecret(character, "WALLET_PUBLIC_KEY")?.startsWith("0x"))
? solanaPlugin
: null,
getSecret(character, "EVM_PRIVATE_KEY") ||
(getSecret(character, "NEAR_ADDRESS") ||
getSecret(character, "NEAR_WALLET_PUBLIC_KEY")) &&
getSecret(character, "NEAR_WALLET_SECRET_KEY")
? nearPlugin
: null,
getSecret(character, "EVM_PUBLIC_KEY") ||
(getSecret(character, "WALLET_PUBLIC_KEY") &&
getSecret(character, "WALLET_PUBLIC_KEY")?.startsWith("0x"))
? evmPlugin
: null,
(getSecret(character, "SOLANA_PUBLIC_KEY") ||
(getSecret(character, "WALLET_PUBLIC_KEY") &&
!getSecret(character, "WALLET_PUBLIC_KEY")?.startsWith(
"0x"
))) &&
getSecret(character, "SOLANA_ADMIN_PUBLIC_KEY") &&
getSecret(character, "SOLANA_PRIVATE_KEY") &&
getSecret(character, "SOLANA_ADMIN_PRIVATE_KEY")
? nftGenerationPlugin
: null,
getSecret(character, "ZEROG_PRIVATE_KEY") ? zgPlugin : null,
getSecret(character, "COINBASE_COMMERCE_KEY")
? coinbaseCommercePlugin
: null,
getSecret(character, "FAL_API_KEY") ||
getSecret(character, "OPENAI_API_KEY") ||
getSecret(character, "VENICE_API_KEY") ||
getSecret(character, "HEURIST_API_KEY")
? imageGenerationPlugin
: null,
Expand All @@ -490,6 +545,11 @@ export async function createAgent(
? flowPlugin
: null,
getSecret(character, "APTOS_PRIVATE_KEY") ? aptosPlugin : null,
getSecret(character, "MVX_PRIVATE_KEY") ? multiversxPlugin : null,
getSecret(character, "ZKSYNC_PRIVATE_KEY") ? zksyncEraPlugin : null,
getSecret(character, "TON_PRIVATE_KEY") ? tonPlugin : null,
getSecret(character, "SUI_PRIVATE_KEY") ? suiPlugin : null,
getSecret(character, "STORY_PRIVATE_KEY") ? storyPlugin : null,
].filter(Boolean),
providers: [],
actions: [],
Expand All @@ -512,7 +572,10 @@ function initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {
return cache;
}

async function startAgent(character: Character, directClient): Promise<AgentRuntime> {
async function startAgent(
character: Character,
directClient
): Promise<AgentRuntime> {
let db: IDatabaseAdapter & IDatabaseCacheAdapter;
try {
character.id ??= stringToUuid(character.name);
Expand All @@ -531,7 +594,12 @@ async function startAgent(character: Character, directClient): Promise<AgentRunt
await db.init();

const cache = initializeDbCache(character, db);
const runtime:AgentRuntime = await createAgent(character, db, cache, token);
const runtime: AgentRuntime = await createAgent(
character,
db,
cache,
token
);

// start services/plugins/process knowledge
await runtime.initialize();
Expand All @@ -543,15 +611,15 @@ async function startAgent(character: Character, directClient): Promise<AgentRunt
directClient.registerAgent(runtime);

// report to console
elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`)
elizaLogger.debug(`Started ${character.name} as ${runtime.agentId}`);

return runtime;
} catch (error) {
elizaLogger.error(
`Error starting agent for character ${character.name}:`,
error
);
console.error(error);
elizaLogger.error(error);
if (db) {
await db.close();
}
Expand All @@ -560,7 +628,8 @@ async function startAgent(character: Character, directClient): Promise<AgentRunt
}

const startAgents = async () => {
const directClient = await DirectClientInterface.start({} as IAgentRuntime);
const directClient = new DirectClient();
const serverPort = parseInt(settings.SERVER_PORT || "3000");
const args = parseArguments();

let charactersArg = args.characters || args.character;
Expand All @@ -579,67 +648,18 @@ const startAgents = async () => {
elizaLogger.error("Error starting agents:", error);
}

function chat() {
const agentId = characters[0].name ?? "Agent";
rl.question("You: ", async (input) => {
await handleUserInput(input, agentId);
if (input.toLowerCase() !== "exit") {
chat(); // Loop back to ask another question
}
});
}
// upload some agent functionality into directClient
directClient.startAgent = async character => {
// wrap it so we don't have to inject directClient later
return startAgent(character, directClient)
};
directClient.start(serverPort);

if (!args["non-interactive"]) {
elizaLogger.log("Chat started. Type 'exit' to quit.");
chat();
}
elizaLogger.log("Visit the following URL to chat with your agents:");
elizaLogger.log(`http://localhost:5173`);
};

startAgents().catch((error) => {
elizaLogger.error("Unhandled error in startAgents:", error);
process.exit(1); // Exit the process after logging
});

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

async function handleUserInput(input, agentId) {
if (input.toLowerCase() === "exit") {
gracefulExit();
}

try {
const serverPort = parseInt(settings.SERVER_PORT || "3000");

const response = await fetch(
`http://localhost:${serverPort}/${agentId}/message`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
text: input,
userId: "user",
userName: "User",
}),
}
);

const data = await response.json();
data.forEach((message) =>
elizaLogger.log(`${"Agent"}: ${message.text}`)
);
} catch (error) {
console.error("Error fetching response:", error);
}
}

async function gracefulExit() {
elizaLogger.log("Terminating and cleaning up resources...");
rl.close();
process.exit(0);
}

rl.on("SIGINT", gracefulExit);
rl.on("SIGTERM", gracefulExit);
Loading

0 comments on commit 54af42b

Please sign in to comment.