diff --git a/.dockerignore b/.dockerignore
index e91e3fe3e..25d43c004 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -5,3 +5,4 @@ readme*
Start.bat
/dist
/backups/
+cloudflared.exe
diff --git a/.gitignore b/.gitignore
index be3012bd6..f7228af4f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,3 +28,4 @@ secrets.json
public/movingUI/
public/QuickReplies/
content.log
+cloudflared.exe
diff --git a/Remote-Link.cmd b/Remote-Link.cmd
new file mode 100644
index 000000000..f44f232f2
--- /dev/null
+++ b/Remote-Link.cmd
@@ -0,0 +1,18 @@
+@echo off
+echo ========================================================================================================================
+echo WARNING: Cloudflare Tunnel!
+echo ========================================================================================================================
+echo This script downloads and runs the latest cloudflared.exe from Cloudflare to set up an HTTPS tunnel to your SillyTavern!
+echo Using the randomly generated temporary tunnel URL, anyone can access your SillyTavern over the Internet while the tunnel
+echo is active. Keep the URL safe and secure your SillyTavern installation by setting a username and password in config.conf!
+echo.
+echo See https://docs.sillytavern.app/usage/remoteconnections/ for more details about how to secure your SillyTavern install.
+echo.
+echo By continuing you confirm that you're aware of the potential dangers of having a tunnel open and take all responsibility
+echo to properly use and secure it!
+echo.
+echo To abort, press Ctrl+C or close this window now!
+echo.
+pause
+if not exist cloudflared.exe curl -Lo cloudflared.exe https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe
+cloudflared.exe tunnel --url localhost:8000
diff --git a/public/index.html b/public/index.html
index 4a04a45e8..74c7be0d1 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1555,30 +1555,55 @@
+ For privacy reasons, your API key will be hidden after you reload the page.
+
+
+
Blocking API url
+ Example: http://127.0.0.1:5000/
+
+
+
+
Streaming API url
+ Example: ws://127.0.0.1:5005/api/v1/stream
+
+
+
+
+
+
+
Not connected
@@ -2639,6 +2664,14 @@
+
+
+
@@ -3276,7 +3309,7 @@
-
+
diff --git a/public/script.js b/public/script.js
index a5a84e7c5..4748266c1 100644
--- a/public/script.js
+++ b/public/script.js
@@ -17,6 +17,7 @@ import {
loadTextGenSettings,
generateTextGenWithStreaming,
getTextGenGenerationData,
+ formatTextGenURL,
} from "./scripts/textgen-settings.js";
import {
@@ -721,6 +722,7 @@ let is_get_status = false;
let is_get_status_novel = false;
let is_api_button_press = false;
let is_api_button_press_novel = false;
+let api_use_mancer_webui = false;
let is_send_press = false; //Send generation
let add_mes_without_animation = false;
@@ -854,9 +856,9 @@ async function getStatus() {
type: "POST", //
url: "/getstatus", //
data: JSON.stringify({
- api_server:
- main_api == "kobold" ? api_server : api_server_textgenerationwebui,
+ api_server: main_api == "kobold" ? api_server : api_server_textgenerationwebui,
main_api: main_api,
+ use_mancer: main_api == "textgenerationwebui" ? api_use_mancer_webui : false,
}),
beforeSend: function () { },
cache: false,
@@ -883,6 +885,11 @@ async function getStatus() {
kai_settings.can_use_streaming = canUseKoboldStreaming(data.koboldVersion);
}
+ // We didn't get a 200 status code, but the endpoint has an explanation. Which means it DID connect, but I digress.
+ if (online_status == "no_connection" && data.response) {
+ toastr.error(data.response, "API Error", {timeOut: 5000, preventDuplicates:true})
+ }
+
//console.log(online_status);
resultCheckStatus();
if (online_status !== "no_connection") {
@@ -2716,6 +2723,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
}
else if (main_api == 'textgenerationwebui') {
generate_data = getTextGenGenerationData(finalPromt, this_amount_gen, isImpersonate);
+ generate_data.use_mancer = api_use_mancer_webui;
}
else if (main_api == 'novel') {
const this_settings = novelai_settings[novelai_setting_names[nai_settings.preset_settings_novel]];
@@ -2978,6 +2986,13 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
activateSendButtons();
//console.log('runGenerate calling showSwipeBtns');
showSwipeButtons();
+
+ if (main_api == 'textgenerationwebui' && api_use_mancer_webui) {
+ const errorText = `
Inferencer endpoint is unhappy!
+ Returned status ${data.status} with the reason:
+ ${data.response}`;
+ callPopup(errorText, 'text');
+ }
}
console.debug('/savechat called by /Generate');
@@ -4554,7 +4569,9 @@ export function setUserName(value) {
name1 = default_user_name;
console.log(`User name changed to ${name1}`);
$("#your_name").val(name1);
- toastr.success(`Your messages will now be sent as ${name1}`, 'Current persona updated');
+ if (power_user.persona_show_notifications) {
+ toastr.success(`Your messages will now be sent as ${name1}`, 'Current persona updated');
+ }
saveSettings("change_name");
}
@@ -4653,7 +4670,7 @@ function setUserAvatar() {
const personaName = power_user.personas[user_avatar];
if (personaName && name1 !== personaName) {
const lockedPersona = chat_metadata['persona'];
- if (lockedPersona && lockedPersona !== user_avatar) {
+ if (lockedPersona && lockedPersona !== user_avatar && power_user.persona_show_notifications) {
toastr.info(
`To permanently set "${personaName}" as the selected persona, unlock and relock it using the "Lock" button. Otherwise, the selection resets upon reloading the chat.`,
`This chat is locked to a different persona (${power_user.personas[lockedPersona]}).`,
@@ -4760,7 +4777,9 @@ async function setDefaultPersona() {
}
console.log(`Removing default persona ${avatarId}`);
- toastr.info('This persona will no longer be used by default when you open a new chat.', `Default persona removed`);
+ if (power_user.persona_show_notifications) {
+ toastr.info('This persona will no longer be used by default when you open a new chat.', `Default persona removed`);
+ }
delete power_user.default_persona;
} else {
const confirm = await callPopup(`
Are you sure you want to set "${personaName}" as the default persona?
@@ -4772,7 +4791,9 @@ async function setDefaultPersona() {
}
power_user.default_persona = avatarId;
- toastr.success('This persona will be used by default when you open a new chat.', `Default persona set to ${personaName}`);
+ if (power_user.persona_show_notifications) {
+ toastr.success('This persona will be used by default when you open a new chat.', `Default persona set to ${personaName}`);
+ }
}
saveSettingsDebounced();
@@ -4835,18 +4856,22 @@ function lockUserNameToChat() {
console.log(`Unlocking persona for this chat ${chat_metadata['persona']}`);
delete chat_metadata['persona'];
saveMetadata();
- toastr.info('User persona is now unlocked for this chat. Click the "Lock" again to revert.', 'Persona unlocked');
+ if (power_user.persona_show_notifications) {
+ toastr.info('User persona is now unlocked for this chat. Click the "Lock" again to revert.', 'Persona unlocked');
+ }
updateUserLockIcon();
return;
}
if (!(user_avatar in power_user.personas)) {
console.log(`Creating a new persona ${user_avatar}`);
- toastr.info(
- 'Creating a new persona for currently selected user name and avatar...',
- 'Persona not set for this avatar',
- { timeOut: 10000, extendedTimeOut: 20000, },
- );
+ if (power_user.persona_show_notifications) {
+ toastr.info(
+ 'Creating a new persona for currently selected user name and avatar...',
+ 'Persona not set for this avatar',
+ { timeOut: 10000, extendedTimeOut: 20000, },
+ );
+ }
power_user.personas[user_avatar] = name1;
power_user.persona_descriptions[user_avatar] = { description: '', position: persona_description_positions.BEFORE_CHAR };
}
@@ -4855,7 +4880,9 @@ function lockUserNameToChat() {
saveMetadata();
saveSettingsDebounced();
console.log(`Locking persona for this chat ${user_avatar}`);
- toastr.success(`User persona is locked to ${name1} in this chat`);
+ if (power_user.persona_show_notifications) {
+ toastr.success(`User persona is locked to ${name1} in this chat`);
+ }
updateUserLockIcon();
}
@@ -5076,11 +5103,13 @@ async function getSettings(type) {
setWorldInfoSettings(settings, data);
- api_server_textgenerationwebui =
- settings.api_server_textgenerationwebui;
+ api_server_textgenerationwebui = settings.api_server_textgenerationwebui;
$("#textgenerationwebui_api_url_text").val(
api_server_textgenerationwebui
);
+ api_use_mancer_webui = settings.api_use_mancer_webui
+ $('#use-mancer-api-checkbox').prop("checked", api_use_mancer_webui);
+ $('#use-mancer-api-checkbox').trigger("change");
selected_button = settings.selected_button;
@@ -5114,6 +5143,7 @@ async function saveSettings(type) {
active_group: active_group,
api_server: api_server,
api_server_textgenerationwebui: api_server_textgenerationwebui,
+ api_use_mancer_webui: api_use_mancer_webui,
preset_settings: preset_settings,
user_avatar: user_avatar,
amount_gen: amount_gen,
@@ -7508,7 +7538,7 @@ $(document).ready(function () {
Delete the character?
THIS IS PERMANENT!
`
);
@@ -7691,16 +7721,28 @@ $(document).ready(function () {
}
});
- $("#api_button_textgenerationwebui").click(function (e) {
+ $("#use-mancer-api-checkbox").on("change", function (e) {
+ const enabled = $("#use-mancer-api-checkbox").prop("checked");
+ $("#mancer-api-ui").toggle(enabled);
+ api_use_mancer_webui = enabled;
+ saveSettingsDebounced();
+ getStatus();
+ });
+
+ $("#api_button_textgenerationwebui").click(async function (e) {
e.stopPropagation();
if ($("#textgenerationwebui_api_url_text").val() != "") {
- let value = formatKoboldUrl($("#textgenerationwebui_api_url_text").val().trim());
-
+ let value = formatTextGenURL($("#textgenerationwebui_api_url_text").val().trim())
if (!value) {
- callPopup('Please enter a valid URL.', 'text');
+ callPopup('Please enter a valid URL. WebUI URLs should end with /api', 'text');
return;
}
+ const mancer_key = $("#api_key_mancer").val().trim();
+ if (mancer_key.length) {
+ await writeSecret(SECRET_KEYS.MANCER, mancer_key);
+ }
+
$("#textgenerationwebui_api_url_text").val(value);
$("#api_loading_textgenerationwebui").css("display", "inline-block");
$("#api_button_textgenerationwebui").css("display", "none");
diff --git a/public/scripts/RossAscends-mods.js b/public/scripts/RossAscends-mods.js
index cb1188cf3..88090b512 100644
--- a/public/scripts/RossAscends-mods.js
+++ b/public/scripts/RossAscends-mods.js
@@ -534,12 +534,14 @@ export function dragElement(elmnt) {
if (elmntHeader.length) {
elmntHeader.off('mousedown').on('mousedown', (e) => {
-
+ hasBeenDraggedByUser = true
+ observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] });
dragMouseDown(e);
});
- $(elmnt).off('mousedown').on('mousedown', () => { isMouseDown = true })
- } else {
- elmnt.off('mousedown').on('mousedown', dragMouseDown);
+ $(elmnt).off('mousedown').on('mousedown', () => {
+ isMouseDown = true
+ observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] });
+ })
}
const observer = new MutationObserver((mutations) => {
@@ -618,7 +620,7 @@ export function dragElement(elmnt) {
}
//prevent resizing from top left into the top bar
- if (top <= 40 && maxX >= topBarFirstX && left <= topBarFirstX
+ if (top < 40 && maxX >= topBarFirstX && left <= topBarFirstX
) {
console.debug('prevent topbar underlap resize')
elmnt.css('width', width - 1 + "px");
@@ -674,8 +676,6 @@ export function dragElement(elmnt) {
}
});
- observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] });
-
function dragMouseDown(e) {
if (e) {
@@ -745,6 +745,7 @@ export function dragElement(elmnt) {
$("body").css("overflow", "");
// Clear the "data-dragged" attribute
elmnt.attr('data-dragged', 'false');
+ observer.disconnect()
console.debug(`Saving ${elmntName} UI position`)
saveSettingsDebounced();
diff --git a/public/scripts/extensions/bulk-edit/index.js b/public/scripts/extensions/bulk-edit/index.js
new file mode 100644
index 000000000..b72b662a1
--- /dev/null
+++ b/public/scripts/extensions/bulk-edit/index.js
@@ -0,0 +1,108 @@
+import { characters, getCharacters, saveSettingsDebounced, handleDeleteCharacter } from "../../../script.js";
+
+let is_bulk_edit = false;
+
+/**
+ * Toggles bulk edit mode on/off when the edit button is clicked.
+ */
+function onEditButtonClick() {
+ console.log("Edit button clicked");
+ // toggle bulk edit mode
+ if (is_bulk_edit) {
+ disableBulkSelect();
+ // hide the delete button
+ $("#bulkDeleteButton").hide();
+ is_bulk_edit = false;
+ } else {
+ enableBulkSelect();
+ // show the delete button
+ $("#bulkDeleteButton").show();
+ is_bulk_edit = true;
+ }
+}
+
+/**
+ * Deletes the character with the given chid.
+ *
+ * @param {string} this_chid - The chid of the character to delete.
+ */
+async function deleteCharacter(this_chid) {
+ await handleDeleteCharacter("del_ch", this_chid);
+}
+
+/**
+ * Deletes all characters that have been selected via the bulk checkboxes.
+ */
+async function onDeleteButtonClick() {
+ console.log("Delete button clicked");
+
+ // Create a mapping of chid to avatar
+ let toDelete = [];
+ $(".bulk_select_checkbox:checked").each((i, el) => {
+ const chid = $(el).parent().attr("chid");
+ const avatar = characters[chid].avatar;
+ // Add the avatar to the list of avatars to delete
+ toDelete.push(avatar);
+ });
+
+ // Delete the characters
+ for (const avatar of toDelete) {
+ console.log(`Deleting character with avatar ${avatar}`);
+ await getCharacters();
+
+ //chid should be the key of the character with the given avatar
+ const chid = Object.keys(characters).find((key) => characters[key].avatar === avatar);
+ console.log(`Deleting character with chid ${chid}`);
+ await deleteCharacter(chid);
+ }
+}
+
+/**
+ * Adds the bulk edit and delete buttons to the UI.
+ */
+function addButtons() {
+ const editButton = $(
+ ""
+ );
+ const deleteButton = $(
+ ""
+ );
+
+ $("#charListGridToggle").after(editButton, deleteButton);
+
+ $("#bulkEditButton").on("click", onEditButtonClick);
+ $("#bulkDeleteButton").on("click", onDeleteButtonClick);
+}
+
+/**
+ * Enables bulk selection by adding a checkbox next to each character.
+ */
+function enableBulkSelect() {
+ $(".character_select").each((i, el) => {
+ const character = $(el).text();
+ const checkbox = $("");
+ checkbox.on("change", () => {
+ // Do something when the checkbox is changed
+ });
+ $(el).prepend(checkbox);
+ });
+ // We also need to disable the default click event for the character_select divs
+ $(document).on("click", ".bulk_select_checkbox", function (event) {
+ event.stopImmediatePropagation();
+ });
+}
+
+/**
+ * Disables bulk selection by removing the checkboxes.
+ */
+function disableBulkSelect() {
+ $(".bulk_select_checkbox").remove();
+}
+
+/**
+ * Entry point that runs on page load.
+ */
+jQuery(async () => {
+ addButtons();
+ // loadSettings();
+});
diff --git a/public/scripts/extensions/bulk-edit/manifest.json b/public/scripts/extensions/bulk-edit/manifest.json
new file mode 100644
index 000000000..b86a2c82b
--- /dev/null
+++ b/public/scripts/extensions/bulk-edit/manifest.json
@@ -0,0 +1,11 @@
+{
+ "display_name": "Bulk Card Editor",
+ "loading_order": 9,
+ "requires": [],
+ "optional": [],
+ "js": "index.js",
+ "css": "style.css",
+ "author": "city-unit",
+ "version": "1.0.0",
+ "homePage": "https://github.com/city-unit"
+}
diff --git a/public/scripts/extensions/expressions/index.js b/public/scripts/extensions/expressions/index.js
index bddc9132c..6656353c5 100644
--- a/public/scripts/extensions/expressions/index.js
+++ b/public/scripts/extensions/expressions/index.js
@@ -449,7 +449,7 @@ async function loadLiveChar() {
function handleImageChange() {
const imgElement = document.querySelector('img#expression-image.expression');
-
+
if (!imgElement) {
console.log("Cannot find addExpressionImage()");
return;
@@ -459,6 +459,7 @@ function handleImageChange() {
previousSrc = imgElement.src;
// Method get IP of endpoint
const live2dResultFeedSrc = `${getApiUrl()}/api/live2d/result_feed`;
+ $('#expression-holder').css({ display: '' });
if (imgElement.src !== live2dResultFeedSrc) {
const expressionImageElement = document.querySelector('.expression_list_image');
@@ -922,7 +923,7 @@ async function setExpression(character, expression, force) {
if (imgElement) {
console.log("setting value");
imgElement.src = getApiUrl() + '/api/live2d/result_feed';
- }
+ }
}
}
diff --git a/public/scripts/extensions/memory/index.js b/public/scripts/extensions/memory/index.js
index f2e9433ea..e33994bc1 100644
--- a/public/scripts/extensions/memory/index.js
+++ b/public/scripts/extensions/memory/index.js
@@ -1,6 +1,7 @@
import { getStringHash, debounce, waitUntilCondition, extractAllWords } from "../../utils.js";
import { getContext, getApiUrl, extension_settings, doExtrasFetch, modules } from "../../extensions.js";
import { eventSource, event_types, extension_prompt_types, generateQuietPrompt, is_send_press, saveSettingsDebounced, substituteParams } from "../../../script.js";
+import { is_group_generating, selected_group } from "../../group-chats.js";
export { MODULE_NAME };
const MODULE_NAME = '1_memory';
@@ -333,6 +334,10 @@ async function summarizeChat(context) {
async function summarizeChatMain(context, force) {
try {
+ // Wait for group to finish generating
+ if (selected_group) {
+ await waitUntilCondition(() => is_group_generating === false, 1000, 10);
+ }
// Wait for the send button to be released
waitUntilCondition(() => is_send_press === false, 30000, 100);
} catch {
diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js
index 133db46e8..d28119a61 100644
--- a/public/scripts/power-user.js
+++ b/public/scripts/power-user.js
@@ -27,7 +27,7 @@ import {
import { registerSlashCommand } from "./slash-commands.js";
-import { delay, debounce } from "./utils.js";
+import { delay } from "./utils.js";
export {
loadPowerUserSettings,
@@ -184,6 +184,7 @@ let power_user = {
persona_description: '',
persona_description_position: persona_description_positions.BEFORE_CHAR,
+ persona_show_notifications: true,
custom_stopping_strings: '',
fuzzy_search: false,
@@ -678,6 +679,7 @@ function loadPowerUserSettings(settings, data) {
$('#auto_swipe_blacklist_threshold').val(power_user.auto_swipe_blacklist_threshold);
$('#custom_stopping_strings').val(power_user.custom_stopping_strings);
$('#fuzzy_search_checkbox').prop("checked", power_user.fuzzy_search);
+ $('#persona_show_notifications').prop("checked", power_user.persona_show_notifications);
$("#console_log_prompts").prop("checked", power_user.console_log_prompts);
$('#auto_fix_generated_markdown').prop("checked", power_user.auto_fix_generated_markdown);
@@ -1998,6 +2000,11 @@ $(document).ready(() => {
saveSettingsDebounced();
});
+ $('#persona_show_notifications').on('input', function () {
+ power_user.persona_show_notifications = !!$(this).prop('checked');
+ saveSettingsDebounced();
+ });
+
$(window).on('focus', function () {
browser_has_focus = true;
});
diff --git a/public/scripts/secrets.js b/public/scripts/secrets.js
index 90edb72f0..00203a106 100644
--- a/public/scripts/secrets.js
+++ b/public/scripts/secrets.js
@@ -2,6 +2,7 @@ import { callPopup, getRequestHeaders } from "../script.js";
export const SECRET_KEYS = {
HORDE: 'api_key_horde',
+ MANCER: 'api_key_mancer',
OPENAI: 'api_key_openai',
NOVEL: 'api_key_novel',
CLAUDE: 'api_key_claude',
@@ -11,6 +12,7 @@ export const SECRET_KEYS = {
const INPUT_MAP = {
[SECRET_KEYS.HORDE]: '#horde_api_key',
+ [SECRET_KEYS.MANCER]: '#api_key_mancer',
[SECRET_KEYS.OPENAI]: '#api_key_openai',
[SECRET_KEYS.NOVEL]: '#api_key_novel',
[SECRET_KEYS.CLAUDE]: '#api_key_claude',
diff --git a/public/scripts/textgen-settings.js b/public/scripts/textgen-settings.js
index 7bdab35e4..cc984e361 100644
--- a/public/scripts/textgen-settings.js
+++ b/public/scripts/textgen-settings.js
@@ -10,6 +10,7 @@ export {
textgenerationwebui_settings,
loadTextGenSettings,
generateTextGenWithStreaming,
+ formatTextGenURL,
}
const textgenerationwebui_settings = {
@@ -94,6 +95,16 @@ function selectPreset(name) {
saveSettingsDebounced();
}
+function formatTextGenURL(value) {
+ try {
+ const url = new URL(value);
+ if (url.pathname.endsWith('/api')) {
+ return url.toString();
+ }
+ } catch { } // Try and Catch both fall through to the same return.
+ return null;
+}
+
function convertPresets(presets) {
return Array.isArray(presets) ? presets.map(JSON.parse) : [];
}
diff --git a/public/style.css b/public/style.css
index fda0ee5e3..326d6f09d 100644
--- a/public/style.css
+++ b/public/style.css
@@ -3040,9 +3040,22 @@ h5 {
opacity: 0.4;
}
+
.PastChat_cross:hover {
color: red;
filter: drop-shadow(0 0 2px red);
+ -webkit-animation: infinite-spinning 1s ease-out 0s infinite normal;
+ animation: infinite-spinning 1s ease-out 0s infinite normal;
+}
+
+/* HEINOUS */
+@keyframes infinite-spinning {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
}
#export_character_div {
@@ -4409,6 +4422,10 @@ toolcool-color-picker {
width: 50px;
}
+.indent20p {
+ margin-left: 20px;
+}
+
.wi-enter-footer-text {
font-size: calc(var(--mainFontSize) * 0.8);
color: var(--SmartThemeBodyColor);
diff --git a/server.js b/server.js
index e6a1d0d20..11146e29b 100644
--- a/server.js
+++ b/server.js
@@ -146,6 +146,14 @@ let response_getstatus;
let first_run = true;
+
+function get_mancer_headers() {
+ const api_key_mancer = readSecret(SECRET_KEYS.MANCER);
+ return api_key_mancer ? { "X-API-KEY": api_key_mancer} : {};
+}
+
+
+
//RossAscends: Added function to format dates used in files and chat timestamps to a humanized format.
//Mostly I wanted this to be for file names, but couldn't figure out exactly where the filename save code was as everything seemed to be connected.
//During testing, this performs the same as previous date.now() structure.
@@ -640,13 +648,22 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
signal: controller.signal,
};
+ if (request.body.use_mancer) {
+ args.headers = Object.assign(args.headers, get_mancer_headers());
+ }
+
try {
const data = await postAsync(api_server + "/v1/generate", args);
console.log(data);
return response_generate.send(data);
} catch (error) {
+ retval = { error: true, status: error.status, response: error.statusText };
console.log(error);
- return response_generate.send({ error: true });
+ try {
+ retval.response = await error.json();
+ retval.response = retval.response.result;
+ } catch {}
+ return response_generate.send(retval);
}
}
});
@@ -710,6 +727,11 @@ app.post("/getstatus", jsonParser, async function (request, response_getstatus =
var args = {
headers: { "Content-Type": "application/json" }
};
+
+ if (main_api == 'textgenerationwebui' && request.body.use_mancer) {
+ args.headers = Object.assign(args.headers, get_mancer_headers());
+ }
+
var url = api_server + "/v1/model";
let version = '';
let koboldVersion = {};
@@ -730,18 +752,18 @@ app.post("/getstatus", jsonParser, async function (request, response_getstatus =
};
}
}
- client.get(url, args, function (data, response) {
+ client.get(url, args, async function (data, response) {
if (typeof data !== 'object') {
data = {};
}
if (response.statusCode == 200) {
data.version = version;
data.koboldVersion = koboldVersion;
- if (data.result != "ReadOnly") {
- } else {
+ if (data.result == "ReadOnly") {
data.result = "no_connection";
}
} else {
+ data.response = data.result;
data.result = "no_connection";
}
response_getstatus.send(data);
@@ -3453,6 +3475,10 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
body: JSON.stringify({ "prompt": text }),
headers: { "Content-Type": "application/json" }
};
+
+ if (main_api == 'textgenerationwebui' && request.body.use_mancer) {
+ args.headers = Object.assign(args.headers, get_mancer_headers());
+ }
const data = await postAsync(api_server + "/v1/token-count", args);
console.log(data);
@@ -3659,6 +3685,7 @@ const SECRETS_FILE = './secrets.json';
const SETTINGS_FILE = './public/settings.json';
const SECRET_KEYS = {
HORDE: 'api_key_horde',
+ MANCER: 'api_key_mancer',
OPENAI: 'api_key_openai',
NOVEL: 'api_key_novel',
CLAUDE: 'api_key_claude',