chore: add back data-provider

This commit is contained in:
Daniel Avila 2023-07-30 10:37:25 -04:00 committed by Danny Avila
parent 488b373695
commit 77a76f8511
16 changed files with 1323 additions and 1 deletions

View file

@ -13,7 +13,13 @@ module.exports = {
'plugin:jest/recommended',
'prettier',
],
ignorePatterns: ['client/dist/**/*', 'client/public/**/*', 'e2e/playwright-report/**/*'],
ignorePatterns: [
'client/dist/**/*',
'client/public/**/*',
'e2e/playwright-report/**/*',
'packages/data-provider/types/**/*',
'packages/data-provider/dist/**/*',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
@ -105,6 +111,18 @@ module.exports = {
'plugin:@typescript-eslint/recommended',
],
},
{
files: './packages/data-provider/**/*.ts',
overrides: [
{
files: '**/*.ts',
parser: '@typescript-eslint/parser',
parserOptions: {
project: './packages/data-provider/tsconfig.json',
},
},
],
},
],
settings: {
react: {

1
packages/data-provider/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
node_modules/

View file

@ -0,0 +1,4 @@
module.exports = {
presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'],
plugins: ['babel-plugin-replace-ts-export-assignment'],
};

View file

@ -0,0 +1,18 @@
module.exports = {
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!<rootDir>/node_modules/'],
coveragePathIgnorePatterns: ['/node_modules/', '/dist/'],
coverageReporters: ['text', 'cobertura'],
testResultsProcessor: 'jest-junit',
moduleNameMapper: {
'^@src/(.*)$': '<rootDir>/src/$1',
},
// coverageThreshold: {
// global: {
// statements: 58,
// branches: 49,
// functions: 50,
// lines: 57,
// },
// },
restoreMocks: true,
};

View file

@ -0,0 +1,49 @@
{
"name": "librechat-data-provider",
"version": "0.1.1",
"description": "data services for librechat apps",
"main": "dist/index.js",
"module": "dist/index.es.js",
"types": "types/index.d.ts",
"scripts": {
"clean": "rimraf dist",
"build": "npm run clean && rollup -c --silent --bundleConfigAsCjs",
"build:watch": "rollup -c -w",
"test": "jest --coverage --watch",
"test:ci": "jest --coverage --ci",
"verify": "npm run test:ci"
},
"repository": {
"type": "git",
"url": "git+https://github.com/danny-avila/librechat-data-provider.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/danny-avila/librechat-data-provider/issues"
},
"homepage": "https://github.com/danny-avila/LibreChat#readme",
"dependencies": {
"@tanstack/react-query": "^4.28.0",
"axios": "^1.3.4"
},
"devDependencies": {
"@babel/preset-env": "^7.21.5",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.0",
"@rollup/plugin-commonjs": "^25.0.2",
"@rollup/plugin-node-resolve": "^15.1.0",
"@tanstack/query-core": "^4.29.19",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.0",
"jest": "^29.5.0",
"jest-junit": "^16.0.0",
"rimraf": "^5.0.1",
"rollup": "^3.26.0",
"rollup-plugin-typescript2": "^0.35.0",
"typescript": "^5.0.4"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
}
}

View file

@ -0,0 +1,31 @@
import typescript from 'rollup-plugin-typescript2';
import resolve from '@rollup/plugin-node-resolve';
import pkg from './package.json';
export default [
{
input: 'src/index.ts',
output: [
{
file: pkg.main,
format: 'cjs',
},
{
file: pkg.module,
format: 'esm',
},
],
...{
external: [
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.devDependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
],
preserveSymlinks: true,
plugins: [
resolve(),
typescript({ useTsconfigDeclarationDir: true, tsconfig: './tsconfig.json' }),
],
},
},
];

View file

@ -0,0 +1,95 @@
export const user = () => {
return '/api/user';
};
export const userPlugins = () => {
return '/api/user/plugins';
};
export const messages = (id: string) => {
return `/api/messages/${id}`;
};
export const abortRequest = (endpoint: string) => {
return `/api/ask/${endpoint}/abort`;
};
export const conversations = (pageNumber: string) => {
return `/api/convos?pageNumber=${pageNumber}`;
};
export const conversationById = (id: string) => {
return `/api/convos/${id}`;
};
export const updateConversation = () => {
return '/api/convos/update';
};
export const deleteConversation = () => {
return '/api/convos/clear';
};
export const search = (q: string, pageNumber: string) => {
return `/api/search?q=${q}&pageNumber=${pageNumber}`;
};
export const searchEnabled = () => {
return '/api/search/enable';
};
export const presets = () => {
return '/api/presets';
};
export const deletePreset = () => {
return '/api/presets/delete';
};
export const aiEndpoints = () => {
return '/api/endpoints';
};
export const tokenizer = () => {
return '/api/tokenizer';
};
export const login = () => {
return '/api/auth/login';
};
export const logout = () => {
return '/api/auth/logout';
};
export const register = () => {
return '/api/auth/register';
};
export const loginFacebook = () => {
return '/api/auth/facebook';
};
export const loginGoogle = () => {
return '/api/auth/google';
};
export const refreshToken = () => {
return '/api/auth/refresh';
};
export const requestPasswordReset = () => {
return '/api/auth/requestPasswordReset';
};
export const resetPassword = () => {
return '/api/auth/resetPassword';
};
export const plugins = () => {
return '/api/plugins';
};
export const config = () => {
return '/api/config';
};

View file

@ -0,0 +1,28 @@
import type { TConversation, TSubmission, EModelEndpoint } from './types';
export default function createPayload(submission: TSubmission) {
const { conversation, message, endpointOption } = submission;
const { conversationId } = conversation as TConversation;
const { endpoint } = endpointOption as { endpoint: EModelEndpoint };
const endpointUrlMap = {
azureOpenAI: '/api/ask/azureOpenAI',
openAI: '/api/ask/openAI',
google: '/api/ask/google',
bingAI: '/api/ask/bingAI',
chatGPT: '/api/ask/chatGPT',
chatGPTBrowser: '/api/ask/chatGPTBrowser',
gptPlugins: '/api/ask/gptPlugins',
anthropic: '/api/ask/anthropic',
};
const server = endpointUrlMap[endpoint];
const payload = {
...message,
...endpointOption,
conversationId,
};
return { server, payload };
}

View file

@ -0,0 +1,119 @@
import * as t from './types';
import request from './request';
import * as endpoints from './api-endpoints';
export function getConversations(pageNumber: string): Promise<t.TGetConversationsResponse> {
return request.get(endpoints.conversations(pageNumber));
}
export function abortRequestWithMessage(
endpoint: string,
abortKey: string,
message: string,
): Promise<void> {
return request.post(endpoints.abortRequest(endpoint), { arg: { abortKey, message } });
}
export function deleteConversation(payload: t.TDeleteConversationRequest) {
//todo: this should be a DELETE request
return request.post(endpoints.deleteConversation(), { arg: payload });
}
export function clearAllConversations(): Promise<unknown> {
return request.post(endpoints.deleteConversation(), { arg: {} });
}
export function getMessagesByConvoId(id: string): Promise<t.TMessage[]> {
return request.get(endpoints.messages(id));
}
export function getConversationById(id: string): Promise<t.TConversation> {
return request.get(endpoints.conversationById(id));
}
export function updateConversation(
payload: t.TUpdateConversationRequest,
): Promise<t.TUpdateConversationResponse> {
return request.post(endpoints.updateConversation(), { arg: payload });
}
export function getPresets(): Promise<t.TPreset[]> {
return request.get(endpoints.presets());
}
export function createPreset(payload: t.TPreset): Promise<t.TPreset[]> {
return request.post(endpoints.presets(), payload);
}
export function updatePreset(payload: t.TPreset): Promise<t.TPreset[]> {
return request.post(endpoints.presets(), payload);
}
export function deletePreset(arg: t.TPreset | object): Promise<t.TPreset[]> {
return request.post(endpoints.deletePreset(), arg);
}
export function getSearchEnabled(): Promise<boolean> {
return request.get(endpoints.searchEnabled());
}
export function getUser(): Promise<t.TUser> {
return request.get(endpoints.user());
}
export const searchConversations = async (
q: string,
pageNumber: string,
): Promise<t.TSearchResults> => {
return request.get(endpoints.search(q, pageNumber));
};
export const getAIEndpoints = () => {
return request.get(endpoints.aiEndpoints());
};
export const updateTokenCount = (text: string) => {
return request.post(endpoints.tokenizer(), { arg: text });
};
export const login = (payload: t.TLoginUser) => {
return request.post(endpoints.login(), payload);
};
export const logout = () => {
return request.post(endpoints.logout());
};
export const register = (payload: t.TRegisterUser) => {
return request.post(endpoints.register(), payload);
};
export const refreshToken = () => {
return request.post(endpoints.refreshToken());
};
export const getLoginGoogle = () => {
return request.get(endpoints.loginGoogle());
};
export const requestPasswordReset = (
payload: t.TRequestPasswordReset,
): Promise<t.TRequestPasswordResetResponse> => {
return request.post(endpoints.requestPasswordReset(), payload);
};
export const resetPassword = (payload: t.TResetPassword) => {
return request.post(endpoints.resetPassword(), payload);
};
export const getAvailablePlugins = (): Promise<t.TPlugin[]> => {
return request.get(endpoints.plugins());
};
export const updateUserPlugins = (payload: t.TUpdateUserPlugins) => {
return request.post(endpoints.userPlugins(), payload);
};
export const getStartupConfig = (): Promise<t.TStartupConfig> => {
return request.get(endpoints.config());
};

View file

@ -0,0 +1,9 @@
import axios from 'axios';
export function setAcceptLanguageHeader(value: string): void {
axios.defaults.headers.common['Accept-Language'] = value;
}
export function setTokenHeader(token: string) {
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
}

View file

@ -0,0 +1,7 @@
export * from './data-service';
export * from './request';
export * from './types';
export * from './react-query-service';
export * from './headers-helpers';
export * from './sse';
export { default as createPayload } from './createPayload';

View file

@ -0,0 +1,362 @@
import {
UseQueryOptions,
useQuery,
useMutation,
useQueryClient,
UseMutationResult,
QueryObserverResult,
} from '@tanstack/react-query';
import * as t from './types';
import * as dataService from './data-service';
export enum QueryKeys {
messages = 'messsages',
allConversations = 'allConversations',
conversation = 'conversation',
searchEnabled = 'searchEnabled',
user = 'user',
endpoints = 'endpoints',
presets = 'presets',
searchResults = 'searchResults',
tokenCount = 'tokenCount',
availablePlugins = 'availablePlugins',
startupConfig = 'startupConfig',
}
export const useAbortRequestWithMessage = (): UseMutationResult<
void,
Error,
{ endpoint: string; abortKey: string; message: string }
> => {
return useMutation(({ endpoint, abortKey, message }) =>
dataService.abortRequestWithMessage(endpoint, abortKey, message),
);
};
export const useGetUserQuery = (
config?: UseQueryOptions<t.TUser>,
): QueryObserverResult<t.TUser> => {
return useQuery<t.TUser>([QueryKeys.user], () => dataService.getUser(), {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
retry: false,
...config,
});
};
export const useGetMessagesByConvoId = (
id: string,
config?: UseQueryOptions<t.TMessage[]>,
): QueryObserverResult<t.TMessage[]> => {
return useQuery<t.TMessage[]>(
[QueryKeys.messages, id],
() => dataService.getMessagesByConvoId(id),
{
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
...config,
},
);
};
export const useGetConversationByIdQuery = (
id: string,
config?: UseQueryOptions<t.TConversation>,
): QueryObserverResult<t.TConversation> => {
return useQuery<t.TConversation>(
[QueryKeys.conversation, id],
() => dataService.getConversationById(id),
{
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
...config,
},
);
};
//This isn't ideal because its just a query and we're using mutation, but it was the only way
//to make it work with how the Chat component is structured
export const useGetConversationByIdMutation = (id: string): UseMutationResult<t.TConversation> => {
const queryClient = useQueryClient();
return useMutation(() => dataService.getConversationById(id), {
// onSuccess: (res: t.TConversation) => {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.conversation, id]);
},
});
};
export const useUpdateConversationMutation = (
id: string,
): UseMutationResult<
t.TUpdateConversationResponse,
unknown,
t.TUpdateConversationRequest,
unknown
> => {
const queryClient = useQueryClient();
return useMutation(
(payload: t.TUpdateConversationRequest) => dataService.updateConversation(payload),
{
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.conversation, id]);
queryClient.invalidateQueries([QueryKeys.allConversations]);
},
},
);
};
export const useDeleteConversationMutation = (
id?: string,
): UseMutationResult<
t.TDeleteConversationResponse,
unknown,
t.TDeleteConversationRequest,
unknown
> => {
const queryClient = useQueryClient();
return useMutation(
(payload: t.TDeleteConversationRequest) => dataService.deleteConversation(payload),
{
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.conversation, id]);
queryClient.invalidateQueries([QueryKeys.allConversations]);
},
},
);
};
export const useClearConversationsMutation = (): UseMutationResult<unknown> => {
const queryClient = useQueryClient();
return useMutation(() => dataService.clearAllConversations(), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.allConversations]);
},
});
};
export const useGetConversationsQuery = (
pageNumber: string,
config?: UseQueryOptions<t.TGetConversationsResponse>,
): QueryObserverResult<t.TGetConversationsResponse> => {
return useQuery<t.TGetConversationsResponse>(
[QueryKeys.allConversations, pageNumber],
() => dataService.getConversations(pageNumber),
{
refetchOnReconnect: false,
refetchOnMount: false,
retry: 1,
...config,
},
);
};
export const useGetSearchEnabledQuery = (
config?: UseQueryOptions<boolean>,
): QueryObserverResult<boolean> => {
return useQuery<boolean>([QueryKeys.searchEnabled], () => dataService.getSearchEnabled(), {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
...config,
});
};
export const useGetEndpointsQuery = (): QueryObserverResult<t.TEndpoints> => {
return useQuery([QueryKeys.endpoints], () => dataService.getAIEndpoints(), {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
});
};
export const useCreatePresetMutation = (): UseMutationResult<
t.TPreset[],
unknown,
t.TPreset,
unknown
> => {
const queryClient = useQueryClient();
return useMutation((payload: t.TPreset) => dataService.createPreset(payload), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.presets]);
},
});
};
export const useUpdatePresetMutation = (): UseMutationResult<
t.TPreset[],
unknown,
t.TPreset,
unknown
> => {
const queryClient = useQueryClient();
return useMutation((payload: t.TPreset) => dataService.updatePreset(payload), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.presets]);
},
});
};
export const useGetPresetsQuery = (
config?: UseQueryOptions<t.TPreset[]>,
): QueryObserverResult<t.TPreset[], unknown> => {
return useQuery<t.TPreset[]>([QueryKeys.presets], () => dataService.getPresets(), {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
...config,
});
};
export const useDeletePresetMutation = (): UseMutationResult<
t.TPreset[],
unknown,
t.TPreset | object,
unknown
> => {
const queryClient = useQueryClient();
return useMutation((payload: t.TPreset | object) => dataService.deletePreset(payload), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.presets]);
},
});
};
export const useSearchQuery = (
searchQuery: string,
pageNumber: string,
config?: UseQueryOptions<t.TSearchResults>,
): QueryObserverResult<t.TSearchResults> => {
return useQuery<t.TSearchResults>(
[QueryKeys.searchResults, pageNumber, searchQuery],
() => dataService.searchConversations(searchQuery, pageNumber),
{
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
...config,
},
);
};
export const useUpdateTokenCountMutation = (): UseMutationResult<
t.TUpdateTokenCountResponse,
unknown,
string,
unknown
> => {
const queryClient = useQueryClient();
return useMutation((text: string) => dataService.updateTokenCount(text), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.tokenCount]);
},
});
};
export const useLoginUserMutation = (): UseMutationResult<
t.TLoginResponse,
unknown,
t.TLoginUser,
unknown
> => {
const queryClient = useQueryClient();
return useMutation((payload: t.TLoginUser) => dataService.login(payload), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.user]);
},
});
};
export const useRegisterUserMutation = (): UseMutationResult<
unknown,
unknown,
t.TRegisterUser,
unknown
> => {
const queryClient = useQueryClient();
return useMutation((payload: t.TRegisterUser) => dataService.register(payload), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.user]);
},
});
};
export const useLogoutUserMutation = (): UseMutationResult<unknown> => {
const queryClient = useQueryClient();
return useMutation(() => dataService.logout(), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.user]);
},
});
};
export const useRefreshTokenMutation = (): UseMutationResult<
t.TRefreshTokenResponse,
unknown,
unknown,
unknown
> => {
return useMutation(() => dataService.refreshToken(), {});
};
export const useRequestPasswordResetMutation = (): UseMutationResult<
t.TRequestPasswordResetResponse,
unknown,
t.TRequestPasswordReset,
unknown
> => {
return useMutation((payload: t.TRequestPasswordReset) =>
dataService.requestPasswordReset(payload),
);
};
export const useResetPasswordMutation = (): UseMutationResult<
unknown,
unknown,
t.TResetPassword,
unknown
> => {
return useMutation((payload: t.TResetPassword) => dataService.resetPassword(payload));
};
export const useAvailablePluginsQuery = (): QueryObserverResult<t.TPlugin[]> => {
return useQuery<t.TPlugin[]>(
[QueryKeys.availablePlugins],
() => dataService.getAvailablePlugins(),
{
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
},
);
};
export const useUpdateUserPluginsMutation = (): UseMutationResult<
t.TUser,
unknown,
t.TUpdateUserPlugins,
unknown
> => {
const queryClient = useQueryClient();
return useMutation((payload: t.TUpdateUserPlugins) => dataService.updateUserPlugins(payload), {
onSuccess: () => {
queryClient.invalidateQueries([QueryKeys.user]);
},
});
};
export const useGetStartupConfig = (): QueryObserverResult<t.TStartupConfig> => {
return useQuery<t.TStartupConfig>(
[QueryKeys.startupConfig],
() => dataService.getStartupConfig(),
{
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
},
);
};

