diff --git a/srv/api/chat/inference.ts b/srv/api/chat/inference.ts index d23db1816..14bbcf388 100644 --- a/srv/api/chat/inference.ts +++ b/srv/api/chat/inference.ts @@ -24,6 +24,7 @@ const validInference = { presetId: 'string?', jsonSchema: 'any?', imageData: 'string?', + chatId: 'string?', } as const const validInferenceApi = { @@ -414,6 +415,7 @@ export const inferenceStream = wrap(async (req, res) => { imageData: body.imageData, stop: body.stop, signal, + chatId: body.chatId, }) const requestId = body.requestId || v4() diff --git a/srv/api/user/index.ts b/srv/api/user/index.ts index 1bfba1a7f..31b7490db 100644 --- a/srv/api/user/index.ts +++ b/srv/api/user/index.ts @@ -28,6 +28,7 @@ import { getThirdPartyPresetModels, testConnectionUrl, getUserPreset, + getChatPreset, } from './presets' import { hordeStats, novelLogin, openRouterModels, updateService } from './services' import { @@ -80,6 +81,7 @@ router.get('/init', loggedIn, getInitialLoad) router.get('/', loggedIn, getProfile) router.get('/presets', loggedIn, getUserPresets) router.get('/presets/:id', loggedIn, getUserPreset) +router.get('/presets/:id/chat', loggedIn, getChatPreset) router.get('/templates', loggedIn, getPromptTemplates) router.delete('/presets/:id/key', loggedIn, deleteUserPresetKey) router.get('/config', loggedIn, getConfig) diff --git a/srv/api/user/presets.ts b/srv/api/user/presets.ts index 2d5754347..57443b176 100644 --- a/srv/api/user/presets.ts +++ b/srv/api/user/presets.ts @@ -1,5 +1,5 @@ import { assertValid } from '/common/valid' -import { defaultPresets, presetValidator } from '../../../common/presets' +import { defaultPresets, getFallbackPreset, presetValidator } from '../../../common/presets' import { store } from '../../db' import { StatusError, handle } from '../wrap' import { AIAdapter } from '../../../common/adapters' @@ -7,6 +7,8 @@ import { AppSchema } from '/common/types' import { toSamplerOrder } from '/common/sampler-order' import { decryptText } from '/srv/db/util' import { getThirdPartyModels } from '/common/requests/util' +import { isDefaultPreset } from '/common/default-preset' +import { deepClone } from '/common/util' const createPreset = { ...presetValidator, @@ -96,6 +98,39 @@ export const getUserPreset = handle(async ({ userId, params }) => { return preset }) +export const getChatPreset = handle(async ({ userId, params }) => { + const chat = await store.chats.getChatOnly(params.id) + if (!chat) { + throw new StatusError(`Preset not found (Invalid chat id)`, 404) + } + + if (!chat.genPreset) { + return getFallbackPreset('agnaistic') + } + + if (isDefaultPreset(chat.genPreset)) { + const copy = deepClone(defaultPresets[chat.genPreset]) + return copy + } + + const preset = await store.presets.getSafeUserPreset(chat.genPreset, userId) + if (!preset) { + const fallback = getFallbackPreset('agnaistic') + return fallback + } + + if (userId === preset.userId) { + return preset + } + + const members = await store.chats.getActiveMembers(params.id) + if (!members.includes(userId)) { + throw new StatusError(`Preset not found: Not allowed`, 402) + } + + return preset +}) + export const getBasePresets = handle(async () => { return { presets: defaultPresets } }) diff --git a/web/pages/Character/CharacterSchema.tsx b/web/pages/Character/CharacterSchema.tsx index 68e838baf..43ed375db 100644 --- a/web/pages/Character/CharacterSchema.tsx +++ b/web/pages/Character/CharacterSchema.tsx @@ -95,7 +95,7 @@ export const CharacterSchema: Component<{ if (props.characterId) { const char = ctx.allBots[props.characterId] - json = char ? char.json : chatStore.getState().active?.char.json + json = char ? char.json : ctx.char?.json } else if (props.presetId || props.inherit) { json = props.inherit || activePreset()?.json } diff --git a/web/pages/Chat/ChatDetail.tsx b/web/pages/Chat/ChatDetail.tsx index 12235b4ec..f06abf551 100644 --- a/web/pages/Chat/ChatDetail.tsx +++ b/web/pages/Chat/ChatDetail.tsx @@ -71,11 +71,12 @@ const ChatDetail: Component = () => { const [_, presetSet] = usePresetContext() const chats = chatStore((s) => ({ - ...(s.active?.chat._id === params.id ? s.active : undefined), + ...(ctx.active?.chat._id === params.id ? ctx.active : undefined), lastId: s.lastChatId, members: s.chatProfiles, loaded: s.detailLoaded, loading: s.detailLoading, + opts: s.opts, linesAddedCount: s.prompt?.template.linesAddedCount, msgVisibility: s.msgVisibility, @@ -213,11 +214,12 @@ const ChatDetail: Component = () => { return nav(`/chat/${chats.lastId}`) } - if (params.id !== chats.chat?._id) { + if (params.id !== chats.lastId) { + presetSet.loadChatId(params.id) + presetStore.getTemplates(true) chatStore.openChat(params.id, { onDone: async (success, chat) => { if (success && chat) { - await Promise.all([presetSet.loadChat(chat, true), presetStore.getTemplates(true)]) return } @@ -425,7 +427,7 @@ const ChatDetail: Component = () => { swipe={swipe()} /> } - loading={!chats.loaded && !chats.chat} + loading={!ctx.active} showPane={showPane()} pane={} split={split()} diff --git a/web/pages/Chat/ChatExport.tsx b/web/pages/Chat/ChatExport.tsx index 9b7bcc0df..9d48f9f8d 100644 --- a/web/pages/Chat/ChatExport.tsx +++ b/web/pages/Chat/ChatExport.tsx @@ -4,15 +4,17 @@ import Button from '../../shared/Button' import Modal from '../../shared/Modal' import { characterStore, chatStore, msgStore } from '../../store' import { resolveChatPath } from '/common/chat' +import { useAppContext } from '/web/store/context' const ChatExport: Component<{ show: boolean; close: () => void }> = (props) => { + const [ctx] = useAppContext() const chats = chatStore.getState() const chars = characterStore.getState().characters const msgs = msgStore.getState() const json = createMemo(() => { const graph = msgs.graph - const chat = chats.active?.chat + const chat = ctx.active?.chat const messages = resolveChatPath(graph.tree, msgs.msgs.slice(-1)[0]._id) const json = { @@ -52,7 +54,7 @@ const ChatExport: Component<{ show: boolean; close: () => void }> = (props) => {