sillytavern 1.11.3 → 1.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -19
- package/public/index.html +10 -1
- package/public/script.js +66 -26
- package/public/scripts/RossAscends-mods.js +2 -2
- package/public/scripts/extensions/expressions/index.js +77 -19
- package/public/scripts/extensions/regex/engine.js +2 -2
- package/public/scripts/extensions/tts/index.js +1 -1
- package/public/scripts/nai-settings.js +1 -1
- package/public/scripts/openai.js +31 -14
- package/public/scripts/secrets.js +2 -0
- package/public/scripts/slash-commands.js +14 -8
- package/public/scripts/textgen-settings.js +5 -2
- package/public/user/.gitkeep +0 -0
- package/src/additional-headers.js +11 -0
- package/src/constants.js +1 -0
- package/src/endpoints/backends/chat-completions.js +14 -33
- package/src/endpoints/novelai.js +1 -1
- package/src/endpoints/openai.js +1 -0
- package/src/endpoints/secrets.js +1 -0
- package/src/endpoints/vectors.js +1 -1
- package/.github/workflows/build-and-publish-release.yml +0 -37
- package/.github/workflows/build-and-publish-staging.yml +0 -37
package/package.json
CHANGED
|
@@ -55,11 +55,10 @@
|
|
|
55
55
|
"type": "git",
|
|
56
56
|
"url": "https://github.com/SillyTavern/SillyTavern.git"
|
|
57
57
|
},
|
|
58
|
-
"version": "1.11.
|
|
58
|
+
"version": "1.11.4",
|
|
59
59
|
"scripts": {
|
|
60
60
|
"start": "node server.js",
|
|
61
61
|
"start-multi": "node server.js --disableCsrf",
|
|
62
|
-
"pkg": "pkg --compress Gzip --no-bytecode --public .",
|
|
63
62
|
"postinstall": "node post-install.js",
|
|
64
63
|
"lint": "eslint \"src/**/*.js\" \"public/**/*.js\" ./*.js",
|
|
65
64
|
"lint-fix": "eslint \"src/**/*.js\" \"public/**/*.js\" ./*.js --fix"
|
|
@@ -72,24 +71,8 @@
|
|
|
72
71
|
"no-var": "off"
|
|
73
72
|
},
|
|
74
73
|
"main": "server.js",
|
|
75
|
-
"pkg": {
|
|
76
|
-
"targets": [
|
|
77
|
-
"node18-linux-x64",
|
|
78
|
-
"node18-macos-x64",
|
|
79
|
-
"node18-windows-x64"
|
|
80
|
-
],
|
|
81
|
-
"assets": [
|
|
82
|
-
"node_modules/**/*"
|
|
83
|
-
],
|
|
84
|
-
"outputPath": "dist",
|
|
85
|
-
"scripts": [
|
|
86
|
-
"server.js"
|
|
87
|
-
]
|
|
88
|
-
},
|
|
89
74
|
"devDependencies": {
|
|
90
75
|
"eslint": "^8.55.0",
|
|
91
|
-
"jquery": "^3.6.4"
|
|
92
|
-
"pkg": "^5.8.1",
|
|
93
|
-
"pkg-fetch": "^3.5.2"
|
|
76
|
+
"jquery": "^3.6.4"
|
|
94
77
|
}
|
|
95
78
|
}
|
package/public/index.html
CHANGED
|
@@ -1277,7 +1277,7 @@
|
|
|
1277
1277
|
<div data-newbie-hidden data-tg-type="ooba, koboldcpp, aphrodite, tabby" class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0">
|
|
1278
1278
|
<small data-i18n="Smoothing Factor">Smoothing Factor</small>
|
|
1279
1279
|
<input class="neo-range-slider" type="range" id="smoothing_factor_textgenerationwebui" name="volume" min="0" max="10" step="0.01" />
|
|
1280
|
-
<input class="neo-range-input" type="number" min="0" max="
|
|
1280
|
+
<input class="neo-range-input" type="number" min="0" max="10" step="0.01" data-for="smoothing_factor_textgenerationwebui" id="smoothing_factor_counter_textgenerationwebui">
|
|
1281
1281
|
</div>
|
|
1282
1282
|
<!--
|
|
1283
1283
|
<div data-tg-type="aphrodite" class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0" data-i18n="Responses">
|
|
@@ -1916,6 +1916,15 @@
|
|
|
1916
1916
|
Make sure you run it with <code>--api</code> flag
|
|
1917
1917
|
</span>
|
|
1918
1918
|
</div>
|
|
1919
|
+
<h4 data-i18n="API key (optional)">API key (optional)</h4>
|
|
1920
|
+
<div class="flex-container">
|
|
1921
|
+
<input id="api_key_ooba" name="api_key_ooba" class="text_pole flex1 wide100p" maxlength="500" size="35" type="text" autocomplete="off">
|
|
1922
|
+
<div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_ooba">
|
|
1923
|
+
</div>
|
|
1924
|
+
</div>
|
|
1925
|
+
<div data-for="api_key_ooba" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page.">
|
|
1926
|
+
For privacy reasons, your API key will be hidden after you reload the page.
|
|
1927
|
+
</div>
|
|
1919
1928
|
<div class="flex1">
|
|
1920
1929
|
<h4 data-i18n="Server url">Server URL</h4>
|
|
1921
1930
|
<small data-i18n="Example: http://127.0.0.1:5000 ">Example: http://127.0.0.1:5000</small>
|
package/public/script.js
CHANGED
|
@@ -2179,6 +2179,7 @@ function substituteParams(content, _name1, _name2, _original, _group, _replaceCh
|
|
|
2179
2179
|
environment.user = _name1 ?? name1;
|
|
2180
2180
|
environment.char = _name2 ?? name2;
|
|
2181
2181
|
environment.group = environment.charIfNotGroup = _group ?? name2;
|
|
2182
|
+
environment.model = getGeneratingModel();
|
|
2182
2183
|
|
|
2183
2184
|
return evaluateMacros(content, environment);
|
|
2184
2185
|
}
|
|
@@ -5420,17 +5421,21 @@ export async function getUserAvatars(doRender = true, openPageAt = '') {
|
|
|
5420
5421
|
if (response.ok) {
|
|
5421
5422
|
const allEntities = await response.json();
|
|
5422
5423
|
|
|
5423
|
-
if (!
|
|
5424
|
-
return
|
|
5424
|
+
if (!Array.isArray(allEntities)) {
|
|
5425
|
+
return [];
|
|
5425
5426
|
}
|
|
5426
5427
|
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
const
|
|
5430
|
-
const bName = String(power_user.personas[b]);
|
|
5428
|
+
allEntities.sort((a, b) => {
|
|
5429
|
+
const aName = String(power_user.personas[a] || a);
|
|
5430
|
+
const bName = String(power_user.personas[b] || b);
|
|
5431
5431
|
return power_user.persona_sort_order === 'asc' ? aName.localeCompare(bName) : bName.localeCompare(aName);
|
|
5432
5432
|
});
|
|
5433
5433
|
|
|
5434
|
+
if (!doRender) {
|
|
5435
|
+
return allEntities;
|
|
5436
|
+
}
|
|
5437
|
+
|
|
5438
|
+
const entities = personasFilter.applyFilters(allEntities);
|
|
5434
5439
|
const storageKey = 'Personas_PerPage';
|
|
5435
5440
|
const listId = '#user_avatar_block';
|
|
5436
5441
|
const perPage = Number(localStorage.getItem(storageKey)) || 5;
|
|
@@ -5490,6 +5495,7 @@ function highlightSelectedAvatar() {
|
|
|
5490
5495
|
* @returns {JQuery<HTMLElement>} Avatar block
|
|
5491
5496
|
*/
|
|
5492
5497
|
function getUserAvatarBlock(name) {
|
|
5498
|
+
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
|
5493
5499
|
const template = $('#user_avatar_template .avatar-container').clone();
|
|
5494
5500
|
const personaName = power_user.personas[name];
|
|
5495
5501
|
const personaDescription = power_user.persona_descriptions[name]?.description;
|
|
@@ -5498,7 +5504,11 @@ function getUserAvatarBlock(name) {
|
|
|
5498
5504
|
template.attr('imgfile', name);
|
|
5499
5505
|
template.find('.avatar').attr('imgfile', name).attr('title', name);
|
|
5500
5506
|
template.toggleClass('default_persona', name === power_user.default_persona);
|
|
5501
|
-
|
|
5507
|
+
let avatarUrl = getUserAvatar(name);
|
|
5508
|
+
if (isFirefox) {
|
|
5509
|
+
avatarUrl += '?t=' + Date.now();
|
|
5510
|
+
}
|
|
5511
|
+
template.find('img').attr('src', avatarUrl);
|
|
5502
5512
|
$('#user_avatar_block').append(template);
|
|
5503
5513
|
return template;
|
|
5504
5514
|
}
|
|
@@ -6080,6 +6090,21 @@ export async function getPastCharacterChats(characterId = null) {
|
|
|
6080
6090
|
return data;
|
|
6081
6091
|
}
|
|
6082
6092
|
|
|
6093
|
+
/**
|
|
6094
|
+
* Helper for `displayPastChats`, to make the same info consistently available for other functions
|
|
6095
|
+
*/
|
|
6096
|
+
function getCurrentChatDetails() {
|
|
6097
|
+
if (!characters[this_chid] && !selected_group) {
|
|
6098
|
+
return { sessionName: '', group: null, characterName: '', avatarImgURL: '' };
|
|
6099
|
+
}
|
|
6100
|
+
|
|
6101
|
+
const group = selected_group ? groups.find(x => x.id === selected_group) : null;
|
|
6102
|
+
const currentChat = selected_group ? group?.chat_id : characters[this_chid]['chat'];
|
|
6103
|
+
const displayName = selected_group ? group?.name : characters[this_chid].name;
|
|
6104
|
+
const avatarImg = selected_group ? group?.avatar_url : getThumbnailUrl('avatar', characters[this_chid]['avatar']);
|
|
6105
|
+
return { sessionName: currentChat, group: group, characterName: displayName, avatarImgURL: avatarImg };
|
|
6106
|
+
}
|
|
6107
|
+
|
|
6083
6108
|
/**
|
|
6084
6109
|
* Displays the past chats for a character or a group based on the selected context.
|
|
6085
6110
|
* The function first fetches the chats, processes them, and then displays them in
|
|
@@ -6090,7 +6115,6 @@ export async function displayPastChats() {
|
|
|
6090
6115
|
$('#select_chat_div').empty();
|
|
6091
6116
|
$('#select_chat_search').val('').off('input');
|
|
6092
6117
|
|
|
6093
|
-
const group = selected_group ? groups.find(x => x.id === selected_group) : null;
|
|
6094
6118
|
const data = await (selected_group ? getGroupPastChats(selected_group) : getPastCharacterChats());
|
|
6095
6119
|
|
|
6096
6120
|
if (!data) {
|
|
@@ -6098,10 +6122,14 @@ export async function displayPastChats() {
|
|
|
6098
6122
|
return;
|
|
6099
6123
|
}
|
|
6100
6124
|
|
|
6101
|
-
const
|
|
6102
|
-
const
|
|
6103
|
-
const
|
|
6125
|
+
const chatDetails = getCurrentChatDetails();
|
|
6126
|
+
const group = chatDetails.group;
|
|
6127
|
+
const currentChat = chatDetails.sessionName;
|
|
6128
|
+
const displayName = chatDetails.characterName;
|
|
6129
|
+
const avatarImg = chatDetails.avatarImgURL;
|
|
6130
|
+
|
|
6104
6131
|
const rawChats = await getChatsFromFiles(data, selected_group);
|
|
6132
|
+
|
|
6105
6133
|
// Sort by last message date descending
|
|
6106
6134
|
data.sort((a, b) => sortMoments(timestampToMoment(a.last_mes), timestampToMoment(b.last_mes)));
|
|
6107
6135
|
console.log(data);
|
|
@@ -7808,15 +7836,18 @@ async function doImpersonate() {
|
|
|
7808
7836
|
}
|
|
7809
7837
|
|
|
7810
7838
|
async function doDeleteChat() {
|
|
7811
|
-
|
|
7812
|
-
await delay(100);
|
|
7839
|
+
await displayPastChats();
|
|
7813
7840
|
let currentChatDeleteButton = $('.select_chat_block[highlight=\'true\']').parent().find('.PastChat_cross');
|
|
7814
|
-
$(currentChatDeleteButton).trigger('click'
|
|
7841
|
+
$(currentChatDeleteButton).trigger('click');
|
|
7815
7842
|
await delay(1);
|
|
7816
|
-
$('#dialogue_popup_ok').trigger('click');
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7843
|
+
$('#dialogue_popup_ok').trigger('click', { fromSlashCommand: true });
|
|
7844
|
+
}
|
|
7845
|
+
|
|
7846
|
+
/**
|
|
7847
|
+
* /getchatname` slash command
|
|
7848
|
+
*/
|
|
7849
|
+
async function doGetChatName() {
|
|
7850
|
+
return getCurrentChatDetails().sessionName;
|
|
7820
7851
|
}
|
|
7821
7852
|
|
|
7822
7853
|
const isPwaMode = window.navigator.standalone;
|
|
@@ -7970,6 +8001,7 @@ jQuery(async function () {
|
|
|
7970
8001
|
registerSlashCommand('api', connectAPISlash, [], `<span class="monospace">(${Object.keys(CONNECT_API_MAP).join(', ')})</span> – connect to an API`, true, true);
|
|
7971
8002
|
registerSlashCommand('impersonate', doImpersonate, ['imp'], '– calls an impersonation response', true, true);
|
|
7972
8003
|
registerSlashCommand('delchat', doDeleteChat, [], '– deletes the current chat', true, true);
|
|
8004
|
+
registerSlashCommand('getchatname', doGetChatName, [], '– returns the name of the current chat file into the pipe', false, true);
|
|
7973
8005
|
registerSlashCommand('closechat', doCloseChat, [], '– closes the current chat', true, true);
|
|
7974
8006
|
registerSlashCommand('panels', doTogglePanels, ['togglepanels'], '– toggle UI panels on/off', true, true);
|
|
7975
8007
|
registerSlashCommand('forcesave', doForceSave, [], '– forces a save of the current chat and settings', true, true);
|
|
@@ -8199,7 +8231,8 @@ jQuery(async function () {
|
|
|
8199
8231
|
$('#character_popup').css('display', 'none');
|
|
8200
8232
|
});
|
|
8201
8233
|
|
|
8202
|
-
$('#dialogue_popup_ok').click(async function (e) {
|
|
8234
|
+
$('#dialogue_popup_ok').click(async function (e, customData) {
|
|
8235
|
+
const fromSlashCommand = customData?.fromSlashCommand || false;
|
|
8203
8236
|
dialogueCloseStop = false;
|
|
8204
8237
|
$('#shadow_popup').transition({
|
|
8205
8238
|
opacity: 0,
|
|
@@ -8229,14 +8262,16 @@ jQuery(async function () {
|
|
|
8229
8262
|
await delChat(chat_file_for_del);
|
|
8230
8263
|
}
|
|
8231
8264
|
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
setTimeout(function () {
|
|
8235
|
-
$('#option_select_chat').click();
|
|
8236
|
-
$('#options').hide();
|
|
8265
|
+
if (fromSlashCommand) { // When called from `/delchat` command, don't re-open the history view.
|
|
8266
|
+
$('#options').hide(); // hide option popup menu
|
|
8237
8267
|
hideLoader();
|
|
8238
|
-
}
|
|
8239
|
-
|
|
8268
|
+
} else { // Open the history view again after 2 seconds (delay to avoid edge cases for deleting last chat).
|
|
8269
|
+
setTimeout(function () {
|
|
8270
|
+
$('#option_select_chat').click();
|
|
8271
|
+
$('#options').hide(); // hide option popup menu
|
|
8272
|
+
hideLoader();
|
|
8273
|
+
}, 2000);
|
|
8274
|
+
}
|
|
8240
8275
|
}
|
|
8241
8276
|
if (popup_type == 'del_ch') {
|
|
8242
8277
|
const deleteChats = !!$('#del_char_checkbox').prop('checked');
|
|
@@ -8532,6 +8567,11 @@ jQuery(async function () {
|
|
|
8532
8567
|
await writeSecret(SECRET_KEYS.TOGETHERAI, togetherKey);
|
|
8533
8568
|
}
|
|
8534
8569
|
|
|
8570
|
+
const oobaKey = String($('#api_key_ooba').val()).trim();
|
|
8571
|
+
if (oobaKey.length) {
|
|
8572
|
+
await writeSecret(SECRET_KEYS.OOBA, oobaKey);
|
|
8573
|
+
}
|
|
8574
|
+
|
|
8535
8575
|
validateTextGenUrl();
|
|
8536
8576
|
startStatusLoading();
|
|
8537
8577
|
main_api = 'textgenerationwebui';
|
|
@@ -1132,7 +1132,7 @@ export function initRossMods() {
|
|
|
1132
1132
|
.not('#right-nav-panel')
|
|
1133
1133
|
.not('#floatingPrompt')
|
|
1134
1134
|
.not('#cfgConfig')
|
|
1135
|
-
.not(
|
|
1135
|
+
.not('#logprobsViewer')
|
|
1136
1136
|
.is(':visible')) {
|
|
1137
1137
|
let visibleDrawerContent = $('.drawer-content:visible')
|
|
1138
1138
|
.not('#WorldInfo')
|
|
@@ -1140,7 +1140,7 @@ export function initRossMods() {
|
|
|
1140
1140
|
.not('#right-nav-panel')
|
|
1141
1141
|
.not('#floatingPrompt')
|
|
1142
1142
|
.not('#cfgConfig')
|
|
1143
|
-
.not(
|
|
1143
|
+
.not('#logprobsViewer');
|
|
1144
1144
|
$(visibleDrawerContent).parent().find('.drawer-icon').trigger('click');
|
|
1145
1145
|
return;
|
|
1146
1146
|
}
|
|
@@ -58,6 +58,17 @@ function isTalkingHeadEnabled() {
|
|
|
58
58
|
return extension_settings.expressions.talkinghead && !extension_settings.expressions.local;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Toggles Talkinghead mode on/off.
|
|
63
|
+
*
|
|
64
|
+
* Implements the `/th` slash command, which is meant to be bound to a Quick Reply button
|
|
65
|
+
* as a quick way to switch Talkinghead on or off (e.g. to conserve GPU resources when AFK
|
|
66
|
+
* for a long time).
|
|
67
|
+
*/
|
|
68
|
+
function toggleTalkingHeadCommand(_) {
|
|
69
|
+
setTalkingHeadState(!extension_settings.expressions.talkinghead);
|
|
70
|
+
}
|
|
71
|
+
|
|
61
72
|
function isVisualNovelMode() {
|
|
62
73
|
return Boolean(!isMobile() && power_user.waifuMode && getContext().groupId);
|
|
63
74
|
}
|
|
@@ -389,13 +400,14 @@ function onExpressionsShowDefaultInput() {
|
|
|
389
400
|
}
|
|
390
401
|
|
|
391
402
|
/**
|
|
392
|
-
* Stops animating
|
|
403
|
+
* Stops animating Talkinghead.
|
|
393
404
|
*/
|
|
394
405
|
async function unloadTalkingHead() {
|
|
395
406
|
if (!modules.includes('talkinghead')) {
|
|
396
407
|
console.debug('talkinghead module is disabled');
|
|
397
408
|
return;
|
|
398
409
|
}
|
|
410
|
+
console.debug('expressions: Stopping Talkinghead');
|
|
399
411
|
|
|
400
412
|
try {
|
|
401
413
|
const url = new URL(getApiUrl());
|
|
@@ -418,6 +430,7 @@ async function loadTalkingHead() {
|
|
|
418
430
|
console.debug('talkinghead module is disabled');
|
|
419
431
|
return;
|
|
420
432
|
}
|
|
433
|
+
console.debug('expressions: Starting Talkinghead');
|
|
421
434
|
|
|
422
435
|
const spriteFolderName = getSpriteFolderName();
|
|
423
436
|
|
|
@@ -528,8 +541,7 @@ function handleImageChange() {
|
|
|
528
541
|
return;
|
|
529
542
|
}
|
|
530
543
|
|
|
531
|
-
if (isTalkingHeadEnabled()) {
|
|
532
|
-
// Method get IP of endpoint
|
|
544
|
+
if (isTalkingHeadEnabled() && modules.includes('talkinghead')) {
|
|
533
545
|
const talkingheadResultFeedSrc = `${getApiUrl()}/api/talkinghead/result_feed`;
|
|
534
546
|
$('#expression-holder').css({ display: '' });
|
|
535
547
|
if (imgElement.src !== talkingheadResultFeedSrc) {
|
|
@@ -545,20 +557,26 @@ function handleImageChange() {
|
|
|
545
557
|
}
|
|
546
558
|
})
|
|
547
559
|
.catch(error => {
|
|
548
|
-
console.error(error);
|
|
560
|
+
console.error(error);
|
|
549
561
|
});
|
|
550
562
|
}
|
|
551
563
|
}
|
|
552
564
|
} else {
|
|
553
|
-
imgElement.src = '';
|
|
554
|
-
|
|
565
|
+
imgElement.src = ''; // remove in case char doesn't have expressions
|
|
566
|
+
|
|
567
|
+
// When switching Talkinghead off, force-set the character to the last known expression, if any.
|
|
568
|
+
// This preserves the same expression Talkinghead had at the moment it was switched off.
|
|
569
|
+
const charName = getContext().name2;
|
|
570
|
+
const last = lastExpression[charName];
|
|
571
|
+
const targetExpression = last ? last : FALLBACK_EXPRESSION;
|
|
572
|
+
setExpression(charName, targetExpression, true);
|
|
555
573
|
}
|
|
556
574
|
}
|
|
557
575
|
|
|
558
576
|
async function moduleWorker() {
|
|
559
577
|
const context = getContext();
|
|
560
578
|
|
|
561
|
-
// Hide and disable
|
|
579
|
+
// Hide and disable Talkinghead while in local mode
|
|
562
580
|
$('#image_type_block').toggle(!extension_settings.expressions.local);
|
|
563
581
|
|
|
564
582
|
if (extension_settings.expressions.local && extension_settings.expressions.talkinghead) {
|
|
@@ -691,7 +709,7 @@ async function moduleWorker() {
|
|
|
691
709
|
}
|
|
692
710
|
|
|
693
711
|
/**
|
|
694
|
-
* Starts/stops
|
|
712
|
+
* Starts/stops Talkinghead talking animation.
|
|
695
713
|
*
|
|
696
714
|
* Talking starts only when all the following conditions are met:
|
|
697
715
|
* - The LLM is currently streaming its output.
|
|
@@ -700,10 +718,13 @@ async function moduleWorker() {
|
|
|
700
718
|
*
|
|
701
719
|
* In all other cases, talking stops.
|
|
702
720
|
*
|
|
703
|
-
* A
|
|
721
|
+
* A Talkinghead API call is made only when the talking state changes.
|
|
722
|
+
*
|
|
723
|
+
* Note that also the TTS system, if enabled, starts/stops the Talkinghead talking animation.
|
|
724
|
+
* See `talkingAnimation` in `SillyTavern/public/scripts/extensions/tts/index.js`.
|
|
704
725
|
*/
|
|
705
726
|
async function updateTalkingState() {
|
|
706
|
-
// Don't bother if
|
|
727
|
+
// Don't bother if Talkinghead is disabled or not loaded.
|
|
707
728
|
if (!isTalkingHeadEnabled() || !modules.includes('talkinghead')) {
|
|
708
729
|
return;
|
|
709
730
|
}
|
|
@@ -727,7 +748,7 @@ async function updateTalkingState() {
|
|
|
727
748
|
newTalkingState = false;
|
|
728
749
|
}
|
|
729
750
|
try {
|
|
730
|
-
// Call the
|
|
751
|
+
// Call the Talkinghead API only if the talking state changed.
|
|
731
752
|
if (newTalkingState !== lastTalkingState) {
|
|
732
753
|
console.debug(`updateTalkingState: calling ${url.pathname}`);
|
|
733
754
|
await doExtrasFetch(url);
|
|
@@ -787,6 +808,7 @@ function getSpriteFolderName(characterMessage = null, characterName = null) {
|
|
|
787
808
|
}
|
|
788
809
|
|
|
789
810
|
function setTalkingHeadState(newState) {
|
|
811
|
+
console.debug(`expressions: New talkinghead state: ${newState}`);
|
|
790
812
|
extension_settings.expressions.talkinghead = newState; // Store setting
|
|
791
813
|
saveSettingsDebounced();
|
|
792
814
|
|
|
@@ -871,12 +893,12 @@ async function setSpriteSlashCommand(_, spriteId) {
|
|
|
871
893
|
|
|
872
894
|
spriteId = spriteId.trim().toLowerCase();
|
|
873
895
|
|
|
874
|
-
// In
|
|
896
|
+
// In Talkinghead mode, don't check for the existence of the sprite
|
|
875
897
|
// (emotion names are the same as for sprites, but it only needs "talkinghead.png").
|
|
876
898
|
const currentLastMessage = getLastCharacterMessage();
|
|
877
899
|
const spriteFolderName = getSpriteFolderName(currentLastMessage, currentLastMessage.name);
|
|
878
900
|
let label = spriteId;
|
|
879
|
-
if (!isTalkingHeadEnabled()) {
|
|
901
|
+
if (!isTalkingHeadEnabled() || !modules.includes('talkinghead')) {
|
|
880
902
|
await validateImages(spriteFolderName);
|
|
881
903
|
|
|
882
904
|
// Fuzzy search for sprite
|
|
@@ -1051,6 +1073,8 @@ function drawSpritesList(character, labels, sprites) {
|
|
|
1051
1073
|
* @returns {string} Rendered list item template
|
|
1052
1074
|
*/
|
|
1053
1075
|
function getListItem(item, imageSrc, textClass, isCustom) {
|
|
1076
|
+
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
|
1077
|
+
imageSrc = isFirefox ? `${imageSrc}?t=${Date.now()}` : imageSrc;
|
|
1054
1078
|
return renderExtensionTemplate(MODULE_NAME, 'list-item', { item, imageSrc, textClass, isCustom });
|
|
1055
1079
|
}
|
|
1056
1080
|
|
|
@@ -1144,7 +1168,7 @@ async function getExpressionsList() {
|
|
|
1144
1168
|
}
|
|
1145
1169
|
|
|
1146
1170
|
async function setExpression(character, expression, force) {
|
|
1147
|
-
if (!isTalkingHeadEnabled()) {
|
|
1171
|
+
if (!isTalkingHeadEnabled() || !modules.includes('talkinghead')) {
|
|
1148
1172
|
console.debug('entered setExpressions');
|
|
1149
1173
|
await validateImages(character);
|
|
1150
1174
|
const img = $('img.expression');
|
|
@@ -1255,8 +1279,8 @@ async function setExpression(character, expression, force) {
|
|
|
1255
1279
|
document.getElementById('expression-holder').style.display = '';
|
|
1256
1280
|
|
|
1257
1281
|
} else {
|
|
1258
|
-
// Set the
|
|
1259
|
-
// TODO: For now,
|
|
1282
|
+
// Set the Talkinghead emotion to the specified expression
|
|
1283
|
+
// TODO: For now, Talkinghead emote only supported when VN mode is off; see also updateVisualNovelMode.
|
|
1260
1284
|
try {
|
|
1261
1285
|
let result = await isTalkingHeadAvailable();
|
|
1262
1286
|
if (result) {
|
|
@@ -1409,8 +1433,8 @@ async function onClickExpressionUpload(event) {
|
|
|
1409
1433
|
// Reset the input
|
|
1410
1434
|
e.target.form.reset();
|
|
1411
1435
|
|
|
1412
|
-
// In
|
|
1413
|
-
if (isTalkingHeadEnabled() &&
|
|
1436
|
+
// In Talkinghead mode, when a new talkinghead image is uploaded, refresh the live char.
|
|
1437
|
+
if (id === 'talkinghead' && isTalkingHeadEnabled() && modules.includes('talkinghead')) {
|
|
1414
1438
|
await loadTalkingHead();
|
|
1415
1439
|
}
|
|
1416
1440
|
};
|
|
@@ -1520,6 +1544,11 @@ async function onClickExpressionUploadPackButton() {
|
|
|
1520
1544
|
|
|
1521
1545
|
// Reset the input
|
|
1522
1546
|
e.target.form.reset();
|
|
1547
|
+
|
|
1548
|
+
// In Talkinghead mode, refresh the live char.
|
|
1549
|
+
if (isTalkingHeadEnabled() && modules.includes('talkinghead')) {
|
|
1550
|
+
await loadTalkingHead();
|
|
1551
|
+
}
|
|
1523
1552
|
};
|
|
1524
1553
|
|
|
1525
1554
|
$('#expression_upload_pack')
|
|
@@ -1657,6 +1686,34 @@ async function fetchImagesNoCache() {
|
|
|
1657
1686
|
$('#expression_custom_remove').on('click', onClickExpressionRemoveCustom);
|
|
1658
1687
|
}
|
|
1659
1688
|
|
|
1689
|
+
// Pause Talkinghead to save resources when the ST tab is not visible or the window is minimized.
|
|
1690
|
+
// We currently do this via loading/unloading. Could be improved by adding new pause/unpause endpoints to Extras.
|
|
1691
|
+
document.addEventListener('visibilitychange', function (event) {
|
|
1692
|
+
let pageIsVisible;
|
|
1693
|
+
if (document.hidden) {
|
|
1694
|
+
console.debug('expressions: SillyTavern is now hidden');
|
|
1695
|
+
pageIsVisible = false;
|
|
1696
|
+
} else {
|
|
1697
|
+
console.debug('expressions: SillyTavern is now visible');
|
|
1698
|
+
pageIsVisible = true;
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
if (isTalkingHeadEnabled() && modules.includes('talkinghead')) {
|
|
1702
|
+
isTalkingHeadAvailable().then(result => {
|
|
1703
|
+
if (result) {
|
|
1704
|
+
if (pageIsVisible) {
|
|
1705
|
+
loadTalkingHead();
|
|
1706
|
+
} else {
|
|
1707
|
+
unloadTalkingHead();
|
|
1708
|
+
}
|
|
1709
|
+
handleImageChange(); // Change image as needed
|
|
1710
|
+
} else {
|
|
1711
|
+
//console.log("talkinghead does not exist.");
|
|
1712
|
+
}
|
|
1713
|
+
});
|
|
1714
|
+
}
|
|
1715
|
+
});
|
|
1716
|
+
|
|
1660
1717
|
addExpressionImage();
|
|
1661
1718
|
addVisualNovelMode();
|
|
1662
1719
|
addSettings();
|
|
@@ -1664,7 +1721,7 @@ async function fetchImagesNoCache() {
|
|
|
1664
1721
|
const updateFunction = wrapper.update.bind(wrapper);
|
|
1665
1722
|
setInterval(updateFunction, UPDATE_INTERVAL);
|
|
1666
1723
|
moduleWorker();
|
|
1667
|
-
// For setting the
|
|
1724
|
+
// For setting the Talkinghead talking animation on/off quickly enough for realtime use, we need another timer on a shorter schedule.
|
|
1668
1725
|
const wrapperTalkingState = new ModuleWorkerWrapper(updateTalkingState);
|
|
1669
1726
|
const updateTalkingStateFunction = wrapperTalkingState.update.bind(wrapperTalkingState);
|
|
1670
1727
|
setInterval(updateTalkingStateFunction, TALKINGCHECK_UPDATE_INTERVAL);
|
|
@@ -1701,4 +1758,5 @@ async function fetchImagesNoCache() {
|
|
|
1701
1758
|
registerSlashCommand('sprite', setSpriteSlashCommand, ['emote'], '<span class="monospace">(spriteId)</span> – force sets the sprite for the current character', true, true);
|
|
1702
1759
|
registerSlashCommand('spriteoverride', setSpriteSetCommand, ['costume'], '<span class="monospace">(optional folder)</span> – sets an override sprite folder for the current character. If the name starts with a slash or a backslash, selects a sub-folder in the character-named folder. Empty value to reset to default.', true, true);
|
|
1703
1760
|
registerSlashCommand('lastsprite', (_, value) => lastExpression[value.trim()] ?? '', [], '<span class="monospace">(charName)</span> – Returns the last set sprite / expression for the named character.', true, true);
|
|
1761
|
+
registerSlashCommand('th', toggleTalkingHeadCommand, ['talkinghead'], '– Character Expressions: toggles <i>Image Type - talkinghead (extras)</i> on/off.');
|
|
1704
1762
|
})();
|
|
@@ -73,12 +73,12 @@ function getRegexedString(rawString, placement, { characterOverride, isMarkdown,
|
|
|
73
73
|
) {
|
|
74
74
|
// Check if the depth is within the min/max depth
|
|
75
75
|
if (typeof depth === 'number' && depth >= 0) {
|
|
76
|
-
if (!isNaN(script.minDepth) && script.minDepth >= 0 && depth < script.minDepth) {
|
|
76
|
+
if (!isNaN(script.minDepth) && script.minDepth !== null && script.minDepth >= 0 && depth < script.minDepth) {
|
|
77
77
|
console.debug(`getRegexedString: Skipping script ${script.scriptName} because depth ${depth} is less than minDepth ${script.minDepth}`);
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
if (!isNaN(script.maxDepth) && script.maxDepth >= 0 && depth > script.maxDepth) {
|
|
81
|
+
if (!isNaN(script.maxDepth) && script.maxDepth !== null && script.maxDepth >= 0 && depth > script.maxDepth) {
|
|
82
82
|
console.debug(`getRegexedString: Skipping script ${script.scriptName} because depth ${depth} is greater than maxDepth ${script.maxDepth}`);
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
@@ -536,7 +536,7 @@ async function processTtsQueue() {
|
|
|
536
536
|
}
|
|
537
537
|
|
|
538
538
|
if (extension_settings.tts.narrate_quoted_only) {
|
|
539
|
-
const special_quotes = /[
|
|
539
|
+
const special_quotes = /[“”«»]/g; // Extend this regex to include other special quotes
|
|
540
540
|
text = text.replace(special_quotes, '"');
|
|
541
541
|
const matches = text.match(/".*?"/g); // Matches text inside double quotes, non-greedily
|
|
542
542
|
const partJoiner = (ttsProvider?.separator || ' ... ');
|
|
@@ -674,7 +674,7 @@ export function parseNovelAILogprobs(data) {
|
|
|
674
674
|
// them with a logprob of -Infinity (0% probability)
|
|
675
675
|
const notInAfter = befores
|
|
676
676
|
.filter(([id]) => !afters.some(([aid]) => aid === id))
|
|
677
|
-
.map(([id]) => [id, -Infinity])
|
|
677
|
+
.map(([id]) => [id, -Infinity]);
|
|
678
678
|
const merged = afters.concat(notInAfter);
|
|
679
679
|
|
|
680
680
|
// Add the chosen token to `merged` if it's not already there. This can
|
package/public/scripts/openai.js
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
this_chid,
|
|
32
32
|
} from '../script.js';
|
|
33
33
|
import { groups, selected_group } from './group-chats.js';
|
|
34
|
+
import { registerSlashCommand } from './slash-commands.js';
|
|
34
35
|
|
|
35
36
|
import {
|
|
36
37
|
chatCompletionDefaultPrompts,
|
|
@@ -1617,7 +1618,7 @@ async function sendOpenAIRequest(type, messages, signal) {
|
|
|
1617
1618
|
}
|
|
1618
1619
|
|
|
1619
1620
|
// Add logprobs request (currently OpenAI only, max 5 on their side)
|
|
1620
|
-
if (useLogprobs && isOAI) {
|
|
1621
|
+
if (useLogprobs && (isOAI || isCustom)) {
|
|
1621
1622
|
generate_data['logprobs'] = 5;
|
|
1622
1623
|
}
|
|
1623
1624
|
|
|
@@ -1691,24 +1692,17 @@ async function sendOpenAIRequest(type, messages, signal) {
|
|
|
1691
1692
|
throw new Error(`Got response status ${response.status}`);
|
|
1692
1693
|
}
|
|
1693
1694
|
if (stream) {
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
const eventStream = new EventSourceStream();
|
|
1698
|
-
response.body.pipeThrough(eventStream);
|
|
1699
|
-
reader = eventStream.readable.getReader();
|
|
1700
|
-
} else {
|
|
1701
|
-
reader = response.body.getReader();
|
|
1702
|
-
}
|
|
1695
|
+
const eventStream = new EventSourceStream();
|
|
1696
|
+
response.body.pipeThrough(eventStream);
|
|
1697
|
+
const reader = eventStream.readable.getReader();
|
|
1703
1698
|
return async function* streamData() {
|
|
1704
1699
|
let text = '';
|
|
1705
|
-
let utf8Decoder = new TextDecoder();
|
|
1706
1700
|
const swipes = [];
|
|
1707
1701
|
while (true) {
|
|
1708
1702
|
const { done, value } = await reader.read();
|
|
1709
1703
|
if (done) return;
|
|
1710
|
-
const rawData =
|
|
1711
|
-
if (
|
|
1704
|
+
const rawData = value.data;
|
|
1705
|
+
if (rawData === '[DONE]') return;
|
|
1712
1706
|
tryParseStreamingError(response, rawData);
|
|
1713
1707
|
const parsed = JSON.parse(rawData);
|
|
1714
1708
|
|
|
@@ -1749,7 +1743,7 @@ function getStreamingReply(data) {
|
|
|
1749
1743
|
if (oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) {
|
|
1750
1744
|
return data?.completion || '';
|
|
1751
1745
|
} else if (oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE) {
|
|
1752
|
-
return data?.candidates[0]
|
|
1746
|
+
return data?.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
|
1753
1747
|
} else {
|
|
1754
1748
|
return data.choices[0]?.delta?.content || data.choices[0]?.message?.content || data.choices[0]?.text || '';
|
|
1755
1749
|
}
|
|
@@ -1768,6 +1762,7 @@ function parseChatCompletionLogprobs(data) {
|
|
|
1768
1762
|
|
|
1769
1763
|
switch (oai_settings.chat_completion_source) {
|
|
1770
1764
|
case chat_completion_sources.OPENAI:
|
|
1765
|
+
case chat_completion_sources.CUSTOM:
|
|
1771
1766
|
if (!data.choices?.length) {
|
|
1772
1767
|
return null;
|
|
1773
1768
|
}
|
|
@@ -3933,6 +3928,28 @@ $('#delete_proxy').on('click', async function () {
|
|
|
3933
3928
|
}
|
|
3934
3929
|
});
|
|
3935
3930
|
|
|
3931
|
+
function runProxyCallback(_, value) {
|
|
3932
|
+
if (!value) {
|
|
3933
|
+
toastr.warning('Proxy preset name is required');
|
|
3934
|
+
return '';
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3937
|
+
const proxyNames = proxies.map(preset => preset.name);
|
|
3938
|
+
const fuse = new Fuse(proxyNames);
|
|
3939
|
+
const result = fuse.search(value);
|
|
3940
|
+
|
|
3941
|
+
if (result.length === 0) {
|
|
3942
|
+
toastr.warning(`Proxy preset "${value}" not found`);
|
|
3943
|
+
return '';
|
|
3944
|
+
}
|
|
3945
|
+
|
|
3946
|
+
const foundName = result[0].item;
|
|
3947
|
+
$('#openai_proxy_preset').val(foundName).trigger('change');
|
|
3948
|
+
return foundName;
|
|
3949
|
+
}
|
|
3950
|
+
|
|
3951
|
+
registerSlashCommand('proxy', runProxyCallback, [], '<span class="monospace">(name)</span> – sets a proxy preset by name');
|
|
3952
|
+
|
|
3936
3953
|
$(document).ready(async function () {
|
|
3937
3954
|
$('#test_api_button').on('click', testApiConnection);
|
|
3938
3955
|
|
|
@@ -17,6 +17,7 @@ export const SECRET_KEYS = {
|
|
|
17
17
|
MISTRALAI: 'api_key_mistralai',
|
|
18
18
|
TOGETHERAI: 'api_key_togetherai',
|
|
19
19
|
CUSTOM: 'api_key_custom',
|
|
20
|
+
OOBA: 'api_key_ooba',
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
const INPUT_MAP = {
|
|
@@ -35,6 +36,7 @@ const INPUT_MAP = {
|
|
|
35
36
|
[SECRET_KEYS.MISTRALAI]: '#api_key_mistralai',
|
|
36
37
|
[SECRET_KEYS.CUSTOM]: '#api_key_custom',
|
|
37
38
|
[SECRET_KEYS.TOGETHERAI]: '#api_key_togetherai',
|
|
39
|
+
[SECRET_KEYS.OOBA]: '#api_key_ooba',
|
|
38
40
|
};
|
|
39
41
|
|
|
40
42
|
async function clearSecret() {
|
|
@@ -154,7 +154,7 @@ parser.addCommand('sysgen', generateSystemMessage, [], '<span class="monospace">
|
|
|
154
154
|
parser.addCommand('ask', askCharacter, [], '<span class="monospace">(prompt)</span> – asks a specified character card a prompt', true, true);
|
|
155
155
|
parser.addCommand('delname', deleteMessagesByNameCallback, ['cancel'], '<span class="monospace">(name)</span> – deletes all messages attributed to a specified name', true, true);
|
|
156
156
|
parser.addCommand('send', sendUserMessageCallback, [], '<span class="monospace">(text)</span> – adds a user message to the chat log without triggering a generation', true, true);
|
|
157
|
-
parser.addCommand('trigger', triggerGenerationCallback, [], ' – triggers a message generation. If in group, can trigger a message for the specified group member index or name.', true, true);
|
|
157
|
+
parser.addCommand('trigger', triggerGenerationCallback, [], ' <span class="monospace">await=true/false</span> – triggers a message generation. If in group, can trigger a message for the specified group member index or name. If <code>await=true</code> named argument passed, the command will await for the triggered generation before continuing.', true, true);
|
|
158
158
|
parser.addCommand('hide', hideMessageCallback, [], '<span class="monospace">(message index or range)</span> – hides a chat message from the prompt', true, true);
|
|
159
159
|
parser.addCommand('unhide', unhideMessageCallback, [], '<span class="monospace">(message index or range)</span> – unhides a message from the prompt', true, true);
|
|
160
160
|
parser.addCommand('disable', disableGroupMemberCallback, [], '<span class="monospace">(member index or name)</span> – disables a group member from being drafted for replies', true, true);
|
|
@@ -1029,8 +1029,9 @@ async function addGroupMemberCallback(_, arg) {
|
|
|
1029
1029
|
return character.name;
|
|
1030
1030
|
}
|
|
1031
1031
|
|
|
1032
|
-
async function triggerGenerationCallback(
|
|
1033
|
-
|
|
1032
|
+
async function triggerGenerationCallback(args, value) {
|
|
1033
|
+
const shouldAwait = isTrueBoolean(args?.await);
|
|
1034
|
+
const outerPromise = new Promise((outerResolve) => setTimeout(async () => {
|
|
1034
1035
|
try {
|
|
1035
1036
|
await waitUntilCondition(() => !is_send_press && !is_group_generating, 10000, 100);
|
|
1036
1037
|
} catch {
|
|
@@ -1044,16 +1045,21 @@ async function triggerGenerationCallback(_, arg) {
|
|
|
1044
1045
|
|
|
1045
1046
|
let chid = undefined;
|
|
1046
1047
|
|
|
1047
|
-
if (selected_group &&
|
|
1048
|
-
chid = findGroupMemberId(
|
|
1048
|
+
if (selected_group && value) {
|
|
1049
|
+
chid = findGroupMemberId(value);
|
|
1049
1050
|
|
|
1050
1051
|
if (chid === undefined) {
|
|
1051
|
-
console.warn(`WARN: No group member found for argument ${
|
|
1052
|
+
console.warn(`WARN: No group member found for argument ${value}`);
|
|
1052
1053
|
}
|
|
1053
1054
|
}
|
|
1054
1055
|
|
|
1055
|
-
setTimeout(() => Generate('normal', { force_chid: chid }), 100);
|
|
1056
|
-
}, 1);
|
|
1056
|
+
outerResolve(new Promise(innerResolve => setTimeout(() => innerResolve(Generate('normal', { force_chid: chid })), 100)));
|
|
1057
|
+
}, 1));
|
|
1058
|
+
|
|
1059
|
+
if (shouldAwait) {
|
|
1060
|
+
const innerPromise = await outerPromise;
|
|
1061
|
+
await innerPromise;
|
|
1062
|
+
}
|
|
1057
1063
|
|
|
1058
1064
|
return '';
|
|
1059
1065
|
}
|
|
@@ -716,6 +716,7 @@ function parseTextgenLogprobs(token, logprobs) {
|
|
|
716
716
|
}
|
|
717
717
|
|
|
718
718
|
switch (settings.type) {
|
|
719
|
+
case TABBY:
|
|
719
720
|
case APHRODITE:
|
|
720
721
|
case OOBA: {
|
|
721
722
|
/** @type {Record<string, number>[]} */
|
|
@@ -807,6 +808,8 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate,
|
|
|
807
808
|
'temperature': settings.dynatemp ? (settings.min_temp + settings.max_temp) / 2 : settings.temp,
|
|
808
809
|
'top_p': settings.top_p,
|
|
809
810
|
'typical_p': settings.typical_p,
|
|
811
|
+
'typical': settings.typical_p,
|
|
812
|
+
'sampler_seed': settings.seed,
|
|
810
813
|
'min_p': settings.min_p,
|
|
811
814
|
'repetition_penalty': settings.rep_pen,
|
|
812
815
|
'frequency_penalty': settings.freq_pen,
|
|
@@ -819,8 +822,8 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate,
|
|
|
819
822
|
'early_stopping': settings.early_stopping,
|
|
820
823
|
'add_bos_token': settings.add_bos_token,
|
|
821
824
|
'dynamic_temperature': settings.dynatemp,
|
|
822
|
-
'dynatemp_low': settings.dynatemp ? settings.min_temp :
|
|
823
|
-
'dynatemp_high': settings.dynatemp ? settings.max_temp :
|
|
825
|
+
'dynatemp_low': settings.dynatemp ? settings.min_temp : 1,
|
|
826
|
+
'dynatemp_high': settings.dynatemp ? settings.max_temp : 1,
|
|
824
827
|
'dynatemp_range': settings.dynatemp ? (settings.max_temp - settings.min_temp) / 2 : 0,
|
|
825
828
|
'dynatemp_exponent': settings.dynatemp ? settings.dynatemp_exponent : 1,
|
|
826
829
|
'smoothing_factor': settings.smoothing_factor,
|
|
File without changes
|
|
@@ -37,6 +37,14 @@ function getTabbyHeaders() {
|
|
|
37
37
|
}) : {};
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
function getOobaHeaders() {
|
|
41
|
+
const apiKey = readSecret(SECRET_KEYS.OOBA);
|
|
42
|
+
|
|
43
|
+
return apiKey ? ({
|
|
44
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
45
|
+
}) : {};
|
|
46
|
+
}
|
|
47
|
+
|
|
40
48
|
function getOverrideHeaders(urlHost) {
|
|
41
49
|
const requestOverrides = getConfigValue('requestOverrides', []);
|
|
42
50
|
const overrideHeaders = requestOverrides?.find((e) => e.hosts?.includes(urlHost))?.headers;
|
|
@@ -69,6 +77,9 @@ function setAdditionalHeaders(request, args, server) {
|
|
|
69
77
|
case TEXTGEN_TYPES.TOGETHERAI:
|
|
70
78
|
headers = getTogetherAIHeaders();
|
|
71
79
|
break;
|
|
80
|
+
case TEXTGEN_TYPES.OOBA:
|
|
81
|
+
headers = getOobaHeaders();
|
|
82
|
+
break;
|
|
72
83
|
default:
|
|
73
84
|
headers = server ? getOverrideHeaders((new URL(server))?.host) : {};
|
|
74
85
|
break;
|
package/src/constants.js
CHANGED
|
@@ -267,7 +267,7 @@ async function sendMakerSuiteRequest(request, response) {
|
|
|
267
267
|
? (stream ? 'streamGenerateContent' : 'generateContent')
|
|
268
268
|
: (isText ? 'generateText' : 'generateMessage');
|
|
269
269
|
|
|
270
|
-
const generateResponse = await fetch(`https://generativelanguage.googleapis.com/${apiVersion}/models/${model}:${responseType}?key=${apiKey}`, {
|
|
270
|
+
const generateResponse = await fetch(`https://generativelanguage.googleapis.com/${apiVersion}/models/${model}:${responseType}?key=${apiKey}${stream ? '&alt=sse' : ''}`, {
|
|
271
271
|
body: JSON.stringify(body),
|
|
272
272
|
method: 'POST',
|
|
273
273
|
headers: {
|
|
@@ -279,36 +279,8 @@ async function sendMakerSuiteRequest(request, response) {
|
|
|
279
279
|
// have to do this because of their busted ass streaming endpoint
|
|
280
280
|
if (stream) {
|
|
281
281
|
try {
|
|
282
|
-
|
|
283
|
-
generateResponse
|
|
284
|
-
const chunk = data.toString();
|
|
285
|
-
if (chunk.startsWith(',') || chunk.endsWith(',') || chunk.startsWith('[') || chunk.endsWith(']')) {
|
|
286
|
-
partialData = chunk.slice(1);
|
|
287
|
-
} else {
|
|
288
|
-
partialData += chunk;
|
|
289
|
-
}
|
|
290
|
-
while (true) {
|
|
291
|
-
let json;
|
|
292
|
-
try {
|
|
293
|
-
json = JSON.parse(partialData);
|
|
294
|
-
} catch (e) {
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
response.write(JSON.stringify(json));
|
|
298
|
-
partialData = '';
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
request.socket.on('close', function () {
|
|
303
|
-
if (generateResponse.body instanceof Readable) generateResponse.body.destroy();
|
|
304
|
-
response.end();
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
generateResponse.body.on('end', () => {
|
|
308
|
-
console.log('Streaming request finished');
|
|
309
|
-
response.end();
|
|
310
|
-
});
|
|
311
|
-
|
|
282
|
+
// Pipe remote SSE stream to Express response
|
|
283
|
+
forwardFetchResponse(generateResponse, response);
|
|
312
284
|
} catch (error) {
|
|
313
285
|
console.log('Error forwarding streaming response:', error);
|
|
314
286
|
if (!response.headersSent) {
|
|
@@ -719,7 +691,7 @@ router.post('/generate', jsonParser, function (request, response) {
|
|
|
719
691
|
// Adjust logprobs params for Chat Completions API, which expects { top_logprobs: number; logprobs: boolean; }
|
|
720
692
|
if (!isTextCompletion && bodyParams.logprobs > 0) {
|
|
721
693
|
bodyParams.top_logprobs = bodyParams.logprobs;
|
|
722
|
-
bodyParams.logprobs = true
|
|
694
|
+
bodyParams.logprobs = true;
|
|
723
695
|
}
|
|
724
696
|
|
|
725
697
|
if (getConfigValue('openai.randomizeUserId', false)) {
|
|
@@ -751,7 +723,16 @@ router.post('/generate', jsonParser, function (request, response) {
|
|
|
751
723
|
apiUrl = request.body.custom_url;
|
|
752
724
|
apiKey = readSecret(SECRET_KEYS.CUSTOM);
|
|
753
725
|
headers = {};
|
|
754
|
-
bodyParams = {
|
|
726
|
+
bodyParams = {
|
|
727
|
+
logprobs: request.body.logprobs,
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
// Adjust logprobs params for Chat Completions API, which expects { top_logprobs: number; logprobs: boolean; }
|
|
731
|
+
if (!isTextCompletion && bodyParams.logprobs > 0) {
|
|
732
|
+
bodyParams.top_logprobs = bodyParams.logprobs;
|
|
733
|
+
bodyParams.logprobs = true;
|
|
734
|
+
}
|
|
735
|
+
|
|
755
736
|
mergeObjectWithYaml(bodyParams, request.body.custom_include_body);
|
|
756
737
|
mergeObjectWithYaml(headers, request.body.custom_include_headers);
|
|
757
738
|
} else {
|
package/src/endpoints/novelai.js
CHANGED
|
@@ -216,7 +216,7 @@ router.post('/generate', jsonParser, async function (req, res) {
|
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
const data = await response.json();
|
|
219
|
-
console.log(
|
|
219
|
+
console.log('NovelAI Output', data?.output);
|
|
220
220
|
return res.send(data);
|
|
221
221
|
}
|
|
222
222
|
} catch (error) {
|
package/src/endpoints/openai.js
CHANGED
package/src/endpoints/secrets.js
CHANGED
package/src/endpoints/vectors.js
CHANGED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
name: Build and Publish Release (Release)
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- release
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
build_and_publish:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: Checkout code
|
|
14
|
-
uses: actions/checkout@v2
|
|
15
|
-
|
|
16
|
-
- name: Set up Node.js
|
|
17
|
-
uses: actions/setup-node@v2
|
|
18
|
-
with:
|
|
19
|
-
node-version: 18
|
|
20
|
-
|
|
21
|
-
- name: Install dependencies
|
|
22
|
-
run: npm ci
|
|
23
|
-
|
|
24
|
-
- name: Build and package with pkg
|
|
25
|
-
run: |
|
|
26
|
-
npm install -g pkg
|
|
27
|
-
npm run pkg
|
|
28
|
-
|
|
29
|
-
- name: Upload binaries to release
|
|
30
|
-
uses: softprops/action-gh-release@v1
|
|
31
|
-
with:
|
|
32
|
-
files: dist/*
|
|
33
|
-
tag_name: ci-release
|
|
34
|
-
name: Continuous Release (Release)
|
|
35
|
-
prerelease: true
|
|
36
|
-
env:
|
|
37
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
name: Build and Publish Release (Staging)
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- staging
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
build_and_publish:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: Checkout code
|
|
14
|
-
uses: actions/checkout@v2
|
|
15
|
-
|
|
16
|
-
- name: Set up Node.js
|
|
17
|
-
uses: actions/setup-node@v2
|
|
18
|
-
with:
|
|
19
|
-
node-version: 18
|
|
20
|
-
|
|
21
|
-
- name: Install dependencies
|
|
22
|
-
run: npm ci
|
|
23
|
-
|
|
24
|
-
- name: Build and package with pkg
|
|
25
|
-
run: |
|
|
26
|
-
npm install -g pkg
|
|
27
|
-
npm run pkg
|
|
28
|
-
|
|
29
|
-
- name: Upload binaries to release
|
|
30
|
-
uses: softprops/action-gh-release@v1
|
|
31
|
-
with:
|
|
32
|
-
files: dist/*
|
|
33
|
-
tag_name: ci-staging
|
|
34
|
-
name: Continuous Release (Staging)
|
|
35
|
-
prerelease: true
|
|
36
|
-
env:
|
|
37
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|