diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 833bf62dc..b52fc7f6e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -34,3 +34,8 @@
- What did you do to achieve this?
- 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.
+
+## 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)
diff --git a/package-lock.json b/package-lock.json
index 300041962..3862aa21f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1391,12 +1391,11 @@
"license": "MIT"
},
"node_modules/axios": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz",
- "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==",
- "license": "MIT",
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
+ "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
"dependencies": {
- "follow-redirects": "^1.15.0",
+ "follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
diff --git a/public/index.html b/public/index.html
index 9629415cb..48cc5c2a9 100644
--- a/public/index.html
+++ b/public/index.html
@@ -383,7 +383,7 @@
Max Response Length (tokens)
-
+
@@ -2573,6 +2573,7 @@
gpt-4o
gpt-4o-2024-08-06
gpt-4o-2024-05-13
+ chatgpt-4o-latest
gpt-4o-mini
diff --git a/public/scripts/extensions/quick-reply/api/QuickReplyApi.js b/public/scripts/extensions/quick-reply/api/QuickReplyApi.js
index fedb6d0e6..59c258620 100644
--- a/public/scripts/extensions/quick-reply/api/QuickReplyApi.js
+++ b/public/scripts/extensions/quick-reply/api/QuickReplyApi.js
@@ -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.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.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
* @returns {QuickReply} the new quick reply
*/
@@ -218,6 +219,7 @@ export class QuickReplyApi {
executeOnAi,
executeOnChatChange,
executeOnGroupMemberDraft,
+ executeOnNewChat,
automationId,
} = {}) {
const set = this.getSetByName(setName);
@@ -236,6 +238,7 @@ export class QuickReplyApi {
qr.executeOnAi = executeOnAi ?? false;
qr.executeOnChatChange = executeOnChatChange ?? false;
qr.executeOnGroupMemberDraft = executeOnGroupMemberDraft ?? false;
+ qr.executeOnNewChat = executeOnNewChat ?? false;
qr.automationId = automationId ?? '';
qr.onUpdate();
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.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.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
* @returns {QuickReply} the altered quick reply
*/
@@ -273,6 +277,7 @@ export class QuickReplyApi {
executeOnAi,
executeOnChatChange,
executeOnGroupMemberDraft,
+ executeOnNewChat,
automationId,
} = {}) {
const qr = this.getQrByLabel(setName, label);
@@ -290,6 +295,7 @@ export class QuickReplyApi {
qr.executeOnAi = executeOnAi ?? qr.executeOnAi;
qr.executeOnChatChange = executeOnChatChange ?? qr.executeOnChatChange;
qr.executeOnGroupMemberDraft = executeOnGroupMemberDraft ?? qr.executeOnGroupMemberDraft;
+ qr.executeOnNewChat = executeOnNewChat ?? qr.executeOnNewChat;
qr.automationId = automationId ?? qr.automationId;
qr.onUpdate();
return qr;
diff --git a/public/scripts/extensions/quick-reply/html/qrEditor.html b/public/scripts/extensions/quick-reply/html/qrEditor.html
index 89766d78a..e81a11ba2 100644
--- a/public/scripts/extensions/quick-reply/html/qrEditor.html
+++ b/public/scripts/extensions/quick-reply/html/qrEditor.html
@@ -108,6 +108,10 @@
Execute on chat change
+
+
+ Execute on new chat
+
Execute on group member draft
diff --git a/public/scripts/extensions/quick-reply/index.js b/public/scripts/extensions/quick-reply/index.js
index 7bd108243..80dde92ed 100644
--- a/public/scripts/extensions/quick-reply/index.js
+++ b/public/scripts/extensions/quick-reply/index.js
@@ -105,6 +105,7 @@ const loadSets = async () => {
qr.executeOnAi = slot.autoExecute_botMessage ?? false;
qr.executeOnChatChange = slot.autoExecute_chatLoad ?? false;
qr.executeOnGroupMemberDraft = slot.autoExecute_groupMemberDraft ?? false;
+ qr.executeOnNewChat = slot.autoExecute_newChat ?? false;
qr.automationId = slot.automationId ?? '';
qr.contextList = (slot.contextMenu ?? []).map(it=>({
set: it.preset,
@@ -260,3 +261,8 @@ const onWIActivation = async (entries) => {
await autoExec.handleWIActivation(entries);
};
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));
diff --git a/public/scripts/extensions/quick-reply/src/AutoExecuteHandler.js b/public/scripts/extensions/quick-reply/src/AutoExecuteHandler.js
index f81f7ca37..1b9174bba 100644
--- a/public/scripts/extensions/quick-reply/src/AutoExecuteHandler.js
+++ b/public/scripts/extensions/quick-reply/src/AutoExecuteHandler.js
@@ -83,6 +83,15 @@ export class AutoExecuteHandler {
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
*/
diff --git a/public/scripts/extensions/quick-reply/src/QuickReply.js b/public/scripts/extensions/quick-reply/src/QuickReply.js
index 6b9ad3c63..502a9b437 100644
--- a/public/scripts/extensions/quick-reply/src/QuickReply.js
+++ b/public/scripts/extensions/quick-reply/src/QuickReply.js
@@ -44,6 +44,7 @@ export class QuickReply {
/**@type {boolean}*/ executeOnAi = false;
/**@type {boolean}*/ executeOnChatChange = false;
/**@type {boolean}*/ executeOnGroupMemberDraft = false;
+ /**@type {boolean}*/ executeOnNewChat = false;
/**@type {string}*/ automationId = '';
/**@type {function}*/ onExecute;
@@ -1061,6 +1062,13 @@ export class QuickReply {
this.updateContext();
});
/**@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');
automationId.value = this.automationId;
automationId.addEventListener('input', () => {
diff --git a/public/scripts/openai.js b/public/scripts/openai.js
index 232787b85..93e045ddb 100644
--- a/public/scripts/openai.js
+++ b/public/scripts/openai.js
@@ -3921,7 +3921,7 @@ function getMaxContextOpenAI(value) {
if (oai_settings.max_context_unlocked) {
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;
}
else if (value.includes('gpt-3.5-turbo-1106')) {
@@ -4768,7 +4768,7 @@ export function isImageInliningSupported() {
switch (oai_settings.chat_completion_source) {
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:
return visionSupportedModels.some(model => oai_settings.google_model.includes(model));
case chat_completion_sources.CLAUDE:
diff --git a/src/endpoints/tokenizers.js b/src/endpoints/tokenizers.js
index 6b150e32b..55ec41ba3 100644
--- a/src/endpoints/tokenizers.js
+++ b/src/endpoints/tokenizers.js
@@ -268,6 +268,10 @@ function getTokenizerModel(requestModel) {
return 'gpt-4o';
}
+ if (requestModel.includes('chatgpt-4o-latest')) {
+ return 'gpt-4o';
+ }
+
if (requestModel.includes('gpt-4-32k')) {
return 'gpt-4-32k';
}
diff --git a/tests/package-lock.json b/tests/package-lock.json
index a0b1125e8..113736d83 100644
--- a/tests/package-lock.json
+++ b/tests/package-lock.json
@@ -1653,10 +1653,9 @@
"license": "MIT"
},
"node_modules/axios": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
- "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
- "license": "MIT",
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
+ "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",