Merge branch 'staging' into image-swipes

This commit is contained in:
Cohee
2024-08-15 00:01:11 +03:00
11 changed files with 53 additions and 12 deletions

View File

@@ -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
View File

@@ -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"
} }

View File

@@ -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>

View File

@@ -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;

View File

@@ -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>

View File

@@ -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));

View File

@@ -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
*/ */

View File

@@ -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', () => {

View File

@@ -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:

View File

@@ -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';
} }

View File

@@ -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",