mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into parser-enum-stuff
This commit is contained in:
@@ -81,12 +81,15 @@ dialog {
|
|||||||
animation: fade-out var(--animation-duration-slow) ease-in-out;
|
animation: fade-out var(--animation-duration-slow) ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix toastr in dialogs by actually placing it at the top of the screen via transform */
|
|
||||||
.popup #toast-container {
|
.popup #toast-container {
|
||||||
|
/* Fix toastr in dialogs by actually placing it at the top of the screen via transform */
|
||||||
height: 100svh;
|
height: 100svh;
|
||||||
top: calc(50% + var(--topBarBlockSize));
|
top: calc(50% + var(--topBarBlockSize));
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
/* Fix text align, popups are centered by default. toasts should not. */
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-input {
|
.popup-input {
|
||||||
|
@@ -2551,6 +2551,7 @@
|
|||||||
<h4 data-i18n="Claude Model">Claude Model</h4>
|
<h4 data-i18n="Claude Model">Claude Model</h4>
|
||||||
<select id="model_claude_select">
|
<select id="model_claude_select">
|
||||||
<optgroup label="Versions">
|
<optgroup label="Versions">
|
||||||
|
<option value="claude-3-5-sonnet-20240620">claude-3-5-sonnet-20240620</option>
|
||||||
<option value="claude-3-opus-20240229">claude-3-opus-20240229</option>
|
<option value="claude-3-opus-20240229">claude-3-opus-20240229</option>
|
||||||
<option value="claude-3-sonnet-20240229">claude-3-sonnet-20240229</option>
|
<option value="claude-3-sonnet-20240229">claude-3-sonnet-20240229</option>
|
||||||
<option value="claude-3-haiku-20240307">claude-3-haiku-20240307</option>
|
<option value="claude-3-haiku-20240307">claude-3-haiku-20240307</option>
|
||||||
@@ -5496,7 +5497,6 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div id="logit_bias_template" class="template_element">
|
<div id="logit_bias_template" class="template_element">
|
||||||
<div class="logit_bias_form">
|
<div class="logit_bias_form">
|
||||||
<input class="logit_bias_text text_pole" data-i18n="[placeholder]Type here..." placeholder="type here..." />
|
<input class="logit_bias_text text_pole" data-i18n="[placeholder]Type here..." placeholder="type here..." />
|
||||||
|
@@ -272,12 +272,12 @@ toastr.options.timeOut = 4000; // How long the toast will display without user i
|
|||||||
toastr.options.extendedTimeOut = 10000; // How long the toast will display after a user hovers over it
|
toastr.options.extendedTimeOut = 10000; // How long the toast will display after a user hovers over it
|
||||||
toastr.options.progressBar = true; // Visually indicate how long before a toast expires.
|
toastr.options.progressBar = true; // Visually indicate how long before a toast expires.
|
||||||
toastr.options.closeButton = true; // enable a close button
|
toastr.options.closeButton = true; // enable a close button
|
||||||
toastr.options.positionClass = "toast-top-center"; // Where to position the toast container
|
toastr.options.positionClass = 'toast-top-center'; // Where to position the toast container
|
||||||
toastr.options.onHidden = () => {
|
toastr.options.onHidden = () => {
|
||||||
// If we have any dialog still open, the last "hidden" toastr will remove the toastr-container. We need to keep it alive inside the dialog though
|
// If we have any dialog still open, the last "hidden" toastr will remove the toastr-container. We need to keep it alive inside the dialog though
|
||||||
// so the toasts still show up inside there.
|
// so the toasts still show up inside there.
|
||||||
fixToastrForDialogs();
|
fixToastrForDialogs();
|
||||||
}
|
};
|
||||||
|
|
||||||
// Allow target="_blank" in links
|
// Allow target="_blank" in links
|
||||||
DOMPurify.addHook('afterSanitizeAttributes', function (node) {
|
DOMPurify.addHook('afterSanitizeAttributes', function (node) {
|
||||||
@@ -3439,7 +3439,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
* @returns {string[]} Examples array with block heading
|
* @returns {string[]} Examples array with block heading
|
||||||
*/
|
*/
|
||||||
function parseMesExamples(examplesStr) {
|
function parseMesExamples(examplesStr) {
|
||||||
if (examplesStr.length === 0) {
|
if (examplesStr.length === 0 || examplesStr === '<START>') {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7543,10 +7543,15 @@ function addAlternateGreeting(template, greeting, index, getArray) {
|
|||||||
template.find('.alternate_greetings_list').append(greetingBlock);
|
template.find('.alternate_greetings_list').append(greetingBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates or edits a character based on the form data.
|
||||||
|
* @param {Event} [e] Event that triggered the function call.
|
||||||
|
*/
|
||||||
async function createOrEditCharacter(e) {
|
async function createOrEditCharacter(e) {
|
||||||
$('#rm_info_avatar').html('');
|
$('#rm_info_avatar').html('');
|
||||||
const formData = new FormData($('#form_create').get(0));
|
const formData = new FormData($('#form_create').get(0));
|
||||||
formData.set('fav', String(fav_ch_checked));
|
formData.set('fav', String(fav_ch_checked));
|
||||||
|
const isNewChat = e instanceof CustomEvent && e.type === 'newChat';
|
||||||
|
|
||||||
const rawFile = formData.get('avatar');
|
const rawFile = formData.get('avatar');
|
||||||
if (rawFile instanceof File) {
|
if (rawFile instanceof File) {
|
||||||
@@ -7689,6 +7694,7 @@ async function createOrEditCharacter(e) {
|
|||||||
// Recreate the chat if it hasn't been used at least once (i.e. with continue).
|
// Recreate the chat if it hasn't been used at least once (i.e. with continue).
|
||||||
const message = getFirstMessage();
|
const message = getFirstMessage();
|
||||||
const shouldRegenerateMessage =
|
const shouldRegenerateMessage =
|
||||||
|
!isNewChat &&
|
||||||
message.mes &&
|
message.mes &&
|
||||||
!selected_group &&
|
!selected_group &&
|
||||||
!chat_metadata['tainted'] &&
|
!chat_metadata['tainted'] &&
|
||||||
@@ -9215,7 +9221,7 @@ jQuery(async function () {
|
|||||||
characters[this_chid].chat = `${name2} - ${humanizedDateTime()}`;
|
characters[this_chid].chat = `${name2} - ${humanizedDateTime()}`;
|
||||||
$('#selected_chat_pole').val(characters[this_chid].chat);
|
$('#selected_chat_pole').val(characters[this_chid].chat);
|
||||||
await getChat();
|
await getChat();
|
||||||
await createOrEditCharacter();
|
await createOrEditCharacter(new CustomEvent('newChat'));
|
||||||
if (isDelChatCheckbox) await delChat(chat_file_for_del + '.jsonl');
|
if (isDelChatCheckbox) await delChat(chat_file_for_del + '.jsonl');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10774,4 +10780,4 @@ jQuery(async function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
initCustomSelectedSamplers();
|
initCustomSelectedSamplers();
|
||||||
});
|
});
|
||||||
|
@@ -39,6 +39,7 @@ import { textgen_types, textgenerationwebui_settings as textgen_settings, getTex
|
|||||||
import { debounce_timeout } from './constants.js';
|
import { debounce_timeout } from './constants.js';
|
||||||
|
|
||||||
import Bowser from '../lib/bowser.min.js';
|
import Bowser from '../lib/bowser.min.js';
|
||||||
|
import { Popup } from './popup.js';
|
||||||
|
|
||||||
var RPanelPin = document.getElementById('rm_button_panel_pin');
|
var RPanelPin = document.getElementById('rm_button_panel_pin');
|
||||||
var LPanelPin = document.getElementById('lm_button_panel_pin');
|
var LPanelPin = document.getElementById('lm_button_panel_pin');
|
||||||
@@ -1096,6 +1097,9 @@ export function initRossMods() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event.key == 'Escape') { //closes various panels
|
if (event.key == 'Escape') { //closes various panels
|
||||||
|
// Do not close panels if we are currently inside a popup
|
||||||
|
if (Popup.util.isPopupOpen())
|
||||||
|
return;
|
||||||
|
|
||||||
//dont override Escape hotkey functions from script.js
|
//dont override Escape hotkey functions from script.js
|
||||||
//"close edit box" and "cancel stream generation".
|
//"close edit box" and "cancel stream generation".
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
<option data-type="openai" value="gpt-4-vision-preview">gpt-4-vision-preview</option>
|
<option data-type="openai" value="gpt-4-vision-preview">gpt-4-vision-preview</option>
|
||||||
<option data-type="openai" value="gpt-4-turbo">gpt-4-turbo</option>
|
<option data-type="openai" value="gpt-4-turbo">gpt-4-turbo</option>
|
||||||
<option data-type="openai" value="gpt-4o">gpt-4o</option>
|
<option data-type="openai" value="gpt-4o">gpt-4o</option>
|
||||||
|
<option data-type="anthropic" value="claude-3-5-sonnet-20240620">claude-3-5-sonnet-20240620</option>
|
||||||
<option data-type="anthropic" value="claude-3-opus-20240229">claude-3-opus-20240229</option>
|
<option data-type="anthropic" value="claude-3-opus-20240229">claude-3-opus-20240229</option>
|
||||||
<option data-type="anthropic" value="claude-3-sonnet-20240229">claude-3-sonnet-20240229</option>
|
<option data-type="anthropic" value="claude-3-sonnet-20240229">claude-3-sonnet-20240229</option>
|
||||||
<option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option>
|
<option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option>
|
||||||
@@ -44,9 +45,11 @@
|
|||||||
<option data-type="openrouter" value="openai/gpt-4-turbo">openai/gpt-4-turbo</option>
|
<option data-type="openrouter" value="openai/gpt-4-turbo">openai/gpt-4-turbo</option>
|
||||||
<option data-type="openrouter" value="haotian-liu/llava-13b">haotian-liu/llava-13b</option>
|
<option data-type="openrouter" value="haotian-liu/llava-13b">haotian-liu/llava-13b</option>
|
||||||
<option data-type="openrouter" value="fireworks/firellava-13b">fireworks/firellava-13b</option>
|
<option data-type="openrouter" value="fireworks/firellava-13b">fireworks/firellava-13b</option>
|
||||||
|
<option data-type="openrouter" value="anthropic/claude-3.5-sonnet">anthropic/claude-3.5-sonnet</option>
|
||||||
<option data-type="openrouter" value="anthropic/claude-3-haiku">anthropic/claude-3-haiku</option>
|
<option data-type="openrouter" value="anthropic/claude-3-haiku">anthropic/claude-3-haiku</option>
|
||||||
<option data-type="openrouter" value="anthropic/claude-3-sonnet">anthropic/claude-3-sonnet</option>
|
<option data-type="openrouter" value="anthropic/claude-3-sonnet">anthropic/claude-3-sonnet</option>
|
||||||
<option data-type="openrouter" value="anthropic/claude-3-opus">anthropic/claude-3-opus</option>
|
<option data-type="openrouter" value="anthropic/claude-3-opus">anthropic/claude-3-opus</option>
|
||||||
|
<option data-type="openrouter" value="anthropic/claude-3.5-sonnet:beta">anthropic/claude-3.5-sonnet:beta</option>
|
||||||
<option data-type="openrouter" value="anthropic/claude-3-haiku:beta">anthropic/claude-3-haiku:beta</option>
|
<option data-type="openrouter" value="anthropic/claude-3-haiku:beta">anthropic/claude-3-haiku:beta</option>
|
||||||
<option data-type="openrouter" value="anthropic/claude-3-sonnet:beta">anthropic/claude-3-sonnet:beta</option>
|
<option data-type="openrouter" value="anthropic/claude-3-sonnet:beta">anthropic/claude-3-sonnet:beta</option>
|
||||||
<option data-type="openrouter" value="anthropic/claude-3-opus:beta">anthropic/claude-3-opus:beta</option>
|
<option data-type="openrouter" value="anthropic/claude-3-opus:beta">anthropic/claude-3-opus:beta</option>
|
||||||
|
@@ -195,19 +195,19 @@ export class Popup {
|
|||||||
|
|
||||||
this.ok.addEventListener('click', () => this.complete(POPUP_RESULT.AFFIRMATIVE));
|
this.ok.addEventListener('click', () => this.complete(POPUP_RESULT.AFFIRMATIVE));
|
||||||
this.cancel.addEventListener('click', () => this.complete(POPUP_RESULT.NEGATIVE));
|
this.cancel.addEventListener('click', () => this.complete(POPUP_RESULT.NEGATIVE));
|
||||||
|
|
||||||
|
// Bind dialog listeners manually, so we can be sure context is preserved
|
||||||
|
const cancelListener = (evt) => {
|
||||||
|
this.complete(POPUP_RESULT.CANCELLED);
|
||||||
|
evt.preventDefault();
|
||||||
|
evt.stopPropagation();
|
||||||
|
window.removeEventListener('cancel', cancelListenerBound);
|
||||||
|
};
|
||||||
|
const cancelListenerBound = cancelListener.bind(this);
|
||||||
|
this.dlg.addEventListener('cancel', cancelListenerBound);
|
||||||
|
|
||||||
const keyListener = (evt) => {
|
const keyListener = (evt) => {
|
||||||
switch (evt.key) {
|
switch (evt.key) {
|
||||||
case 'Escape': {
|
|
||||||
// Check if we are the currently active popup
|
|
||||||
if (this.dlg != document.activeElement?.closest('.popup'))
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.complete(POPUP_RESULT.CANCELLED);
|
|
||||||
evt.preventDefault();
|
|
||||||
evt.stopPropagation();
|
|
||||||
window.removeEventListener('keydown', keyListenerBound);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'Enter': {
|
case 'Enter': {
|
||||||
// CTRL+Enter counts as a closing action, but all other modifiers (ALT, SHIFT) should not trigger this
|
// CTRL+Enter counts as a closing action, but all other modifiers (ALT, SHIFT) should not trigger this
|
||||||
if (evt.altKey || evt.shiftKey)
|
if (evt.altKey || evt.shiftKey)
|
||||||
|
@@ -2678,7 +2678,7 @@ async function doDelMode(_, text) {
|
|||||||
|
|
||||||
let oldestMesToDel = $('#chat').find(`.mes[mesid=${oldestMesIDToDel}]`);
|
let oldestMesToDel = $('#chat').find(`.mes[mesid=${oldestMesIDToDel}]`);
|
||||||
|
|
||||||
if (!oldestMesIDToDel) {
|
if (!oldestMesIDToDel && lastMesID > 0) {
|
||||||
oldestMesToDel = await loadUntilMesId(oldestMesIDToDel);
|
oldestMesToDel = await loadUntilMesId(oldestMesIDToDel);
|
||||||
|
|
||||||
if (!oldestMesToDel || !oldestMesToDel.length) {
|
if (!oldestMesToDel || !oldestMesToDel.length) {
|
||||||
|
@@ -185,7 +185,7 @@ class WebScraper {
|
|||||||
const files = [];
|
const files = [];
|
||||||
|
|
||||||
for (const link of links) {
|
for (const link of links) {
|
||||||
const result = await fetch('/api/serpapi/visit', {
|
const result = await fetch('/api/search/visit', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getRequestHeaders(),
|
headers: getRequestHeaders(),
|
||||||
body: JSON.stringify({ url: link }),
|
body: JSON.stringify({ url: link }),
|
||||||
@@ -530,7 +530,7 @@ class YouTubeScraper {
|
|||||||
async getScript(videoUrl, lang) {
|
async getScript(videoUrl, lang) {
|
||||||
const id = this.parseId(String(videoUrl).trim());
|
const id = this.parseId(String(videoUrl).trim());
|
||||||
|
|
||||||
const result = await fetch('/api/serpapi/transcript', {
|
const result = await fetch('/api/search/transcript', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getRequestHeaders(),
|
headers: getRequestHeaders(),
|
||||||
body: JSON.stringify({ id, lang }),
|
body: JSON.stringify({ id, lang }),
|
||||||
|
@@ -404,6 +404,11 @@ redirect('/api/content/import', '/api/content/importURL');
|
|||||||
// Redirect deprecated moving UI endpoints
|
// Redirect deprecated moving UI endpoints
|
||||||
redirect('/savemovingui', '/api/moving-ui/save');
|
redirect('/savemovingui', '/api/moving-ui/save');
|
||||||
|
|
||||||
|
// Redirect Serp endpoints
|
||||||
|
redirect('/api/serpapi/search', '/api/search/serpapi');
|
||||||
|
redirect('/api/serpapi/visit', '/api/search/visit');
|
||||||
|
redirect('/api/serpapi/transcript', '/api/search/transcript');
|
||||||
|
|
||||||
// Moving UI
|
// Moving UI
|
||||||
app.use('/api/moving-ui', require('./src/endpoints/moving-ui').router);
|
app.use('/api/moving-ui', require('./src/endpoints/moving-ui').router);
|
||||||
|
|
||||||
@@ -499,8 +504,8 @@ app.use('/api/extra/classify', require('./src/endpoints/classify').router);
|
|||||||
// Image captioning
|
// Image captioning
|
||||||
app.use('/api/extra/caption', require('./src/endpoints/caption').router);
|
app.use('/api/extra/caption', require('./src/endpoints/caption').router);
|
||||||
|
|
||||||
// Web search extension
|
// Web search and scraping
|
||||||
app.use('/api/serpapi', require('./src/endpoints/serpapi').router);
|
app.use('/api/search', require('./src/endpoints/search').router);
|
||||||
|
|
||||||
// The different text generation APIs
|
// The different text generation APIs
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@ async function sendClaudeRequest(request, response) {
|
|||||||
let use_system_prompt = (request.body.model.startsWith('claude-2') || request.body.model.startsWith('claude-3')) && request.body.claude_use_sysprompt;
|
let use_system_prompt = (request.body.model.startsWith('claude-2') || request.body.model.startsWith('claude-3')) && request.body.claude_use_sysprompt;
|
||||||
let converted_prompt = convertClaudeMessages(request.body.messages, request.body.assistant_prefill, use_system_prompt, request.body.human_sysprompt_message, request.body.char_name, request.body.user_name);
|
let converted_prompt = convertClaudeMessages(request.body.messages, request.body.assistant_prefill, use_system_prompt, request.body.human_sysprompt_message, request.body.char_name, request.body.user_name);
|
||||||
// Add custom stop sequences
|
// Add custom stop sequences
|
||||||
const stopSequences = ['\n\nHuman:', '\n\nSystem:', '\n\nAssistant:'];
|
const stopSequences = [];
|
||||||
if (Array.isArray(request.body.stop)) {
|
if (Array.isArray(request.body.stop)) {
|
||||||
stopSequences.push(...request.body.stop);
|
stopSequences.push(...request.body.stop);
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ const visitHeaders = {
|
|||||||
'Sec-Fetch-User': '?1',
|
'Sec-Fetch-User': '?1',
|
||||||
};
|
};
|
||||||
|
|
||||||
router.post('/search', jsonParser, async (request, response) => {
|
router.post('/serpapi', jsonParser, async (request, response) => {
|
||||||
try {
|
try {
|
||||||
const key = readSecret(request.user.directories, SECRET_KEYS.SERPAPI);
|
const key = readSecret(request.user.directories, SECRET_KEYS.SERPAPI);
|
||||||
|
|
||||||
@@ -134,6 +134,41 @@ router.post('/transcript', jsonParser, async (request, response) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post('/searxng', jsonParser, async (request, response) => {
|
||||||
|
try {
|
||||||
|
const { baseUrl, query } = request.body;
|
||||||
|
|
||||||
|
if (!baseUrl || !query) {
|
||||||
|
console.log('Missing required parameters for /searxng');
|
||||||
|
return response.sendStatus(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(baseUrl);
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append('q', query);
|
||||||
|
params.append('format', 'html');
|
||||||
|
url.pathname = '/search';
|
||||||
|
url.search = params.toString();
|
||||||
|
|
||||||
|
const result = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: visitHeaders,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
const text = await result.text();
|
||||||
|
console.log('SearXNG request failed', result.statusText, text);
|
||||||
|
return response.sendStatus(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await result.text();
|
||||||
|
return response.send(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('SearXNG request failed', error);
|
||||||
|
return response.sendStatus(500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
router.post('/visit', jsonParser, async (request, response) => {
|
router.post('/visit', jsonParser, async (request, response) => {
|
||||||
try {
|
try {
|
||||||
const url = request.body.url;
|
const url = request.body.url;
|
Reference in New Issue
Block a user