View file

@ -0,0 +1,55 @@
import axios, { AxiosRequestConfig } from 'axios';
async function _get<T>(url: string, options?: AxiosRequestConfig): Promise<T> {
const response = await axios.get(url, { ...options });
return response.data;
}
async function _post(url: string, data?: any) {
const response = await axios.post(url, JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
return response.data;
}
async function _postMultiPart(url: string, formData: FormData, options?: AxiosRequestConfig) {
const response = await axios.post(url, formData, {
...options,
headers: { 'Content-Type': 'multipart/form-data' },
});
return response.data;
}
async function _put(url: string, data?: any) {
const response = await axios.put(url, JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
return response.data;
}
async function _delete<T>(url: string): Promise<T> {
const response = await axios.delete(url);
return response.data;
}
async function _deleteWithOptions<T>(url: string, options?: AxiosRequestConfig): Promise<T> {
const response = await axios.delete(url, { ...options });
return response.data;
}
async function _patch(url: string, data?: any) {
const response = await axios.patch(url, JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
return response.data;
}
export default {
get: _get,
post: _post,
postMultiPart: _postMultiPart,
put: _put,
delete: _delete,
deleteWithOptions: _deleteWithOptions,
patch: _patch,
};

View file

@ -0,0 +1,224 @@
/* eslint-disable */
/**
* Copyright (C) 2016 Maxime Petazzoni <maxime.petazzoni@bulix.org>.
* All rights reserved.
*/
var SSE = function (url, options) {
if (!(this instanceof SSE)) {
return new SSE(url, options);
}
this.INITIALIZING = -1;
this.CONNECTING = 0;
this.OPEN = 1;
this.CLOSED = 2;
this.url = url;
options = options || {};
this.headers = options.headers || {};
this.payload = options.payload !== undefined ? options.payload : '';
this.method = options.method || (this.payload && 'POST') || 'GET';
this.withCredentials = !!options.withCredentials;
this.FIELD_SEPARATOR = ':';
this.listeners = {};
this.xhr = null;
this.readyState = this.INITIALIZING;
this.progress = 0;
this.chunk = '';
this.addEventListener = function (type, listener) {
if (this.listeners[type] === undefined) {
this.listeners[type] = [];
}
if (this.listeners[type].indexOf(listener) === -1) {
this.listeners[type].push(listener);
}
};
this.removeEventListener = function (type, listener) {
if (this.listeners[type] === undefined) {
return;
}
var filtered = [];
this.listeners[type].forEach(function (element) {
if (element !== listener) {
filtered.push(element);
}
});
if (filtered.length === 0) {
delete this.listeners[type];
} else {
this.listeners[type] = filtered;
}
};
this.dispatchEvent = function (e) {
if (!e) {
return true;
}
e.source = this;
var onHandler = 'on' + e.type;
if (this.hasOwnProperty(onHandler)) {
this[onHandler].call(this, e);
if (e.defaultPrevented) {
return false;
}
}
if (this.listeners[e.type]) {
return this.listeners[e.type].every(function (callback) {
callback(e);
return !e.defaultPrevented;
});
}
return true;
};
this._setReadyState = function (state) {
var event = new CustomEvent('readystatechange');
event.readyState = state;
this.readyState = state;
this.dispatchEvent(event);
};
this._onStreamFailure = function (e) {
var event = new CustomEvent('error');
event.data = e.currentTarget.response;
this.dispatchEvent(event);
this.close();
};
this._onStreamAbort = function (e) {
this.dispatchEvent(new CustomEvent('abort'));
this.close();
};
this._onStreamProgress = function (e) {
if (!this.xhr) {
return;
}
if (this.xhr.status !== 200) {
this._onStreamFailure(e);
return;
}
if (this.readyState == this.CONNECTING) {
this.dispatchEvent(new CustomEvent('open'));
this._setReadyState(this.OPEN);
}
var data = this.xhr.responseText.substring(this.progress);
this.progress += data.length;
data.split(/(\r\n|\r|\n){2}/g).forEach(
function (part) {
if (part.trim().length === 0) {
this.dispatchEvent(this._parseEventChunk(this.chunk.trim()));
this.chunk = '';
} else {
this.chunk += part;
}
}.bind(this),
);
};
this._onStreamLoaded = function (e) {
this._onStreamProgress(e);
// Parse the last chunk.
this.dispatchEvent(this._parseEventChunk(this.chunk));
this.chunk = '';
};
/**
* Parse a received SSE event chunk into a constructed event object.
*/
this._parseEventChunk = function (chunk) {
if (!chunk || chunk.length === 0) {
return null;
}
var e = { id: null, retry: null, data: '', event: 'message' };
chunk.split(/\n|\r\n|\r/).forEach(
function (line) {
line = line.trimRight();
var index = line.indexOf(this.FIELD_SEPARATOR);
if (index <= 0) {
// Line was either empty, or started with a separator and is a comment.
// Either way, ignore.
return;
}
var field = line.substring(0, index);
if (!(field in e)) {
return;
}
var value = line.substring(index + 1).trimLeft();
if (field === 'data') {
e[field] += value;
} else {
e[field] = value;
}
}.bind(this),
);
var event = new CustomEvent(e.event);
event.data = e.data;
event.id = e.id;
return event;
};
this._checkStreamClosed = function () {
if (!this.xhr) {
return;
}
if (this.xhr.readyState === XMLHttpRequest.DONE) {
this._setReadyState(this.CLOSED);
}
};
this.stream = function () {
this._setReadyState(this.CONNECTING);
this.xhr = new XMLHttpRequest();
this.xhr.addEventListener('progress', this._onStreamProgress.bind(this));
this.xhr.addEventListener('load', this._onStreamLoaded.bind(this));
this.xhr.addEventListener('readystatechange', this._checkStreamClosed.bind(this));
this.xhr.addEventListener('error', this._onStreamFailure.bind(this));
this.xhr.addEventListener('abort', this._onStreamAbort.bind(this));
this.xhr.open(this.method, this.url);
for (var header in this.headers) {
this.xhr.setRequestHeader(header, this.headers[header]);
}
this.xhr.withCredentials = this.withCredentials;
this.xhr.send(this.payload);
};
this.close = function () {
if (this.readyState === this.CLOSED) {
return;
}
this.xhr.abort();
this.xhr = null;
this._setReadyState(this.CLOSED);
};
};
export { SSE };
// Export our SSE module for npm.js
// if (typeof exports !== 'undefined') {
// // exports.SSE = SSE;
// module.exports = { SSE };
// }

View file

@ -0,0 +1,275 @@
export type TMessage = {
messageId: string;
conversationId: string;
clientId: string;
parentMessageId: string;
sender: string;
text: string;
isCreatedByUser: boolean;
error: boolean;
createdAt: string;
updatedAt: string;
};
export type TExample = {
input: string;
output: string;
};
export enum EModelEndpoint {
azureOpenAI = 'azureOpenAI',
openAI = 'openAI',
bingAI = 'bingAI',
chatGPT = 'chatGPT',
chatGPTBrowser = 'chatGPTBrowser',
google = 'google',
gptPlugins = 'gptPlugins',
anthropic = 'anthropic',
}
export type TSubmission = {
clientId?: string;
context?: string;
conversationId?: string;
conversationSignature?: string;
current: boolean;
endpoint: EModelEndpoint;
invocationId: number;
isCreatedByUser: boolean;
jailbreak: boolean;
jailbreakConversationId?: string;
messageId: string;
overrideParentMessageId?: string | boolean;
parentMessageId?: string;
sender: string;
systemMessage?: string;
text: string;
toneStyle?: string;
model?: string;
promptPrefix?: string;
temperature?: number;
top_p?: number;
presence_penalty?: number;
frequence_penalty?: number;
conversation: TConversation;
message: TMessage;
endpointOption: TEndpointOption;
};
export type TEndpointOption = {
endpoint: EModelEndpoint;
model?: string;
promptPrefix?: string;
temperature?: number;
};
export type TPluginAuthConfig = {
authField: string;
label: string;
description: string;
};
export type TPlugin = {
name: string;
pluginKey: string;
description: string;
icon: string;
authConfig: TPluginAuthConfig[];
authenticated: boolean;
};
export type TUpdateUserPlugins = {
pluginKey: string;
action: string;
auth?: unknown;
};
export type TConversation = {
conversationId: string;
title: string;
user?: string;
endpoint: EModelEndpoint;
suggestions?: string[];
messages?: TMessage[];
tools?: TPlugin[];
createdAt: string;
updatedAt: string;
// google only
modelLabel?: string;
examples?: TExample[];
// for azureOpenAI, openAI only
chatGptLabel?: string;
userLabel?: string;
model?: string;
promptPrefix?: string;
temperature?: number;
topP?: number;
topK?: number;
// bing and google
context?: string;
top_p?: number;
presence_penalty?: number;
// for bingAI only
jailbreak?: boolean;
jailbreakConversationId?: string;
conversationSignature?: string;
parentMessageId?: string;
clientId?: string;
invocationId?: string;
toneStyle?: string;
};
export type TPreset = {
title: string;
endpoint: EModelEndpoint;
conversationSignature?: string;
createdAt?: string;
updatedAt?: string;
presetId?: string;
user?: string;
// for azureOpenAI, openAI only
chatGptLabel?: string;
frequence_penalty?: number;
model?: string;
presence_penalty?: number;
promptPrefix?: string;
temperature?: number;
top_p?: number;
//for BingAI
clientId?: string;
invocationId?: number;
jailbreak?: boolean;
jailbreakPresetId?: string;
presetSignature?: string;
toneStyle?: string;
};
export type TUser = {
id: string;
username: string;
email: string;
name: string;
avatar: string;
role: string;
provider: string;
plugins: string[];
createdAt: string;
updatedAt: string;
};
export type TGetConversationsResponse = {
conversations: TConversation[];
pageNumber: string;
pageSize: string | number;
pages: string | number;
};
export type TUpdateConversationRequest = {
conversationId: string;
title: string;
};
export type TUpdateConversationResponse = {
data: TConversation;
};
export type TDeleteConversationRequest = {
conversationId?: string;
source?: string;
};
export type TDeleteConversationResponse = {
acknowledged: boolean;
deletedCount: number;
messages: {
acknowledged: boolean;
deletedCount: number;
};
};
export type TSearchResults = {
conversations: TConversation[];
messages: TMessage[];
pageNumber: string;
pageSize: string | number;
pages: string | number;
filter: object;
};
export type TEndpoints = {
azureOpenAI: boolean;
bingAI: boolean;
ChatGptBrowser: {
availableModels: [];
};
OpenAI: {
availableModels: [];
};
};
export type TUpdateTokenCountResponse = {
count: number;
};
export type TMessageTreeNode = object;
export type TSearchMessage = object;
export type TSearchMessageTreeNode = object;
export type TRegisterUser = {
name: string;
email: string;
username: string;
password: string;
confirm_password?: string;
};
export type TLoginUser = {
email: string;
password: string;
};
export type TLoginResponse = {
token: string;
user: TUser;
};
export type TRequestPasswordReset = {
email: string;
};
export type TResetPassword = {
userId: string;
token: string;
password: string;
confirm_password?: string;
};
export type TStartupConfig = {
appTitle: boolean;
googleLoginEnabled: boolean;
openidLoginEnabled: boolean;
githubLoginEnabled: boolean;
openidLabel: string;
openidImageUrl: string;
discordLoginEnabled: boolean;
serverDomain: string;
registrationEnabled: boolean;
socialLoginEnabled: boolean;
};
export type TRefreshTokenResponse = {
token: string;
user: TUser;
};
export type TRequestPasswordResetResponse = {
link: string;
};
export type File = {
name: string;
date: number;
size: number;
};

View file

@ -0,0 +1,27 @@
{
"compilerOptions": {
"declaration": true,
"declarationDir": "./types",
"module": "esnext",
"noImplicitAny": true,
"outDir": "./types",
"target": "es5",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"lib": ["es2017", "dom"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"baseUrl": "src",
"paths": {
"@src/*": ["./*"]
}
},
"exclude": ["node_modules", "dist", "types"],
"include": ["src/**/*", "types/index.d.ts"]
}