Skip to content

Commit

Permalink
Merge pull request #1029 from odilitime/rest-upgrade
Browse files Browse the repository at this point in the history
feat: client-discord stop implementation / agent improvements
  • Loading branch information
odilitime authored Dec 13, 2024
2 parents f4d8dfe + 4465102 commit ccd70d4
Show file tree
Hide file tree
Showing 5 changed files with 341 additions and 264 deletions.
52 changes: 35 additions & 17 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,42 +323,53 @@ function initializeDatabase(dataDir: string) {
}
}

// also adds plugins from character file into the runtime
export async function initializeClients(
character: Character,
runtime: IAgentRuntime
) {
const clients = [];
const clientTypes =
// each client can only register once
// and if we want two we can explicitly support it
const clients: Record<string, any> = {};
const clientTypes:string[] =
character.clients?.map((str) => str.toLowerCase()) || [];
elizaLogger.log('initializeClients', clientTypes, 'for', character.name)

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

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

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

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

if (clientTypes.includes("farcaster")) {
const farcasterClients = new FarcasterAgentClient(runtime);
farcasterClients.start();
clients.push(farcasterClients);
// why is this one different :(
const farcasterClient = new FarcasterAgentClient(runtime);
if (farcasterClient) {
farcasterClient.start();
clients.farcaster = farcasterClient;
}
}

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

if (character.plugins?.length > 0) {
for (const plugin of character.plugins) {
// if plugin has clients, add those..
if (plugin.clients) {
for (const client of plugin.clients) {
clients.push(await client.start(runtime));
Expand Down Expand Up @@ -387,7 +398,7 @@ function isFalsish(input: any): boolean {
}

function getSecret(character: Character, secret: string) {
return character.settings.secrets?.[secret] || process.env[secret];
return character.settings?.secrets?.[secret] || process.env[secret];
}

let nodePlugin: any | undefined;
Expand All @@ -397,7 +408,7 @@ export async function createAgent(
db: IDatabaseAdapter,
cache: ICacheManager,
token: string
) {
):AgentRuntime {
elizaLogger.success(
elizaLogger.successesTitle,
"Creating runtime for character",
Expand Down Expand Up @@ -430,6 +441,7 @@ export async function createAgent(
modelProvider: character.modelProvider,
evaluators: [],
character,
// character.plugins are handled when clients are added
plugins: [
bootstrapPlugin,
getSecret(character, "CONFLUX_CORE_PRIVATE_KEY")
Expand Down Expand Up @@ -500,7 +512,7 @@ function initializeDbCache(character: Character, db: IDatabaseCacheAdapter) {
return cache;
}

async function startAgent(character: Character, directClient) {
async function startAgent(character: Character, directClient):AgentRuntime {
let db: IDatabaseAdapter & IDatabaseCacheAdapter;
try {
character.id ??= stringToUuid(character.name);
Expand All @@ -519,15 +531,21 @@ async function startAgent(character: Character, directClient) {
await db.init();

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

// start services/plugins/process knowledge
await runtime.initialize();

const clients = await initializeClients(character, runtime);
// start assigned clients
runtime.clients = await initializeClients(character, runtime);

// add to container
directClient.registerAgent(runtime);

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

return runtime;
} catch (error) {
elizaLogger.error(
`Error starting agent for character ${character.name}:`,
Expand Down Expand Up @@ -571,8 +589,8 @@ const startAgents = async () => {
});
}

elizaLogger.log("Chat started. Type 'exit' to quit.");
if (!args["non-interactive"]) {
elizaLogger.log("Chat started. Type 'exit' to quit.");
chat();
}
};
Expand Down
32 changes: 26 additions & 6 deletions packages/client-discord/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { getEmbeddingZeroVector } from "@ai16z/eliza";
import { Character, Client as ElizaClient, IAgentRuntime } from "@ai16z/eliza";
import { stringToUuid } from "@ai16z/eliza";
import { elizaLogger } from "@ai16z/eliza";
import {
getEmbeddingZeroVector,
stringToUuid,
elizaLogger,
Character,
Client as ElizaClient,
IAgentRuntime,
} from "@ai16z/eliza";
import {
Client,
Events,
Expand Down Expand Up @@ -111,6 +115,16 @@ export class DiscordClient extends EventEmitter {
);
}

async stop() {
try {
// disconnect websocket
// this unbinds all the listeners
await this.client.destroy();
} catch(e) {
elizaLogger.error('client-discord instance stop err', e);
}
}

private async onClientReady(readyClient: { user: { tag: any; id: any } }) {
elizaLogger.success(`Logged in as ${readyClient.user?.tag}`);

Expand Down Expand Up @@ -388,7 +402,13 @@ export function startDiscord(runtime: IAgentRuntime) {

export const DiscordClientInterface: ElizaClient = {
start: async (runtime: IAgentRuntime) => new DiscordClient(runtime),
stop: async (_runtime: IAgentRuntime) => {
console.warn("Discord client does not support stopping yet");
stop: async (runtime: IAgentRuntime) => {
try {
// stop it
elizaLogger.log('Stopping discord client', runtime.agentId)
await runtime.clients.discord.stop()
} catch(e) {
elizaLogger.error('client-discord interface stop error', e);
}
},
};
20 changes: 20 additions & 0 deletions packages/core/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export class AgentRuntime implements IAgentRuntime {
services: Map<ServiceType, Service> = new Map();
memoryManagers: Map<string, IMemoryManager> = new Map();
cacheManager: ICacheManager;
clients: Record<string, any>;

registerMemoryManager(manager: IMemoryManager): void {
if (!manager.tableName) {
Expand Down Expand Up @@ -405,6 +406,25 @@ export class AgentRuntime implements IAgentRuntime {
}
}

async stop() {
elizaLogger.debug('runtime::stop - character', this.character)
// stop services, they don't have a stop function
// just initialize

// plugins
// have actions, providers, evaluators (no start/stop)
// services (just initialized), clients

// client have a start
for(const cStr in this.clients) {
const c = this.clients[cStr]
elizaLogger.log('runtime::stop - requesting', cStr, 'client stop for', this.character.name)
c.stop()
}
// we don't need to unregister with directClient
// don't need to worry about knowledge
}

/**
* Processes character knowledge by creating document memories and fragment memories.
* This function takes an array of knowledge items, creates a document memory for each item if it doesn't exist,
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,9 @@ export type Plugin = {
*/
export enum Clients {
DISCORD = "discord",
DIRECT = "direct",
// you can't specify this in characters
// all characters are registered with this
// DIRECT = "direct",
TWITTER = "twitter",
TELEGRAM = "telegram",
FARCASTER = "farcaster",
Expand Down Expand Up @@ -1010,6 +1012,9 @@ export interface IAgentRuntime {
cacheManager: ICacheManager;

services: Map<ServiceType, Service>;
// any could be EventEmitter
// but I think the real solution is forthcoming as a base client interface
clients: Record<string, any>;

initialize(): Promise<void>;

Expand Down
Loading

0 comments on commit ccd70d4

Please sign in to comment.