mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into image-swipes
This commit is contained in:
@@ -34,3 +34,8 @@
|
|||||||
- What did you do to achieve this?
|
- What did you do to achieve this?
|
||||||
- How would a reviewer test the change?
|
- How would a reviewer test the change?
|
||||||
6. Mind the license. Your contributions will be licensed under the GNU Affero General Public License. If you don't know what that implies, consult your lawyer.
|
6. Mind the license. Your contributions will be licensed under the GNU Affero General Public License. If you don't know what that implies, consult your lawyer.
|
||||||
|
|
||||||
|
## Further reading
|
||||||
|
|
||||||
|
1. [How to write UI extensions](https://docs.sillytavern.app/for-contributors/writing-extensions/)
|
||||||
|
2. [How to write server plugins](https://docs.sillytavern.app/for-contributors/server-plugins)
|
||||||
|
9
package-lock.json
generated
9
package-lock.json
generated
@@ -1391,12 +1391,11 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.6.1",
|
"version": "1.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
|
||||||
"integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==",
|
"integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.0",
|
"follow-redirects": "^1.15.6",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"proxy-from-env": "^1.1.0"
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
|
@@ -383,7 +383,7 @@
|
|||||||
Max Response Length (tokens)
|
Max Response Length (tokens)
|
||||||
</div>
|
</div>
|
||||||
<div class="wide100p">
|
<div class="wide100p">
|
||||||
<input type="number" id="openai_max_tokens" name="openai_max_tokens" class="text_pole" min="50" max="8000">
|
<input type="number" id="openai_max_tokens" name="openai_max_tokens" class="text_pole" min="1" max="16384">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block" data-source="openai,custom">
|
<div class="range-block" data-source="openai,custom">
|
||||||
@@ -2573,6 +2573,7 @@
|
|||||||
<option value="gpt-4o">gpt-4o</option>
|
<option value="gpt-4o">gpt-4o</option>
|
||||||
<option value="gpt-4o-2024-08-06">gpt-4o-2024-08-06</option>
|
<option value="gpt-4o-2024-08-06">gpt-4o-2024-08-06</option>
|
||||||
<option value="gpt-4o-2024-05-13">gpt-4o-2024-05-13</option>
|
<option value="gpt-4o-2024-05-13">gpt-4o-2024-05-13</option>
|
||||||
|
<option value="chatgpt-4o-latest">chatgpt-4o-latest</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="gpt-4o-mini">
|
<optgroup label="gpt-4o-mini">
|
||||||
<option value="gpt-4o-mini">gpt-4o-mini</option>
|
<option value="gpt-4o-mini">gpt-4o-mini</option>
|
||||||
|
@@ -204,6 +204,7 @@ export class QuickReplyApi {
|
|||||||
* @param {boolean} [props.executeOnAi] whether to execute the quick reply after the AI has sent a message
|
* @param {boolean} [props.executeOnAi] whether to execute the quick reply after the AI has sent a message
|
||||||
* @param {boolean} [props.executeOnChatChange] whether to execute the quick reply when a new chat is loaded
|
* @param {boolean} [props.executeOnChatChange] whether to execute the quick reply when a new chat is loaded
|
||||||
* @param {boolean} [props.executeOnGroupMemberDraft] whether to execute the quick reply when a group member is selected
|
* @param {boolean} [props.executeOnGroupMemberDraft] whether to execute the quick reply when a group member is selected
|
||||||
|
* @param {boolean} [props.executeOnNewChat] whether to execute the quick reply when a new chat is created
|
||||||
* @param {string} [props.automationId] when not empty, the quick reply will be executed when the WI with the given automation ID is activated
|
* @param {string} [props.automationId] when not empty, the quick reply will be executed when the WI with the given automation ID is activated
|
||||||
* @returns {QuickReply} the new quick reply
|
* @returns {QuickReply} the new quick reply
|
||||||
*/
|
*/
|
||||||
@@ -218,6 +219,7 @@ export class QuickReplyApi {
|
|||||||
executeOnAi,
|
executeOnAi,
|
||||||
executeOnChatChange,
|
executeOnChatChange,
|
||||||
executeOnGroupMemberDraft,
|
executeOnGroupMemberDraft,
|
||||||
|
executeOnNewChat,
|
||||||
automationId,
|
automationId,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const set = this.getSetByName(setName);
|
const set = this.getSetByName(setName);
|
||||||
@@ -236,6 +238,7 @@ export class QuickReplyApi {
|
|||||||
qr.executeOnAi = executeOnAi ?? false;
|
qr.executeOnAi = executeOnAi ?? false;
|
||||||
qr.executeOnChatChange = executeOnChatChange ?? false;
|
qr.executeOnChatChange = executeOnChatChange ?? false;
|
||||||
qr.executeOnGroupMemberDraft = executeOnGroupMemberDraft ?? false;
|
qr.executeOnGroupMemberDraft = executeOnGroupMemberDraft ?? false;
|
||||||
|
qr.executeOnNewChat = executeOnNewChat ?? false;
|
||||||
qr.automationId = automationId ?? '';
|
qr.automationId = automationId ?? '';
|
||||||
qr.onUpdate();
|
qr.onUpdate();
|
||||||
return qr;
|
return qr;
|
||||||
@@ -258,6 +261,7 @@ export class QuickReplyApi {
|
|||||||
* @param {boolean} [props.executeOnAi] whether to execute the quick reply after the AI has sent a message
|
* @param {boolean} [props.executeOnAi] whether to execute the quick reply after the AI has sent a message
|
||||||
* @param {boolean} [props.executeOnChatChange] whether to execute the quick reply when a new chat is loaded
|
* @param {boolean} [props.executeOnChatChange] whether to execute the quick reply when a new chat is loaded
|
||||||
* @param {boolean} [props.executeOnGroupMemberDraft] whether to execute the quick reply when a group member is selected
|
* @param {boolean} [props.executeOnGroupMemberDraft] whether to execute the quick reply when a group member is selected
|
||||||
|
* @param {boolean} [props.executeOnNewChat] whether to execute the quick reply when a new chat is created
|
||||||
* @param {string} [props.automationId] when not empty, the quick reply will be executed when the WI with the given automation ID is activated
|
* @param {string} [props.automationId] when not empty, the quick reply will be executed when the WI with the given automation ID is activated
|
||||||
* @returns {QuickReply} the altered quick reply
|
* @returns {QuickReply} the altered quick reply
|
||||||
*/
|
*/
|
||||||
@@ -273,6 +277,7 @@ export class QuickReplyApi {
|
|||||||
executeOnAi,
|
executeOnAi,
|
||||||
executeOnChatChange,
|
executeOnChatChange,
|
||||||
executeOnGroupMemberDraft,
|
executeOnGroupMemberDraft,
|
||||||
|
executeOnNewChat,
|
||||||
automationId,
|
automationId,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const qr = this.getQrByLabel(setName, label);
|
const qr = this.getQrByLabel(setName, label);
|
||||||
@@ -290,6 +295,7 @@ export class QuickReplyApi {
|
|||||||
qr.executeOnAi = executeOnAi ?? qr.executeOnAi;
|
qr.executeOnAi = executeOnAi ?? qr.executeOnAi;
|
||||||
qr.executeOnChatChange = executeOnChatChange ?? qr.executeOnChatChange;
|
qr.executeOnChatChange = executeOnChatChange ?? qr.executeOnChatChange;
|
||||||
qr.executeOnGroupMemberDraft = executeOnGroupMemberDraft ?? qr.executeOnGroupMemberDraft;
|
qr.executeOnGroupMemberDraft = executeOnGroupMemberDraft ?? qr.executeOnGroupMemberDraft;
|
||||||
|
qr.executeOnNewChat = executeOnNewChat ?? qr.executeOnNewChat;
|
||||||
qr.automationId = automationId ?? qr.automationId;
|
qr.automationId = automationId ?? qr.automationId;
|
||||||
qr.onUpdate();
|
qr.onUpdate();
|
||||||
return qr;
|
return qr;
|
||||||
|
@@ -108,6 +108,10 @@
|
|||||||
<input type="checkbox" id="qr--executeOnChatChange" >
|
<input type="checkbox" id="qr--executeOnChatChange" >
|
||||||
<span><i class="fa-solid fa-fw fa-message"></i><span data-i18n="Execute on chat change">Execute on chat change</span></span>
|
<span><i class="fa-solid fa-fw fa-message"></i><span data-i18n="Execute on chat change">Execute on chat change</span></span>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="checkbox_label">
|
||||||
|
<input type="checkbox" id="qr--executeOnNewChat">
|
||||||
|
<span><i class="fa-solid fa-fw fa-comments"></i><span data-i18n="Execute on new chat">Execute on new chat</span></span>
|
||||||
|
</label>
|
||||||
<label class="checkbox_label">
|
<label class="checkbox_label">
|
||||||
<input type="checkbox" id="qr--executeOnGroupMemberDraft">
|
<input type="checkbox" id="qr--executeOnGroupMemberDraft">
|
||||||
<span><i class="fa-solid fa-fw fa-people-group"></i><span data-i18n="Execute on group member draft">Execute on group member draft</span></span>
|
<span><i class="fa-solid fa-fw fa-people-group"></i><span data-i18n="Execute on group member draft">Execute on group member draft</span></span>
|
||||||
|
@@ -105,6 +105,7 @@ const loadSets = async () => {
|
|||||||
qr.executeOnAi = slot.autoExecute_botMessage ?? false;
|
qr.executeOnAi = slot.autoExecute_botMessage ?? false;
|
||||||
qr.executeOnChatChange = slot.autoExecute_chatLoad ?? false;
|
qr.executeOnChatChange = slot.autoExecute_chatLoad ?? false;
|
||||||
qr.executeOnGroupMemberDraft = slot.autoExecute_groupMemberDraft ?? false;
|
qr.executeOnGroupMemberDraft = slot.autoExecute_groupMemberDraft ?? false;
|
||||||
|
qr.executeOnNewChat = slot.autoExecute_newChat ?? false;
|
||||||
qr.automationId = slot.automationId ?? '';
|
qr.automationId = slot.automationId ?? '';
|
||||||
qr.contextList = (slot.contextMenu ?? []).map(it=>({
|
qr.contextList = (slot.contextMenu ?? []).map(it=>({
|
||||||
set: it.preset,
|
set: it.preset,
|
||||||
@@ -260,3 +261,8 @@ const onWIActivation = async (entries) => {
|
|||||||
await autoExec.handleWIActivation(entries);
|
await autoExec.handleWIActivation(entries);
|
||||||
};
|
};
|
||||||
eventSource.on(event_types.WORLD_INFO_ACTIVATED, (...args) => executeIfReadyElseQueue(onWIActivation, args));
|
eventSource.on(event_types.WORLD_INFO_ACTIVATED, (...args) => executeIfReadyElseQueue(onWIActivation, args));
|
||||||
|
|
||||||
|
const onNewChat = async () => {
|
||||||
|
await autoExec.handleNewChat();
|
||||||
|
};
|
||||||
|
eventSource.on(event_types.CHAT_CREATED, (...args) => executeIfReadyElseQueue(onNewChat, args));
|
||||||
|
@@ -83,6 +83,15 @@ export class AutoExecuteHandler {
|
|||||||
await this.performAutoExecute(qrList);
|
await this.performAutoExecute(qrList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleNewChat() {
|
||||||
|
if (!this.checkExecute()) return;
|
||||||
|
const qrList = [
|
||||||
|
...this.settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnNewChat)).flat(),
|
||||||
|
...(this.settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnNewChat))?.flat() ?? []),
|
||||||
|
];
|
||||||
|
await this.performAutoExecute(qrList);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {any[]} entries Set of activated entries
|
* @param {any[]} entries Set of activated entries
|
||||||
*/
|
*/
|
||||||
|
@@ -44,6 +44,7 @@ export class QuickReply {
|
|||||||
/**@type {boolean}*/ executeOnAi = false;
|
/**@type {boolean}*/ executeOnAi = false;
|
||||||
/**@type {boolean}*/ executeOnChatChange = false;
|
/**@type {boolean}*/ executeOnChatChange = false;
|
||||||
/**@type {boolean}*/ executeOnGroupMemberDraft = false;
|
/**@type {boolean}*/ executeOnGroupMemberDraft = false;
|
||||||
|
/**@type {boolean}*/ executeOnNewChat = false;
|
||||||
/**@type {string}*/ automationId = '';
|
/**@type {string}*/ automationId = '';
|
||||||
|
|
||||||
/**@type {function}*/ onExecute;
|
/**@type {function}*/ onExecute;
|
||||||
@@ -1061,6 +1062,13 @@ export class QuickReply {
|
|||||||
this.updateContext();
|
this.updateContext();
|
||||||
});
|
});
|
||||||
/**@type {HTMLInputElement}*/
|
/**@type {HTMLInputElement}*/
|
||||||
|
const executeOnNewChat = dom.querySelector('#qr--executeOnNewChat');
|
||||||
|
executeOnNewChat.checked = this.executeOnNewChat;
|
||||||
|
executeOnNewChat.addEventListener('click', ()=>{
|
||||||
|
this.executeOnNewChat = executeOnNewChat.checked;
|
||||||
|
this.updateContext();
|
||||||
|
});
|
||||||
|
/**@type {HTMLInputElement}*/
|
||||||
const automationId = dom.querySelector('#qr--automationId');
|
const automationId = dom.querySelector('#qr--automationId');
|
||||||
automationId.value = this.automationId;
|
automationId.value = this.automationId;
|
||||||
automationId.addEventListener('input', () => {
|
automationId.addEventListener('input', () => {
|
||||||
|
@@ -3921,7 +3921,7 @@ function getMaxContextOpenAI(value) {
|
|||||||
if (oai_settings.max_context_unlocked) {
|
if (oai_settings.max_context_unlocked) {
|
||||||
return unlocked_max;
|
return unlocked_max;
|
||||||
}
|
}
|
||||||
else if (value.includes('gpt-4-turbo') || value.includes('gpt-4o') || value.includes('gpt-4-1106') || value.includes('gpt-4-0125') || value.includes('gpt-4-vision')) {
|
else if (value.includes('chatgpt-4o-latest') || value.includes('gpt-4-turbo') || value.includes('gpt-4o') || value.includes('gpt-4-1106') || value.includes('gpt-4-0125') || value.includes('gpt-4-vision')) {
|
||||||
return max_128k;
|
return max_128k;
|
||||||
}
|
}
|
||||||
else if (value.includes('gpt-3.5-turbo-1106')) {
|
else if (value.includes('gpt-3.5-turbo-1106')) {
|
||||||
@@ -4768,7 +4768,7 @@ export function isImageInliningSupported() {
|
|||||||
|
|
||||||
switch (oai_settings.chat_completion_source) {
|
switch (oai_settings.chat_completion_source) {
|
||||||
case chat_completion_sources.OPENAI:
|
case chat_completion_sources.OPENAI:
|
||||||
return visionSupportedModels.some(model => oai_settings.openai_model.includes(model) && !oai_settings.openai_model.includes('gpt-4-turbo-preview'));
|
return visionSupportedModels.some(model => oai_settings.openai_model.includes(model) && !oai_settings.openai_model.includes('chatgpt-4o-latest') && !oai_settings.openai_model.includes('gpt-4-turbo-preview'));
|
||||||
case chat_completion_sources.MAKERSUITE:
|
case chat_completion_sources.MAKERSUITE:
|
||||||
return visionSupportedModels.some(model => oai_settings.google_model.includes(model));
|
return visionSupportedModels.some(model => oai_settings.google_model.includes(model));
|
||||||
case chat_completion_sources.CLAUDE:
|
case chat_completion_sources.CLAUDE:
|
||||||
|
@@ -268,6 +268,10 @@ function getTokenizerModel(requestModel) {
|
|||||||
return 'gpt-4o';
|
return 'gpt-4o';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requestModel.includes('chatgpt-4o-latest')) {
|
||||||
|
return 'gpt-4o';
|
||||||
|
}
|
||||||
|
|
||||||
if (requestModel.includes('gpt-4-32k')) {
|
if (requestModel.includes('gpt-4-32k')) {
|
||||||
return 'gpt-4-32k';
|
return 'gpt-4-32k';
|
||||||
}
|
}
|
||||||
|
7
tests/package-lock.json
generated
7
tests/package-lock.json
generated
@@ -1653,10 +1653,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.7.2",
|
"version": "1.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
|
||||||
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
|
"integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
|
Reference in New Issue
Block a user