diff --git a/apps/chat/components/ui/multiplayer-actions.tsx b/apps/chat/components/ui/multiplayer-actions.tsx index d51b32a37..d3b544531 100644 --- a/apps/chat/components/ui/multiplayer-actions.tsx +++ b/apps/chat/components/ui/multiplayer-actions.tsx @@ -183,6 +183,7 @@ export function MultiplayerActionsProvider({ children }: MultiplayerActionsProvi const timestamp = new Date(); const message: ActionMessage = { + id: crypto.randomUUID(), method, userId, name, diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/chats-manager.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/chats-manager.ts index 607af52ac..7989fb2d5 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/chats-manager.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/chats-manager.ts @@ -21,7 +21,7 @@ import { import { bindConversationToAgent, } from '../runtime'; -// import { Player } from 'react-agents-client/util/player.mjs'; +import { Player } from 'react-agents-client/util/player.mjs'; import { ReactAgentsMultiplayerConnection } from 'react-agents-client/react-agents-client.mjs'; import { ExtendableMessageEvent, @@ -35,7 +35,7 @@ import { import { TranscribedVoiceInput, } from 'react-agents/devices/audio-transcriber.mjs'; -import { formatConversationMessage } from '../util/message-utils'; +import { createMessageCache, formatConversationMessage } from '../util/message-utils'; // @@ -91,14 +91,23 @@ export class ChatsManager { agent, } = this; + const agentPlayer = new Player(agent.id, { + name: agent.name, + bio: agent.bio, + }); const conversation = new ConversationObject({ - agent, + agentPlayer, getHash: () => { return getChatKey({ room, endpointUrl, }); }, + messageCache: createMessageCache({ + agent, + conversationId: key, + agentId: agent.id, + }), }); this.agent.conversationManager.addConversation(conversation); diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/conversation-object.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/conversation-object.ts index 6cbab9d2d..e36e38871 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/conversation-object.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/conversation-object.ts @@ -12,13 +12,10 @@ import { import { SceneObject } from '../classes/scene-object'; import { Player } from 'react-agents-client/util/player.mjs'; import { ExtendableMessageEvent } from '../util/extendable-message-event'; -import { MessageCache as MessageCacheConstructor, CACHED_MESSAGES_LIMIT } from './message-cache'; -import { loadMessagesFromDatabase } from '../util/loadMessagesFromDatabase'; // export class ConversationObject extends EventTarget { - agent: ActiveAgentObject; // the current agent agentsMap: Map; // note: agents does not include the current agent scene: SceneObject | null; getHash: GetHashFn; // XXX this can be a string, since conversation hashes do not change (?) @@ -27,37 +24,30 @@ export class ConversationObject extends EventTarget { mentionsRegex: RegExp | null = null; constructor({ - agent, agentsMap = new Map(), + agentPlayer, scene = null, getHash = () => '', mentionsRegex = null, + messageCache, }: { - agent: ActiveAgentObject | null; agentsMap?: Map; + agentPlayer: Player; scene?: SceneObject | null; getHash?: GetHashFn; mentionsRegex?: RegExp | null; + messageCache: MessageCache; }) { super(); - this.agent = agent; this.agentsMap = agentsMap; this.scene = scene; this.getHash = getHash; this.mentionsRegex = mentionsRegex; - this.messageCache = new MessageCacheConstructor({ - loader: async () => { - const supabase = this.agent.appContextValue.useSupabase(); - const messages = await loadMessagesFromDatabase({ - supabase, - conversationId: this.getKey(), - agentId: this.agent.id, - limit: CACHED_MESSAGES_LIMIT, - }); - return messages; - }, - }); + this.messageCache = messageCache; + + // add the agent player to the agents map + this.agentsMap.set(agentPlayer.playerId, agentPlayer); } // @@ -94,9 +84,6 @@ export class ConversationObject extends EventTarget { this.scene = scene; } - getAgent() { - return this.agent; - } // setAgent(agent: ActiveAgentObject) { // this.agent = agent; // } @@ -127,7 +114,6 @@ export class ConversationObject extends EventTarget { const allAgents: object[] = [ ...Array.from(this.agentsMap.values()).map(player => player.playerSpec), ]; - this.agent && allAgents.push(this.agent.agentJson); return allAgents; } getEmbeddingString() { diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/discord-manager.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/discord-manager.ts index 52e5d37eb..75d3f7fdd 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/discord-manager.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/discord-manager.ts @@ -13,7 +13,7 @@ import { } from './conversation-object'; import { Player } from 'react-agents-client/util/player.mjs'; import { DiscordBotClient } from '../lib/discord/discord-client'; -import { formatConversationMessage } from '../util/message-utils'; +import { createMessageCache, formatConversationMessage } from '../util/message-utils'; import { bindConversationToAgent, } from '../runtime'; @@ -97,6 +97,45 @@ const bindOutgoing = ({ channelId, userId, }); + } else if (method === 'messageReaction') { + const { + reaction, + id, + } = args as { + reaction: string, + id: string, + }; + + + // get message from conversation by messageId + const message = conversation.getCachedMessages().find(m => m.args.id === id); + + const getDiscordIdForUserId = (userId: string) => { + const agents = conversation.getAgents(); + const agent = agents.find( + agent => agent.playerId === userId + ); + + const discordId = agent?.playerSpec?.mentionId; + return discordId; + }; + + // get userId from message + const userId = message?.userId; + const discordMessageId = message?.metadata?.discordMessageId; + + const discordId = getDiscordIdForUserId(userId); + console.log('discord manager message reaction', { + reaction, + discordMessageId, + userId, + channelId, + discordId, + }); + discordBotClient.input.reactToMessage(reaction, discordMessageId, { + channelId, + userId: discordId, + }); } else { // ignore } @@ -126,6 +165,7 @@ const bindOutgoing = ({ export class DiscordBot extends EventTarget { token: string; + appId: string; channels: DiscordRoomSpec[]; dms: DiscordRoomSpec[]; userWhitelist: string[]; @@ -139,6 +179,7 @@ export class DiscordBot extends EventTarget { // arguments const { token, + appId, channels, dms, userWhitelist, @@ -147,6 +188,7 @@ export class DiscordBot extends EventTarget { jwt, } = args; this.token = token; + this.appId = appId; this.channels = channels; this.dms = dms; this.userWhitelist = userWhitelist; @@ -164,6 +206,7 @@ export class DiscordBot extends EventTarget { // initialize discord bot client const discordBotClient = new DiscordBotClient({ token, + appId, codecs, jwt, name, @@ -247,12 +290,23 @@ export class DiscordBot extends EventTarget { return } + const conversationId = `discord:channel:${channelId}`; + const agentPlayer = new Player(agent.id, { + name: agent.name, + bio: agent.bio, + mentionId: appId, + }); const conversation = new ConversationObject({ - agent, + agentPlayer, getHash: () => { - return `discord:channel:${channelId}`; + return conversationId; }, mentionsRegex: discordMentionRegex, + messageCache: createMessageCache({ + agent, + conversationId, + agentId: agent.id, + }), }); this.agent.conversationManager.addConversation(conversation); @@ -293,15 +347,26 @@ export class DiscordBot extends EventTarget { console.log('dm conversation already exists for this user, skipping', userId); return } - + + const conversationId = `discord:dm:${userId}`; + const agentPlayer = new Player(agent.id, { + name: agent.name, + bio: agent.bio, + mentionId: appId, + }); const conversation = new ConversationObject({ - agent, + agentPlayer, getHash: () => { - return `discord:dm:${userId}`; + return conversationId; }, mentionsRegex: discordMentionRegex, + messageCache: createMessageCache({ + agent, + conversationId, + agentId: agent.id, + }), }); - + this.agent.conversationManager.addConversation(conversation); this.dmConversations.set(userId, conversation); @@ -370,6 +435,7 @@ export class DiscordBot extends EventTarget { text, channelId, // if there is no channelId, it's a DM // XXX discord channel/dm distinction can be made more explicit with a type: string field... + messageId, } = e.data; // look up conversation @@ -391,6 +457,9 @@ export class DiscordBot extends EventTarget { args: { text: formattedMessage, }, + metadata: { + discordMessageId: messageId, + }, }; const id = getIdFromUserId(userId); const agent = { @@ -411,11 +480,71 @@ export class DiscordBot extends EventTarget { }); }; + // message reactions + const _bindIncomingMessageReactions = () => { + const handleReaction = (e: MessageEvent, eventType: string) => { + const { + userId, + messageId, + emoji, + channelId, + userDisplayName, + guildId, + } = e.data; + + console.log(eventType, { + userId, + userDisplayName, + messageId, + emoji, + channelId, + guildId, + }); + + // look up conversation + const conversation = guildId + ? this.channelConversations.get(channelId) ?? null + : this.dmConversations.get(userId) ?? null; + + if (!conversation) return; + + const rawMessageReaction = { + userId, + name: userDisplayName, + method: 'messageReaction', + args: { + text: `${eventType === 'messagereactionadd' ? 'Added' : 'Removed'} reaction '${emoji}' ${eventType === 'messagereactionadd' ? 'to' : 'from'} message ${messageId}`, + }, + metadata: { + discordMessageId: messageId, + }, + }; + + const newMessageReaction = formatConversationMessage(rawMessageReaction, { + agent: { + id: getIdFromUserId(userId), + name: userDisplayName, + }, + }); + + conversation.addLocalMessage(newMessageReaction); + }; + + discordBotClient.output.addEventListener('messagereactionadd', + (e) => handleReaction(e, 'messagereactionadd') + ); + + discordBotClient.output.addEventListener('messagereactionremove', + (e) => handleReaction(e, 'messagereactionremove') + ); + }; + (async () => { _bindChannels(); _bindGuildMemberAdd(); _bindGuildMemberRemove(); _bindIncoming(); + _bindIncomingMessageReactions(); await _connect(); })().catch(err => { console.warn('discord bot error', err); diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/generative-agent-object.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/generative-agent-object.ts index a3841cc45..b67dd1164 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/generative-agent-object.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/generative-agent-object.ts @@ -11,6 +11,7 @@ import type { ActionStep, Evaluator, DebugOptions, + EvaluateOpts, } from '../types'; import { ConversationObject, @@ -110,7 +111,7 @@ export class GenerativeAgentObject { }); // }); } - async evaluate(evaluator: Evaluator) { + async evaluate(evaluator: Evaluator, opts?: EvaluateOpts) { return await this.conversation.typing(async () => { const step = await evaluator.evaluate({ generativeAgent: this, diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/telnyx-manager.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/telnyx-manager.ts index 4d93a7f29..f76e52353 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/telnyx-manager.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/telnyx-manager.ts @@ -14,7 +14,7 @@ import type { TelnyxMessageArgs, TelnyxVoiceArgs, } from '../lib/telnyx/telnyx-client'; -import { formatConversationMessage } from '../util/message-utils'; +import { createMessageCache, formatConversationMessage } from '../util/message-utils'; import { bindConversationToAgent, } from '../runtime'; @@ -175,9 +175,19 @@ export class TelnyxBot extends EventTarget { }); let conversation = this.conversations.get(hash); if (!conversation) { + + const agentPlayer = new Player(agent.id, { + name: agent.name, + bio: agent.bio, + }); conversation = new ConversationObject({ - agent, + agentPlayer, getHash: () => hash, + messageCache: createMessageCache({ + agent, + conversationId: hash, + agentId: agent.id, + }), }); const player = makePlayerFromPhoneNumber(toPhoneNumber); conversation.addAgent(player.playerId, player); diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/twitter-manager.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/twitter-manager.ts index 11662a203..f4ec6e994 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/twitter-manager.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/twitter-manager.ts @@ -13,7 +13,7 @@ import { ConversationObject, } from './conversation-object'; // import { Player } from 'react-agents-client/util/player.mjs'; -import { formatConversationMessage } from '../util/message-utils'; +import { createMessageCache, formatConversationMessage } from '../util/message-utils'; import { bindConversationToAgent, } from '../runtime'; @@ -197,9 +197,19 @@ class TwitterBot { // Create or get conversation let conversation = this.conversations.get(conversation_id); if (!conversation) { + const agentPlayer = new Player(this.agent.id, { + name: this.agent.name, + bio: this.agent.bio, + }); + conversation = new ConversationObject({ - agent: this.agent, + agentPlayer, getHash: () => `twitter:conversation:${conversation_id}`, + messageCache: createMessageCache({ + agent: this.agent, + conversationId: `twitter:conversation:${conversation_id}`, + agentId: this.agent.id, + }), }); this.agent.conversationManager.addConversation(conversation); diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/twitter-spaces-manager.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/twitter-spaces-manager.ts index 22f67808f..f50a74397 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/twitter-spaces-manager.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/classes/twitter-spaces-manager.ts @@ -14,7 +14,7 @@ import { bindConversationToAgent, } from '../runtime'; import { AudioDecodeStream } from 'codecs/audio-decode.mjs'; -import { formatConversationMessage } from '../util/message-utils'; +import { createMessageCache, formatConversationMessage } from '../util/message-utils'; import { QueueManager, } from 'queue-manager'; @@ -24,6 +24,7 @@ import { import { TranscribedVoiceInput, } from '../devices/audio-transcriber.mjs'; +import { Player } from 'react-agents-client/util/player.mjs'; // @@ -80,11 +81,20 @@ class TwitterSpacesBot { live = false; }); + const agentPlayer = new Player(this.agent.id, { + name: this.agent.name, + bio: this.agent.bio, + }); const conversation = new ConversationObject({ - agent, + agentPlayer, getHash: () => { return `twitterSpaces:channel:${url}`; }, + messageCache: createMessageCache({ + agent, + conversationId: `twitterSpaces:channel:${url}`, + agentId: agent.id, + }), }); this.agent.conversationManager.addConversation(conversation); diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/components/core/chat.tsx b/packages/usdk/packages/upstreet-agent/packages/react-agents/components/core/chat.tsx index 0b00c4520..606ca1213 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/components/core/chat.tsx +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/components/core/chat.tsx @@ -2,6 +2,7 @@ import React from 'react'; import dedent from 'dedent'; import { z } from 'zod'; import { Action } from './action'; +import { PendingActionEvent } from '../../types/react-agents'; export const ChatActions = () => { return ( @@ -27,6 +28,38 @@ export const ChatActions = () => { // await e.commit(); // }} /> + { + await e.commit(); + }} + /> ); }; \ No newline at end of file diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/components/plugins/discord.tsx b/packages/usdk/packages/upstreet-agent/packages/react-agents/components/plugins/discord.tsx index e5c4547a3..70d74079b 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/components/plugins/discord.tsx +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/components/plugins/discord.tsx @@ -11,6 +11,7 @@ import { export const Discord: React.FC = (props: DiscordProps) => { const { token, + appId, channels, dms, userWhitelist, @@ -25,6 +26,7 @@ export const Discord: React.FC = (props: DiscordProps) => { if (!conversation) { const args: DiscordArgs = { token, + appId, channels: channels ? (Array.isArray(channels) ? channels : [channels]) : [], dms: dms ? (Array.isArray(dms) ? dms : [dms]) : [], userWhitelist, @@ -39,6 +41,7 @@ export const Discord: React.FC = (props: DiscordProps) => { } }, [ token, + appId, JSON.stringify(channels), JSON.stringify(dms), JSON.stringify(userWhitelist), diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/components/util/default-components.tsx b/packages/usdk/packages/upstreet-agent/packages/react-agents/components/util/default-components.tsx index 364df23f2..d3babc768 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/components/util/default-components.tsx +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/components/util/default-components.tsx @@ -4,6 +4,7 @@ import type { AgentObject, Attachment, FormattedAttachment, + Player, } from '../../types'; import { useAgent, @@ -117,59 +118,47 @@ const ScenePrompt = () => { }; const CharactersPrompt = () => { const conversation = useConversation(); - const agent = useAgent(); - const name = useName(); - const bio = usePersonality(); - if (conversation) { - const agents = conversation.getAgents(); - const currentAgentSpec = { - id: agent.id, - name, - bio, - }; - const agentSpecs = agents.map((agent) => { - const agentSpec = agent.getPlayerSpec() as any; - return { - name: agentSpec?.name, - id: agent.playerId, - bio: agentSpec?.bio, - }; - }); + const activeAgent = useAgent(); - const formatAgent = (agent: any) => { - return [ - `Name: ${agent.name}`, - `UserId: ${agent.id}`, - `Bio: ${agent.bio}`, - ].join('\n'); - }; + if (!conversation) return null; - return ( - - {dedent` - # Your Character - ` + - '\n\n' + - formatAgent(currentAgentSpec) + - (agents.length > 0 - ? ( - '\n\n' + - dedent` - # Other Characters - ` + - '\n\n' + - agentSpecs - .map(formatAgent) - .join('\n\n') - ) - : '' + const agents = conversation.getAgents(); + const agentCharacter = agents.find(agent => agent.playerId === activeAgent.id); + const otherAgents = agents + .filter(agent => agent.playerId !== activeAgent.id); + + const formatAgent = (agent: Player) => { + const agentSpecs = agent.getPlayerSpec() as any; + return [ + `Name: ${agentSpecs?.name}`, + `UserId: ${agent.playerId}`, + `Bio: ${agentSpecs?.bio}`, + ].join('\n'); + }; + + return ( + + {dedent` + # Your Character + ` + + '\n\n' + + formatAgent(agentCharacter) + + (agents.length > 0 + ? ( + '\n\n' + + dedent` + # Other Characters + ` + + '\n\n' + + otherAgents + .map(formatAgent) + .join('\n\n') ) - } - - ); - } else { - return null; - } + : '' + ) + } + + ); }; const ActionsPromptInternal = () => { const actions = useActions(); @@ -288,8 +277,9 @@ const CachedMessagesPrompt = () => { '\n' + cachedMessages .map((action) => { - const { /*userId,*/ name, method, args, attachments = [], timestamp } = action; + const { id, /*userId,*/ name, method, args, attachments = [], timestamp } = action; const j = { + id, // userId, name, method, diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/lib/discord/discord-client.js b/packages/usdk/packages/upstreet-agent/packages/react-agents/lib/discord/discord-client.js index 4089113fc..592df8783 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/lib/discord/discord-client.js +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/lib/discord/discord-client.js @@ -193,6 +193,22 @@ export class DiscordInput { this.queueManager.completeStream(streamId); } + reactToMessage(reaction, messageId, { + channelId, + userId, + } = {}) { + const m = { + method: 'reactToMessage', + args: { + channelId, + reaction, + messageId, + userId, + }, + }; + this.ws.send(JSON.stringify(m)); + } + destroy() { // Clean up any remaining buffers for (const streamId of this.bufferManager.buffers.keys()) { @@ -340,6 +356,20 @@ export class DiscordOutput extends EventTarget { } } + handleMessageReactionAdd(args) { + console.log('handleMessageReactionAdd', args); + this.dispatchEvent(new MessageEvent('messagereactionadd', { + data: args, + })); + } + + handleMessageReactionRemove(args) { + console.log('handleMessageReactionRemove', args); + this.dispatchEvent(new MessageEvent('messagereactionremove', { + data: args, + })); + } + destroy() { for (const stream of this.streams.values()) { stream.destroy(); @@ -536,6 +566,14 @@ export class DiscordBotClient extends EventTarget { this.input.handleVoiceIdle(args); break; } + case 'messagereactionadd': { + this.output.handleMessageReactionAdd(args); + break; + } + case 'messagereactionremove': { + this.output.handleMessageReactionRemove(args); + break; + } default: { console.warn('unhandled json method', method); break; diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/loops/action-loop.tsx b/packages/usdk/packages/upstreet-agent/packages/react-agents/loops/action-loop.tsx index 5969474b4..6c6a8b0c3 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/loops/action-loop.tsx +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/loops/action-loop.tsx @@ -5,6 +5,8 @@ import { ReACTEvaluator } from '../evaluators/react-evaluator'; // import { PerceptionEvent } from '../classes/perception-event'; import { ConversationObject } from '../classes/conversation-object'; import { DeferConversation } from '../components/core/conversation'; +import { createMessageCache } from '../util/message-utils'; +import { Player } from 'react-agents-client/util/player.mjs'; export const ActionLoop = (props: LoopProps) => { return ( @@ -39,10 +41,19 @@ const ActionLoopInner = (props: LoopProps) => { if (contextConversation) { return contextConversation; } else { + const agentPlayer = new Player(agent.id, { + name: agent.name, + bio: agent.bio, + }); const conversationId = crypto.randomUUID(); return new ConversationObject({ - agent, + agentPlayer, getHash: () => conversationId, + messageCache: createMessageCache({ + agent, + conversationId, + agentId: agent.id, + }), }); } }); diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/loops/chat-loop.tsx b/packages/usdk/packages/upstreet-agent/packages/react-agents/loops/chat-loop.tsx index c2621f38c..fc2e8567f 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/loops/chat-loop.tsx +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/loops/chat-loop.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { useAgent } from '../hooks'; import { Perception } from '../components/core/perception'; -import { LoopProps } from '../types'; +import { EvaluateOpts, LoopProps } from '../types'; import { BasicEvaluator } from '../evaluators/basic-evaluator'; export const ChatLoop = (props: LoopProps) => { @@ -39,6 +39,27 @@ export const ChatLoop = (props: LoopProps) => { }} priority={-1} /> + { + const { targetAgent } = e.data; + + + console.log('messageReaction: ', e.data); + (async () => { + const abortController = new AbortController(); + const { signal } = abortController; + + const opts: EvaluateOpts = { + signal, + sendTyping: false, + generativeAgent: targetAgent, + }; + await targetAgent.evaluate(evaluator, opts); + })(); + }} + priority={-1} + /> { diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/runtime.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/runtime.ts index 1203dc6f2..e96cdd7e2 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/runtime.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/runtime.ts @@ -17,7 +17,7 @@ import { ActionPropsAux, AbortableMessageEvent, PendingActionEventData, - // PerceptionPropsAux, + PerceptionPropsAux, } from './types'; import { PendingActionEvent, diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/types/react-agents.d.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/types/react-agents.d.ts index a1851d0a1..7c4e3a7b6 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/types/react-agents.d.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/types/react-agents.d.ts @@ -121,12 +121,14 @@ export type DiscordRoomSpec = RegExp | string; export type DiscordRoomSpecs = DiscordRoomSpec | DiscordRoomSpec[]; export type DiscordProps = { token: string; + appId: string; channels?: DiscordRoomSpecs; dms?: DiscordRoomSpecs; userWhitelist?: string[]; }; export type DiscordArgs = { token: string; + appId: string; channels: DiscordRoomSpec[]; dms: DiscordRoomSpec[]; userWhitelist: string[]; @@ -194,6 +196,7 @@ export type EvaluatorOpts = { export type EvaluateOpts = { generativeAgent: GenerativeAgentObject, signal?: AbortSignal, + sendTyping?: boolean, }; export type Evaluator = { evaluate: (opts: EvaluateOpts) => Promise; @@ -214,6 +217,7 @@ export type Attachment = FormattedAttachment & { url?: string; }; export type ActionMessage = { + id: string; // 8 characters max for prompt optimisation userId: string; name: string; method: string; @@ -222,6 +226,7 @@ export type ActionMessage = { human: boolean; // XXX can be converted to flags hidden: boolean; timestamp: Date; + metadata?: any; }; export type PendingActionMessage = { method: string; @@ -309,7 +314,6 @@ export type Player = { }; export type GetHashFn = () => string; export type ConversationObject = EventTarget & { - agent: ActiveAgentObject; agentsMap: Map; scene: SceneObject | null; getHash: GetHashFn; @@ -331,9 +335,6 @@ export type ConversationObject = EventTarget & { getScene: () => SceneObject | null; setScene: (scene: SceneObject | null) => void; - getAgent: () => ActiveAgentObject | null; - // setAgent: (agent: ActiveAgentObject) => void; - getAgents: () => Player[]; getAgentIds: () => string[]; addAgent: (agentId: string, player: Player) => void; diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/util/agent-features-renderer.tsx b/packages/usdk/packages/upstreet-agent/packages/react-agents/util/agent-features-renderer.tsx index e78e27993..7e1989566 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/util/agent-features-renderer.tsx +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/util/agent-features-renderer.tsx @@ -287,11 +287,11 @@ export const featureRenderers = { ); }, - discord: ({token, channels}) => { + discord: ({token, appId, channels}) => { if (token) { channels = channels && channels.map((c: string) => c.trim()).filter(Boolean); return ( - + ); } else { return null; diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/util/loadMessagesFromDatabase.js b/packages/usdk/packages/upstreet-agent/packages/react-agents/util/loadMessagesFromDatabase.js index 4f8d444fd..065cfb250 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/util/loadMessagesFromDatabase.js +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/util/loadMessagesFromDatabase.js @@ -7,12 +7,14 @@ export async function loadMessagesFromDatabase({ const { error, data } = await supabase .from( 'agent_messages' ) .select([ + 'id', 'method', 'args', 'attachments', 'src_user_id', 'src_name', 'created_at', + 'metadata', ].join(',')) .eq('user_id', agentId) .eq('conversation_id', conversationId) @@ -27,11 +29,13 @@ export async function loadMessagesFromDatabase({ function decodeMessages(messages) { return messages.map( message => ({ + id: message.id, method: message.method, args: message.args, attachments: message.attachments, userId: message.src_user_id, name: message.src_name, timestamp: message.created_at, + metadata: message.metadata, })); } diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/util/message-utils.ts b/packages/usdk/packages/upstreet-agent/packages/react-agents/util/message-utils.ts index 25c3bb7d6..c9180b3e5 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/util/message-utils.ts +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/util/message-utils.ts @@ -1,19 +1,26 @@ import { PendingActionMessage, AgentSpec, + ActiveAgentObject, + ActionMessage, // AgentObject, // ActiveAgentObject, } from '../types'; +import { MessageCache, CACHED_MESSAGES_LIMIT } from '../classes/message-cache'; +import { loadMessagesFromDatabase } from './loadMessagesFromDatabase'; export const formatConversationMessage = (rawMessage: PendingActionMessage, { agent, }: { agent: AgentSpec, -}) => { +}): ActionMessage => { const { id: userId, name } = agent; const { method, args, attachments } = rawMessage; + const id = crypto.randomUUID(); // generate a new id for the message + const timestamp = new Date(); const newMessage = { + id, userId, name, method, @@ -24,4 +31,28 @@ export const formatConversationMessage = (rawMessage: PendingActionMessage, { hidden: false, }; return newMessage; +}; + + +export const createMessageCache = ({ + agent, + conversationId, + agentId, +}: { + agent: ActiveAgentObject; + conversationId: string; + agentId: string; +}) => { + const supabase = agent.appContextValue.useSupabase(); + return new MessageCache({ + loader: async () => { + const messages = await loadMessagesFromDatabase({ + supabase, + conversationId, + agentId, + limit: CACHED_MESSAGES_LIMIT, + }); + return messages; + }, + }); }; \ No newline at end of file diff --git a/packages/usdk/packages/upstreet-agent/packages/react-agents/util/saveMessageToDatabase.js b/packages/usdk/packages/upstreet-agent/packages/react-agents/util/saveMessageToDatabase.js index 39211d815..ca044579d 100644 --- a/packages/usdk/packages/upstreet-agent/packages/react-agents/util/saveMessageToDatabase.js +++ b/packages/usdk/packages/upstreet-agent/packages/react-agents/util/saveMessageToDatabase.js @@ -26,6 +26,7 @@ async function encodeMessage(message, jwt, userId, conversationId) { args: message.args, }), { jwt }); return { + id: message.id, method: message.method, args: message.args, attachments: message.attachments, @@ -35,5 +36,6 @@ async function encodeMessage(message, jwt, userId, conversationId) { src_user_id: message.userId, src_name: message.name, embedding, + metadata: message.metadata, }; }