Skip to content

Commit

Permalink
Cache AI bots to avoid re-requests (#210)
Browse files Browse the repository at this point in the history
* Cache AI bots to avoid re-requests

* Fix default bot
  • Loading branch information
crspeller authored Jul 8, 2024
1 parent 606e2b7 commit 90810c9
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 40 deletions.
47 changes: 26 additions & 21 deletions webapp/src/bots.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import {useState, useEffect} from 'react';

import {useSelector} from 'react-redux';
import {useDispatch, useSelector} from 'react-redux';

import {GlobalState} from '@mattermost/types/store';

import {getAIBots} from '@/client';

import manifest from './manifest';
import {BotsHandler} from './redux';

export interface LLMBot {
id: string;
displayName: string;
Expand All @@ -17,9 +20,10 @@ export interface LLMBot {
const defaultBotLocalStorageKey = 'defaultBot';

export const useBotlist = () => {
const [bots, setBots] = useState<LLMBot[] | null>(null);
const [activeBot, setActiveBotState] = useState<LLMBot | null>(null);
const bots = useSelector<GlobalState, LLMBot[] | null>((state: any) => state['plugins-' + manifest.id].bots);
const [activeBot, setActiveBot] = useState<LLMBot | null>(null);
const currentUserId = useSelector<GlobalState, string>((state) => state.entities.users.currentUserId);
const dispatch = useDispatch();

// Load bots
useEffect(() => {
Expand All @@ -29,26 +33,27 @@ export const useBotlist = () => {
return;
}

// Set default bot to the one in local storage otherwise default to the first bot (which should be the server default)
let newActiveBot = fetchedBots[0];
if (fetchedBots.length > 1) {
const defaultBotName = localStorage.getItem(defaultBotLocalStorageKey);
const defaultBot = fetchedBots.find((bot: LLMBot) => bot.username === defaultBotName);
if (defaultBot) {
newActiveBot = defaultBot;
}
}

setBots(fetchedBots);
setActiveBotState(newActiveBot);
dispatch({
type: BotsHandler,
bots: fetchedBots,
});
};
fetchBots();
}, [currentUserId]);
if (!bots) {
fetchBots();
}
}, [currentUserId, bots, dispatch]);

const setActiveBot = (bot: LLMBot) => {
setActiveBotState(bot);
localStorage.setItem(defaultBotLocalStorageKey, bot.username);
};
useEffect(() => {
const defaultActiveBotName = localStorage.getItem(defaultBotLocalStorageKey);
setActiveBot(bots?.find((bot: LLMBot) => bot.username === defaultActiveBotName) || bots?.[0] || null);
}, [bots]);

useEffect(() => {
if (!activeBot) {
return;
}
localStorage.setItem(defaultBotLocalStorageKey, activeBot.username);
}, [activeBot]);

return {bots, activeBot, setActiveBot};
};
26 changes: 8 additions & 18 deletions webapp/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {doReaction, doSummarize, getAIDirectChannel, trackEvent} from './client'
import {setOpenRHSAction} from './redux_actions';
import {BotUsername, TelemetryEvents, TelemetrySources} from './constants';
import PostEventListener from './websocket';
import {setupRedux} from './redux';
import {BotsHandler, setupRedux} from './redux';
import UnreadsSumarize from './components/unreads_summarize';
import {PostbackPost} from './components/postback_post';

Expand Down Expand Up @@ -84,23 +84,6 @@ export default class Plugin {
if ((window as any).Components.CreatePost) {
rhs = registry.registerRightHandSidebarComponent(RHS, RHSTitle);
setOpenRHSAction(rhs.showRHSPlugin);

registry.registerReducer((state = {}, action: any) => {
switch (action.type) {
case 'SET_AI_BOT_CHANNEL':
return {
...state,
botChannelId: action.botChannelId,
};
case 'SELECT_AI_POST':
return {
...state,
selectedPostId: action.postId,
};
default:
return state;
}
});
}

let currentUserId = store.getState().entities.users.currentUserId;
Expand Down Expand Up @@ -136,6 +119,13 @@ export default class Plugin {
;
};

registry.registerWebSocketEventHandler('config_changed', (message: any) => {
store.dispatch({
type: BotsHandler,
bots: null,
} as any);
});

registry.registerPostTypeComponent('custom_llmbot', LLMBotPostWithWebsockets);
registry.registerPostTypeComponent('custom_llm_postback', PostbackPost);
if (registry.registerPostActionComponent) {
Expand Down
34 changes: 33 additions & 1 deletion webapp/src/redux.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ import {combineReducers, Store, Action} from 'redux';
import {GlobalState} from '@mattermost/types/lib/store';

import {makeCallsPostButtonClickedHandler} from './calls_button';
import manifest from './manifest';

type WebappStore = Store<GlobalState, Action<Record<string, unknown>>>

const CallsClickHandler = 'calls_post_button_clicked_handler';
export const BotsHandler = manifest.id + '_bots';

export async function setupRedux(registry: any, store: WebappStore) {
const reducer = combineReducers({
callsPostButtonClickedTranscription,
bots,
botChannelId,
selectedPostId,
});

registry.registerReducer(reducer);

store.dispatch({
type: CallsClickHandler as any,
handler: makeCallsPostButtonClickedHandler(store.dispatch),
Expand Down Expand Up @@ -46,3 +51,30 @@ function callsPostButtonClickedTranscription(state = false, action: any) {
return state;
}
}

function bots(state = null, action: any) {
switch (action.type) {
case BotsHandler:
return action.bots;
default:
return state;
}
}

function botChannelId(state = '', action: any) {
switch (action.type) {
case 'SET_AI_BOT_CHANNEL':
return action.botChannelId;
default:
return state;
}
}

function selectedPostId(state = '', action: any) {
switch (action.type) {
case 'SELECT_AI_POST':
return action.postId;
default:
return state;
}
}

0 comments on commit 90810c9

Please sign in to comment.