chore: import upstream snapshot with attribution
CI / Run CI (push) Has been cancelled
CI / check-backend (push) Has been cancelled
CI / check-frontend (push) Has been cancelled
CI / tests (push) Has been cancelled
CI / e2e-tests (push) Has been cancelled
Copilot Setup Steps / copilot-setup-steps (push) Has been cancelled
CI / Run CI (push) Has been cancelled
CI / check-backend (push) Has been cancelled
CI / check-frontend (push) Has been cancelled
CI / tests (push) Has been cancelled
CI / e2e-tests (push) Has been cancelled
Copilot Setup Steps / copilot-setup-steps (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,278 @@
|
||||
import { isEqual } from 'lodash';
|
||||
import { AtomEffect, DefaultValue, atom, selector } from 'recoil';
|
||||
import { Socket } from 'socket.io-client';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { ICommand } from './types/command';
|
||||
import { IMode } from './types/mode';
|
||||
|
||||
import {
|
||||
IAction,
|
||||
IAsk,
|
||||
IAuthConfig,
|
||||
ICallFn,
|
||||
IChainlitConfig,
|
||||
IMcp,
|
||||
IMessageElement,
|
||||
IStep,
|
||||
ITasklistElement,
|
||||
IUser,
|
||||
ThreadHistory
|
||||
} from './types';
|
||||
import { groupByDate } from './utils/group';
|
||||
import { WavRecorder, WavStreamPlayer } from './wavtools';
|
||||
|
||||
export interface ISession {
|
||||
socket: Socket;
|
||||
error?: boolean;
|
||||
}
|
||||
|
||||
export const threadIdToResumeState = atom<string | undefined>({
|
||||
key: 'ThreadIdToResume',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const resumeThreadErrorState = atom<string | undefined>({
|
||||
key: 'ResumeThreadErrorState',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const chatProfileState = atom<string | undefined>({
|
||||
key: 'ChatProfile',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
const sessionIdAtom = atom<string>({
|
||||
key: 'SessionId',
|
||||
default: uuidv4()
|
||||
});
|
||||
|
||||
export const sessionIdState = selector({
|
||||
key: 'SessionIdSelector',
|
||||
get: ({ get }) => get(sessionIdAtom),
|
||||
set: ({ set }, newValue) =>
|
||||
set(sessionIdAtom, newValue instanceof DefaultValue ? uuidv4() : newValue)
|
||||
});
|
||||
|
||||
export const sessionState = atom<ISession | undefined>({
|
||||
key: 'Session',
|
||||
dangerouslyAllowMutability: true,
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const actionState = atom<IAction[]>({
|
||||
key: 'Actions',
|
||||
default: []
|
||||
});
|
||||
|
||||
export const messagesState = atom<IStep[]>({
|
||||
key: 'Messages',
|
||||
dangerouslyAllowMutability: true,
|
||||
default: []
|
||||
});
|
||||
|
||||
export const commandsState = atom<ICommand[]>({
|
||||
key: 'Commands',
|
||||
default: []
|
||||
});
|
||||
|
||||
export const modesState = atom<IMode[]>({
|
||||
key: 'Modes',
|
||||
default: []
|
||||
});
|
||||
|
||||
export const tokenCountState = atom<number>({
|
||||
key: 'TokenCount',
|
||||
default: 0
|
||||
});
|
||||
|
||||
export const loadingState = atom<boolean>({
|
||||
key: 'Loading',
|
||||
default: false
|
||||
});
|
||||
|
||||
export const askUserState = atom<IAsk | undefined>({
|
||||
key: 'AskUser',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const wavRecorderState = atom({
|
||||
key: 'WavRecorder',
|
||||
dangerouslyAllowMutability: true,
|
||||
default: new WavRecorder()
|
||||
});
|
||||
|
||||
export const wavStreamPlayerState = atom({
|
||||
key: 'WavStreamPlayer',
|
||||
dangerouslyAllowMutability: true,
|
||||
default: new WavStreamPlayer()
|
||||
});
|
||||
|
||||
export const audioConnectionState = atom<'connecting' | 'on' | 'off'>({
|
||||
key: 'AudioConnection',
|
||||
default: 'off'
|
||||
});
|
||||
|
||||
export const isAiSpeakingState = atom({
|
||||
key: 'isAiSpeaking',
|
||||
default: false
|
||||
});
|
||||
|
||||
export const callFnState = atom<ICallFn | undefined>({
|
||||
key: 'CallFn',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const chatSettingsInputsState = atom<any>({
|
||||
key: 'ChatSettings',
|
||||
default: []
|
||||
});
|
||||
|
||||
export const chatSettingsDefaultValueSelector = selector({
|
||||
key: 'ChatSettingsValue/Default',
|
||||
get: ({ get }) => {
|
||||
const chatSettings = get(chatSettingsInputsState);
|
||||
|
||||
const collectInitialValues = (
|
||||
inputs: any[],
|
||||
acc: Record<string, any>
|
||||
): Record<string, any> => {
|
||||
if (!Array.isArray(inputs)) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
inputs.forEach((input) => {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(input?.inputs) && input.inputs.length > 0) {
|
||||
// Handle tabs
|
||||
collectInitialValues(input.inputs, acc);
|
||||
} else if (input?.id !== undefined) {
|
||||
acc[input.id] = input.initial;
|
||||
}
|
||||
});
|
||||
|
||||
return acc;
|
||||
};
|
||||
|
||||
return collectInitialValues(chatSettings, {});
|
||||
}
|
||||
});
|
||||
|
||||
export const chatSettingsValueState = atom<Record<string, any>>({
|
||||
key: 'ChatSettingsValue',
|
||||
default: chatSettingsDefaultValueSelector
|
||||
});
|
||||
|
||||
export const elementState = atom<IMessageElement[]>({
|
||||
key: 'DisplayElements',
|
||||
default: []
|
||||
});
|
||||
|
||||
export const tasklistState = atom<ITasklistElement[]>({
|
||||
key: 'TasklistElements',
|
||||
default: []
|
||||
});
|
||||
|
||||
export const firstUserInteraction = atom<string | undefined>({
|
||||
key: 'FirstUserInteraction',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const userState = atom<IUser | undefined | null>({
|
||||
key: 'User',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const configState = atom<IChainlitConfig | undefined>({
|
||||
key: 'ChainlitConfig',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const authState = atom<IAuthConfig | undefined>({
|
||||
key: 'AuthConfig',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const threadHistoryState = atom<ThreadHistory | undefined>({
|
||||
key: 'ThreadHistory',
|
||||
default: {
|
||||
threads: undefined,
|
||||
currentThreadId: undefined,
|
||||
timeGroupedThreads: undefined,
|
||||
pageInfo: undefined
|
||||
},
|
||||
effects: [
|
||||
({ setSelf, onSet }: { setSelf: any; onSet: any }) => {
|
||||
onSet(
|
||||
(
|
||||
newValue: ThreadHistory | undefined,
|
||||
oldValue: ThreadHistory | undefined
|
||||
) => {
|
||||
let timeGroupedThreads = newValue?.timeGroupedThreads;
|
||||
if (
|
||||
newValue?.threads &&
|
||||
!isEqual(newValue.threads, oldValue?.timeGroupedThreads)
|
||||
) {
|
||||
timeGroupedThreads = groupByDate(newValue.threads);
|
||||
}
|
||||
|
||||
setSelf({
|
||||
...newValue,
|
||||
timeGroupedThreads
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
export const sideViewState = atom<
|
||||
{ title: string; elements: IMessageElement[]; key?: string } | undefined
|
||||
>({
|
||||
key: 'SideView',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
export const currentThreadIdState = atom<string | undefined>({
|
||||
key: 'CurrentThreadId',
|
||||
default: undefined
|
||||
});
|
||||
|
||||
const localStorageEffect =
|
||||
<T>(key: string): AtomEffect<T> =>
|
||||
({ setSelf, onSet }) => {
|
||||
// When the atom is first initialized, try to get its value from localStorage
|
||||
const savedValue = localStorage.getItem(key);
|
||||
if (savedValue != null) {
|
||||
try {
|
||||
setSelf(JSON.parse(savedValue));
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error parsing localStorage value for key "${key}":`,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Subscribe to state changes and update localStorage
|
||||
onSet((newValue, _, isReset) => {
|
||||
if (isReset) {
|
||||
localStorage.removeItem(key);
|
||||
} else {
|
||||
localStorage.setItem(key, JSON.stringify(newValue));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const mcpState = atom<IMcp[]>({
|
||||
key: 'Mcp',
|
||||
default: [],
|
||||
effects: [localStorageEffect<IMcp[]>('mcp_storage_key')]
|
||||
});
|
||||
|
||||
export const favoriteMessagesState = atom<IStep[]>({
|
||||
key: 'favoriteMessagesState',
|
||||
default: []
|
||||
});
|
||||
Reference in New Issue
Block a user