diff --git a/Dockerfile b/Dockerfile index 9ab76c8cf..3afd3b7a5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,18 +23,18 @@ COPY . ./ # Copy default chats, characters and user avatars to .default folder RUN \ - IFS="," RESOURCES="characters,chats,groups,group chats,User Avatars,worlds,OpenAI Settings,NovelAI Settings,KoboldAI Settings,TextGen Settings" && \ + IFS="," RESOURCES="assets,backgrounds,user,context,instruct,QuickReplies,movingUI,themes,characters,chats,groups,group chats,User Avatars,worlds,OpenAI Settings,NovelAI Settings,KoboldAI Settings,TextGen Settings" && \ \ echo "*** Store default $RESOURCES in .default ***" && \ - for R in $RESOURCES; do mv "public/$R" "public/$R.default"; done && \ + for R in $RESOURCES; do mv "public/$R" "public/$R.default"; done || true && \ \ echo "*** Create symbolic links to config directory ***" && \ - for R in $RESOURCES; do ln -s "../config/$R" "public/$R"; done && \ - # rm "config.conf" "public/settings.json" "public/css/bg_load.css" && \ - ln -s "./config/config.conf" "config.conf" && \ - ln -s "../config/settings.json" "public/settings.json" && \ - ln -s "../../config/bg_load.css" "public/css/bg_load.css" && \ - mkdir "config" + for R in $RESOURCES; do ln -s "../config/$R" "public/$R"; done || true && \ + \ + ln -s "./config/config.conf" "config.conf" || true && \ + ln -s "../config/settings.json" "public/settings.json" || true && \ + ln -s "../../config/bg_load.css" "public/css/bg_load.css" || true && \ + mkdir "config" || true # Cleanup unnecessary files RUN \ diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index bbdfd5006..f3dd2aae9 100644 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -1,7 +1,7 @@ #!/bin/sh # Initialize missing user files -IFS="," RESOURCES="characters,chats,groups,group chats,User Avatars,worlds,OpenAI Settings,NovelAI Settings,KoboldAI Settings,TextGen Settings" +IFS="," RESOURCES="assets,backgrounds,user,context,instruct,QuickReplies,movingUI,themes,characters,chats,groups,group chats,User Avatars,worlds,OpenAI Settings,NovelAI Settings,KoboldAI Settings,TextGen Settings" for R in $RESOURCES; do if [ ! -e "config/$R" ]; then echo "Resource not found, copying from defaults: $R" @@ -24,5 +24,17 @@ if [ ! -e "config/bg_load.css" ]; then cp -r "default/bg_load.css" "config/bg_load.css" fi +CONFIG_FILE="config.conf" + +if grep -q "listen = false" $CONFIG_FILE; then + echo -e "\033[1;31mThe listen parameter is set to false. If you can't connect to the server, edit the \"docker/config/config.conf\" file and restart the container.\033[0m" + sleep 5 +fi + +if grep -q "whitelistMode = true" $CONFIG_FILE; then + echo -e "\033[1;31mThe whitelistMode parameter is set to true. If you can't connect to the server, edit the \"docker/config/config.conf\" file and restart the container.\033[0m" + sleep 5 +fi + # Start the server exec node server.js diff --git a/public/index.html b/public/index.html index 23ed2435e..1d256980f 100644 --- a/public/index.html +++ b/public/index.html @@ -1618,7 +1618,7 @@ oobabooga/text-generation-webui - Make sure you run it with --extensions openai flag + Make sure you run it with --api flag
@@ -4711,4 +4711,4 @@ - \ No newline at end of file + diff --git a/public/scripts/secrets.js b/public/scripts/secrets.js index edf4123dc..1e0133c6e 100644 --- a/public/scripts/secrets.js +++ b/public/scripts/secrets.js @@ -12,6 +12,7 @@ export const SECRET_KEYS = { AI21: 'api_key_ai21', SCALE_COOKIE: 'scale_cookie', PALM: 'api_key_palm', + SERPAPI: 'api_key_serpapi', } const INPUT_MAP = { diff --git a/public/scripts/textgen-settings.js b/public/scripts/textgen-settings.js index 6c898cebb..2da9e5916 100644 --- a/public/scripts/textgen-settings.js +++ b/public/scripts/textgen-settings.js @@ -11,6 +11,7 @@ import { import { power_user, + registerDebugFunction, } from "./power-user.js"; import { getTextTokens, tokenizers } from "./tokenizers.js"; import { onlyUnique } from "./utils.js"; @@ -29,7 +30,10 @@ export const textgen_types = { }; // Maybe let it be configurable in the future? -export const MANCER_SERVER = 'https://neuro.mancer.tech'; +// (7 days later) The future has come. +const MANCER_SERVER_KEY = 'mancer_server'; +const MANCER_SERVER_DEFAULT = 'https://neuro.mancer.tech'; +export let MANCER_SERVER = localStorage.getItem(MANCER_SERVER_KEY) ?? MANCER_SERVER_DEFAULT; const textgenerationwebui_settings = { temp: 0.7, @@ -259,6 +263,15 @@ function loadTextGenSettings(data, settings) { $(this).show() }) } + + registerDebugFunction('change-mancer-url', 'Change Mancer base URL', 'Change Mancer API server base URL', () => { + const result = prompt(`Enter Mancer base URL\nDefault: ${MANCER_SERVER_DEFAULT}`, MANCER_SERVER); + + if (result) { + localStorage.setItem(MANCER_SERVER_KEY, result); + MANCER_SERVER = result; + } + }); } export function isMancer() { diff --git a/server.js b/server.js index d86e8df05..c3f47880b 100644 --- a/server.js +++ b/server.js @@ -3528,6 +3528,9 @@ require('./src/classify').registerEndpoints(app, jsonParser); // Image captioning require('./src/caption').registerEndpoints(app, jsonParser); +// Web search extension +require('./src/serpapi').registerEndpoints(app, jsonParser); + const tavernUrl = new URL( (cliArguments.ssl ? 'https://' : 'http://') + (listen ? '0.0.0.0' : '127.0.0.1') + diff --git a/src/assets.js b/src/assets.js index a489c5dfb..43c0e6f5c 100644 --- a/src/assets.js +++ b/src/assets.js @@ -94,7 +94,7 @@ function registerEndpoints(app, jsonParser) { //console.debug("FILE FOUND:",files) for (let file of files) { file = path.normalize(file.replace('public' + path.sep, '')); - if (file.endsWith("model3.json")) { + if (file.includes("model") && file.endsWith(".json")) { //console.debug("Asset live2d model found:",file) output[folder].push(path.normalize(path.join(file))); } @@ -273,7 +273,7 @@ function registerEndpoints(app, jsonParser) { if (fs.statSync(live2dModelPath).isDirectory()) { for (let file of fs.readdirSync(live2dModelPath)) { //console.debug("Character live2d model found:", file) - if (file.includes("model")) + if (file.includes("model") && file.endsWith(".json")) output.push(path.join("characters", name, category, modelFolder, file)); } } diff --git a/src/secrets.js b/src/secrets.js index f59da2779..6da764529 100644 --- a/src/secrets.js +++ b/src/secrets.js @@ -21,6 +21,7 @@ const SECRET_KEYS = { ONERING_URL: 'oneringtranslator_url', DEEPLX_URL: 'deeplx_url', PALM: 'api_key_palm', + SERPAPI: 'api_key_serpapi', } /** diff --git a/src/serpapi.js b/src/serpapi.js new file mode 100644 index 000000000..38fc6928a --- /dev/null +++ b/src/serpapi.js @@ -0,0 +1,39 @@ +const fetch = require('node-fetch').default; +const { readSecret } = require('./secrets'); + +/** + * Registers the SerpApi endpoints. + * @param {import("express").Express} app + * @param {any} jsonParser + */ +function registerEndpoints(app, jsonParser) { + app.post('/api/serpapi/search', jsonParser, async (request, response) => { + try { + const key = readSecret('serpapi_key'); + + if (!key) { + console.log('No SerpApi key found'); + return response.sendStatus(401); + } + + const { query } = request.body; + const result = await fetch(`https://serpapi.com/search.json?q=${encodeURIComponent(query)}&api_key=${key}`); + + if (!result.ok) { + const text = await result.text(); + console.log('SerpApi request failed', result.statusText, text); + return response.status(500).send(text); + } + + const data = await result.json(); + return response.json(data); + } catch (error) { + console.log(error); + return response.sendStatus(500); + } + }); +} + +module.exports = { + registerEndpoints, +};