2023-07-30 22:10:37 +02:00
import { getStringHash , debounce , waitUntilCondition , extractAllWords } from "../../utils.js" ;
2023-07-20 19:32:15 +02:00
import { getContext , getApiUrl , extension _settings , doExtrasFetch , modules } from "../../extensions.js" ;
import { eventSource , event _types , extension _prompt _types , generateQuietPrompt , is _send _press , saveSettingsDebounced , substituteParams } from "../../../script.js" ;
2023-08-03 16:17:58 +02:00
import { is _group _generating , selected _group } from "../../group-chats.js" ;
2023-09-18 00:02:02 +02:00
import { registerSlashCommand } from "../../slash-commands.js" ;
2023-10-09 21:49:35 +02:00
import { loadMovingUIState } from '../../power-user.js' ;
import { dragElement } from "../../RossAscends-mods.js" ;
2023-07-20 19:32:15 +02:00
export { MODULE _NAME } ;
const MODULE _NAME = '1_memory' ;
let lastCharacterId = null ;
let lastGroupId = null ;
let lastChatId = null ;
let lastMessageHash = null ;
let lastMessageId = null ;
let inApiCall = false ;
2023-07-30 22:10:37 +02:00
const formatMemoryValue = function ( value ) {
if ( ! value ) {
return '' ;
}
value = value . trim ( ) ;
if ( extension _settings . memory . template ) {
let result = extension _settings . memory . template . replace ( /{{summary}}/i , value ) ;
return substituteParams ( result ) ;
} else {
return ` Summary: ${ value } ` ;
}
}
2023-07-20 19:32:15 +02:00
const saveChatDebounced = debounce ( ( ) => getContext ( ) . saveChat ( ) , 2000 ) ;
const summary _sources = {
'extras' : 'extras' ,
'main' : 'main' ,
} ;
const defaultPrompt = '[Pause your roleplay. Summarize the most important facts and events that have happened in the chat so far. If a summary already exists in your memory, use that as a base and expand with new facts. Limit the summary to {{words}} words or less. Your response should include nothing but the summary.]' ;
2023-07-30 22:10:37 +02:00
const defaultTemplate = '[Summary: {{summary}}]' ;
2023-07-20 19:32:15 +02:00
const defaultSettings = {
minLongMemory : 16 ,
maxLongMemory : 1024 ,
longMemoryLength : 128 ,
shortMemoryLength : 512 ,
minShortMemory : 128 ,
maxShortMemory : 1024 ,
shortMemoryStep : 16 ,
longMemoryStep : 8 ,
repetitionPenaltyStep : 0.05 ,
repetitionPenalty : 1.2 ,
maxRepetitionPenalty : 2.0 ,
minRepetitionPenalty : 1.0 ,
temperature : 1.0 ,
minTemperature : 0.1 ,
maxTemperature : 2.0 ,
temperatureStep : 0.05 ,
lengthPenalty : 1 ,
minLengthPenalty : - 4 ,
maxLengthPenalty : 4 ,
lengthPenaltyStep : 0.1 ,
memoryFrozen : false ,
2023-10-11 12:44:22 +02:00
SkipWIAN : false ,
2023-07-20 19:32:15 +02:00
source : summary _sources . extras ,
prompt : defaultPrompt ,
2023-07-30 22:10:37 +02:00
template : defaultTemplate ,
2023-09-08 00:26:26 +02:00
position : extension _prompt _types . IN _PROMPT ,
2023-07-30 22:10:37 +02:00
depth : 2 ,
2023-07-20 19:32:15 +02:00
promptWords : 200 ,
promptMinWords : 25 ,
promptMaxWords : 1000 ,
promptWordsStep : 25 ,
promptInterval : 10 ,
2023-08-21 22:56:22 +02:00
promptMinInterval : 0 ,
2023-07-20 19:32:15 +02:00
promptMaxInterval : 100 ,
promptIntervalStep : 1 ,
2023-07-30 22:10:37 +02:00
promptForceWords : 0 ,
promptForceWordsStep : 100 ,
promptMinForceWords : 0 ,
promptMaxForceWords : 10000 ,
2023-07-20 19:32:15 +02:00
} ;
function loadSettings ( ) {
if ( Object . keys ( extension _settings . memory ) . length === 0 ) {
Object . assign ( extension _settings . memory , defaultSettings ) ;
}
2023-07-30 22:10:37 +02:00
for ( const key of Object . keys ( defaultSettings ) ) {
if ( extension _settings . memory [ key ] === undefined ) {
extension _settings . memory [ key ] = defaultSettings [ key ] ;
}
2023-07-20 19:32:15 +02:00
}
$ ( '#summary_source' ) . val ( extension _settings . memory . source ) . trigger ( 'change' ) ;
$ ( '#memory_long_length' ) . val ( extension _settings . memory . longMemoryLength ) . trigger ( 'input' ) ;
$ ( '#memory_short_length' ) . val ( extension _settings . memory . shortMemoryLength ) . trigger ( 'input' ) ;
$ ( '#memory_repetition_penalty' ) . val ( extension _settings . memory . repetitionPenalty ) . trigger ( 'input' ) ;
$ ( '#memory_temperature' ) . val ( extension _settings . memory . temperature ) . trigger ( 'input' ) ;
$ ( '#memory_length_penalty' ) . val ( extension _settings . memory . lengthPenalty ) . trigger ( 'input' ) ;
$ ( '#memory_frozen' ) . prop ( 'checked' , extension _settings . memory . memoryFrozen ) . trigger ( 'input' ) ;
2023-10-11 12:44:22 +02:00
$ ( '#memory_skipWIAN' ) . prop ( 'checked' , extension _settings . memory . SkipWIAN ) . trigger ( 'input' ) ;
2023-07-20 19:32:15 +02:00
$ ( '#memory_prompt' ) . val ( extension _settings . memory . prompt ) . trigger ( 'input' ) ;
$ ( '#memory_prompt_words' ) . val ( extension _settings . memory . promptWords ) . trigger ( 'input' ) ;
$ ( '#memory_prompt_interval' ) . val ( extension _settings . memory . promptInterval ) . trigger ( 'input' ) ;
2023-07-30 22:10:37 +02:00
$ ( '#memory_template' ) . val ( extension _settings . memory . template ) . trigger ( 'input' ) ;
$ ( '#memory_depth' ) . val ( extension _settings . memory . depth ) . trigger ( 'input' ) ;
$ ( ` input[name="memory_position"][value=" ${ extension _settings . memory . position } "] ` ) . prop ( 'checked' , true ) . trigger ( 'input' ) ;
$ ( '#memory_prompt_words_force' ) . val ( extension _settings . memory . promptForceWords ) . trigger ( 'input' ) ;
2023-07-20 19:32:15 +02:00
}
function onSummarySourceChange ( event ) {
const value = event . target . value ;
extension _settings . memory . source = value ;
$ ( '#memory_settings [data-source]' ) . each ( ( _ , element ) => {
const source = $ ( element ) . data ( 'source' ) ;
$ ( element ) . toggle ( source === value ) ;
} ) ;
saveSettingsDebounced ( ) ;
}
function onMemoryShortInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . shortMemoryLength = Number ( value ) ;
$ ( '#memory_short_length_tokens' ) . text ( value ) ;
saveSettingsDebounced ( ) ;
// Don't let long buffer be bigger than short
if ( extension _settings . memory . longMemoryLength > extension _settings . memory . shortMemoryLength ) {
$ ( '#memory_long_length' ) . val ( extension _settings . memory . shortMemoryLength ) . trigger ( 'input' ) ;
}
}
function onMemoryLongInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . longMemoryLength = Number ( value ) ;
$ ( '#memory_long_length_tokens' ) . text ( value ) ;
saveSettingsDebounced ( ) ;
// Don't let long buffer be bigger than short
if ( extension _settings . memory . longMemoryLength > extension _settings . memory . shortMemoryLength ) {
$ ( '#memory_short_length' ) . val ( extension _settings . memory . longMemoryLength ) . trigger ( 'input' ) ;
}
}
function onMemoryRepetitionPenaltyInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . repetitionPenalty = Number ( value ) ;
$ ( '#memory_repetition_penalty_value' ) . text ( extension _settings . memory . repetitionPenalty . toFixed ( 2 ) ) ;
saveSettingsDebounced ( ) ;
}
function onMemoryTemperatureInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . temperature = Number ( value ) ;
$ ( '#memory_temperature_value' ) . text ( extension _settings . memory . temperature . toFixed ( 2 ) ) ;
saveSettingsDebounced ( ) ;
}
function onMemoryLengthPenaltyInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . lengthPenalty = Number ( value ) ;
$ ( '#memory_length_penalty_value' ) . text ( extension _settings . memory . lengthPenalty . toFixed ( 2 ) ) ;
saveSettingsDebounced ( ) ;
}
function onMemoryFrozenInput ( ) {
const value = Boolean ( $ ( this ) . prop ( 'checked' ) ) ;
extension _settings . memory . memoryFrozen = value ;
saveSettingsDebounced ( ) ;
}
2023-10-11 12:44:22 +02:00
function onMemorySkipWIANInput ( ) {
const value = Boolean ( $ ( this ) . prop ( 'checked' ) ) ;
extension _settings . memory . SkipWIAN = value ;
saveSettingsDebounced ( ) ;
}
2023-07-20 19:32:15 +02:00
function onMemoryPromptWordsInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . promptWords = Number ( value ) ;
$ ( '#memory_prompt_words_value' ) . text ( extension _settings . memory . promptWords ) ;
saveSettingsDebounced ( ) ;
}
function onMemoryPromptIntervalInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . promptInterval = Number ( value ) ;
$ ( '#memory_prompt_interval_value' ) . text ( extension _settings . memory . promptInterval ) ;
saveSettingsDebounced ( ) ;
}
function onMemoryPromptInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . prompt = value ;
saveSettingsDebounced ( ) ;
}
2023-07-30 22:10:37 +02:00
function onMemoryTemplateInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . template = value ;
2023-09-21 20:13:24 +02:00
reinsertMemory ( ) ;
2023-07-30 22:10:37 +02:00
saveSettingsDebounced ( ) ;
}
function onMemoryDepthInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . depth = Number ( value ) ;
2023-09-21 20:13:24 +02:00
reinsertMemory ( ) ;
2023-07-30 22:10:37 +02:00
saveSettingsDebounced ( ) ;
}
function onMemoryPositionChange ( e ) {
const value = e . target . value ;
extension _settings . memory . position = value ;
2023-09-21 20:13:24 +02:00
reinsertMemory ( ) ;
2023-07-30 22:10:37 +02:00
saveSettingsDebounced ( ) ;
}
function onMemoryPromptWordsForceInput ( ) {
const value = $ ( this ) . val ( ) ;
extension _settings . memory . promptForceWords = Number ( value ) ;
$ ( '#memory_prompt_words_force_value' ) . text ( extension _settings . memory . promptForceWords ) ;
saveSettingsDebounced ( ) ;
}
2023-07-20 19:32:15 +02:00
function saveLastValues ( ) {
const context = getContext ( ) ;
lastGroupId = context . groupId ;
lastCharacterId = context . characterId ;
lastChatId = context . chatId ;
lastMessageId = context . chat ? . length ? ? null ;
lastMessageHash = getStringHash ( ( context . chat . length && context . chat [ context . chat . length - 1 ] [ 'mes' ] ) ? ? '' ) ;
}
function getLatestMemoryFromChat ( chat ) {
if ( ! Array . isArray ( chat ) || ! chat . length ) {
return '' ;
}
const reversedChat = chat . slice ( ) . reverse ( ) ;
reversedChat . shift ( ) ;
for ( let mes of reversedChat ) {
if ( mes . extra && mes . extra . memory ) {
return mes . extra . memory ;
}
}
return '' ;
}
async function onChatEvent ( ) {
// Module not enabled
if ( extension _settings . memory . source === summary _sources . extras ) {
if ( ! modules . includes ( 'summarize' ) ) {
return ;
}
}
const context = getContext ( ) ;
const chat = context . chat ;
// no characters or group selected
if ( ! context . groupId && context . characterId === undefined ) {
return ;
}
// Generation is in progress, summary prevented
if ( is _send _press ) {
return ;
}
// Chat/character/group changed
if ( ( context . groupId && lastGroupId !== context . groupId ) || ( context . characterId !== lastCharacterId ) || ( context . chatId !== lastChatId ) ) {
const latestMemory = getLatestMemoryFromChat ( chat ) ;
setMemoryContext ( latestMemory , false ) ;
saveLastValues ( ) ;
return ;
}
// Currently summarizing or frozen state - skip
if ( inApiCall || extension _settings . memory . memoryFrozen ) {
return ;
}
// No new messages - do nothing
if ( chat . length === 0 || ( lastMessageId === chat . length && getStringHash ( chat [ chat . length - 1 ] . mes ) === lastMessageHash ) ) {
return ;
}
// Messages has been deleted - rewrite the context with the latest available memory
if ( chat . length < lastMessageId ) {
const latestMemory = getLatestMemoryFromChat ( chat ) ;
setMemoryContext ( latestMemory , false ) ;
}
// Message has been edited / regenerated - delete the saved memory
if ( chat . length
&& chat [ chat . length - 1 ] . extra
&& chat [ chat . length - 1 ] . extra . memory
&& lastMessageId === chat . length
&& getStringHash ( chat [ chat . length - 1 ] . mes ) !== lastMessageHash ) {
delete chat [ chat . length - 1 ] . extra . memory ;
}
try {
await summarizeChat ( context ) ;
}
catch ( error ) {
console . log ( error ) ;
}
finally {
saveLastValues ( ) ;
}
}
async function forceSummarizeChat ( ) {
const context = getContext ( ) ;
2023-10-11 12:44:22 +02:00
const skipWIAN = extension _settings . memory . SkipWIAN
console . log ( ` Skipping WIAN? ${ skipWIAN } ` )
2023-07-20 19:32:15 +02:00
if ( ! context . chatId ) {
toastr . warning ( 'No chat selected' ) ;
return ;
}
toastr . info ( 'Summarizing chat...' , 'Please wait' ) ;
2023-10-11 12:44:22 +02:00
const value = await summarizeChatMain ( context , true , skipWIAN ) ;
2023-07-20 19:32:15 +02:00
if ( ! value ) {
toastr . warning ( 'Failed to summarize chat' ) ;
return ;
}
}
async function summarizeChat ( context ) {
2023-10-11 12:44:22 +02:00
const skipWIAN = extension _settings . memory . SkipWIAN
2023-07-20 19:32:15 +02:00
switch ( extension _settings . memory . source ) {
case summary _sources . extras :
await summarizeChatExtras ( context ) ;
break ;
case summary _sources . main :
2023-10-11 12:44:22 +02:00
await summarizeChatMain ( context , false , skipWIAN ) ;
2023-07-20 19:32:15 +02:00
break ;
default :
break ;
}
}
2023-10-11 12:44:22 +02:00
async function summarizeChatMain ( context , force , skipWIAN ) {
2023-08-21 22:56:22 +02:00
if ( extension _settings . memory . promptInterval === 0 && ! force ) {
console . debug ( 'Prompt interval is set to 0, skipping summarization' ) ;
return ;
}
2023-07-20 19:32:15 +02:00
try {
2023-08-03 16:17:58 +02:00
// Wait for group to finish generating
if ( selected _group ) {
await waitUntilCondition ( ( ) => is _group _generating === false , 1000 , 10 ) ;
}
2023-07-20 19:32:15 +02:00
// Wait for the send button to be released
2023-08-01 14:53:10 +02:00
waitUntilCondition ( ( ) => is _send _press === false , 30000 , 100 ) ;
2023-07-20 19:32:15 +02:00
} catch {
console . debug ( 'Timeout waiting for is_send_press' ) ;
return ;
}
if ( ! context . chat . length ) {
console . debug ( 'No messages in chat to summarize' ) ;
return ;
}
if ( context . chat . length < extension _settings . memory . promptInterval && ! force ) {
console . debug ( ` Not enough messages in chat to summarize (chat: ${ context . chat . length } , interval: ${ extension _settings . memory . promptInterval } ) ` ) ;
return ;
}
let messagesSinceLastSummary = 0 ;
2023-07-30 22:10:37 +02:00
let wordsSinceLastSummary = 0 ;
let conditionSatisfied = false ;
2023-07-20 19:32:15 +02:00
for ( let i = context . chat . length - 1 ; i >= 0 ; i -- ) {
if ( context . chat [ i ] . extra && context . chat [ i ] . extra . memory ) {
break ;
}
messagesSinceLastSummary ++ ;
2023-07-30 22:10:37 +02:00
wordsSinceLastSummary += extractAllWords ( context . chat [ i ] . mes ) . length ;
}
if ( messagesSinceLastSummary >= extension _settings . memory . promptInterval ) {
conditionSatisfied = true ;
}
if ( extension _settings . memory . promptForceWords && wordsSinceLastSummary >= extension _settings . memory . promptForceWords ) {
conditionSatisfied = true ;
2023-07-20 19:32:15 +02:00
}
2023-07-30 22:10:37 +02:00
if ( ! conditionSatisfied && ! force ) {
console . debug ( ` Summary conditions not satisfied (messages: ${ messagesSinceLastSummary } , interval: ${ extension _settings . memory . promptInterval } , words: ${ wordsSinceLastSummary } , force words: ${ extension _settings . memory . promptForceWords } ) ` ) ;
2023-07-20 19:32:15 +02:00
return ;
}
2023-07-30 22:10:37 +02:00
console . log ( 'Summarizing chat, messages since last summary: ' + messagesSinceLastSummary , 'words since last summary: ' + wordsSinceLastSummary ) ;
2023-08-20 20:37:17 +02:00
const prompt = extension _settings . memory . prompt ? . replace ( /{{words}}/gi , extension _settings . memory . promptWords ) ;
2023-07-20 19:32:15 +02:00
if ( ! prompt ) {
console . debug ( 'Summarization prompt is empty. Skipping summarization.' ) ;
return ;
}
2023-10-11 12:44:22 +02:00
console . log ( 'sending summary prompt' )
const summary = await generateQuietPrompt ( prompt , false , skipWIAN ) ;
2023-07-20 19:32:15 +02:00
const newContext = getContext ( ) ;
// something changed during summarization request
if ( newContext . groupId !== context . groupId
|| newContext . chatId !== context . chatId
|| ( ! newContext . groupId && ( newContext . characterId !== context . characterId ) ) ) {
console . log ( 'Context changed, summary discarded' ) ;
return ;
}
setMemoryContext ( summary , true ) ;
return summary ;
}
async function summarizeChatExtras ( context ) {
function getMemoryString ( ) {
return ( longMemory + '\n\n' + memoryBuffer . slice ( ) . reverse ( ) . join ( '\n\n' ) ) . trim ( ) ;
}
const chat = context . chat ;
const longMemory = getLatestMemoryFromChat ( chat ) ;
const reversedChat = chat . slice ( ) . reverse ( ) ;
reversedChat . shift ( ) ;
let memoryBuffer = [ ] ;
for ( let mes of reversedChat ) {
// we reached the point of latest memory
if ( longMemory && mes . extra && mes . extra . memory == longMemory ) {
break ;
}
// don't care about system
if ( mes . is _system ) {
continue ;
}
// determine the sender's name
const name = mes . is _user ? ( context . name1 ? ? 'You' ) : ( mes . force _avatar ? mes . name : context . name2 ) ;
const entry = ` ${ name } : \n ${ mes [ 'mes' ] } ` ;
memoryBuffer . push ( entry ) ;
// check if token limit was reached
if ( context . getTokenCount ( getMemoryString ( ) ) >= extension _settings . memory . shortMemoryLength ) {
break ;
}
}
const resultingString = getMemoryString ( ) ;
if ( context . getTokenCount ( resultingString ) < extension _settings . memory . shortMemoryLength ) {
return ;
}
// perform the summarization API call
try {
inApiCall = true ;
const url = new URL ( getApiUrl ( ) ) ;
url . pathname = '/api/summarize' ;
const apiResult = await doExtrasFetch ( url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
'Bypass-Tunnel-Reminder' : 'bypass' ,
} ,
body : JSON . stringify ( {
text : resultingString ,
params : {
min _length : extension _settings . memory . longMemoryLength * 0 , // testing how it behaves 0 min length
max _length : extension _settings . memory . longMemoryLength ,
repetition _penalty : extension _settings . memory . repetitionPenalty ,
temperature : extension _settings . memory . temperature ,
length _penalty : extension _settings . memory . lengthPenalty ,
}
} )
} ) ;
if ( apiResult . ok ) {
const data = await apiResult . json ( ) ;
const summary = data . summary ;
const newContext = getContext ( ) ;
// something changed during summarization request
if ( newContext . groupId !== context . groupId
|| newContext . chatId !== context . chatId
|| ( ! newContext . groupId && ( newContext . characterId !== context . characterId ) ) ) {
console . log ( 'Context changed, summary discarded' ) ;
return ;
}
setMemoryContext ( summary , true ) ;
}
}
catch ( error ) {
console . log ( error ) ;
}
finally {
inApiCall = false ;
}
}
function onMemoryRestoreClick ( ) {
const context = getContext ( ) ;
const content = $ ( '#memory_contents' ) . val ( ) ;
const reversedChat = context . chat . slice ( ) . reverse ( ) ;
reversedChat . shift ( ) ;
for ( let mes of reversedChat ) {
if ( mes . extra && mes . extra . memory == content ) {
delete mes . extra . memory ;
break ;
}
}
const newContent = getLatestMemoryFromChat ( context . chat ) ;
setMemoryContext ( newContent , false ) ;
}
function onMemoryContentInput ( ) {
const value = $ ( this ) . val ( ) ;
setMemoryContext ( value , true ) ;
}
2023-09-21 20:13:24 +02:00
function reinsertMemory ( ) {
const existingValue = $ ( '#memory_contents' ) . val ( ) ;
setMemoryContext ( existingValue , false ) ;
}
2023-07-20 19:32:15 +02:00
function setMemoryContext ( value , saveToMessage ) {
const context = getContext ( ) ;
2023-07-30 22:10:37 +02:00
context . setExtensionPrompt ( MODULE _NAME , formatMemoryValue ( value ) , extension _settings . memory . position , extension _settings . memory . depth ) ;
2023-07-20 19:32:15 +02:00
$ ( '#memory_contents' ) . val ( value ) ;
2023-07-30 22:10:37 +02:00
console . log ( 'Summary set to: ' + value ) ;
console . debug ( 'Position: ' + extension _settings . memory . position ) ;
console . debug ( 'Depth: ' + extension _settings . memory . depth ) ;
2023-07-20 19:32:15 +02:00
if ( saveToMessage && context . chat . length ) {
const idx = context . chat . length - 2 ;
const mes = context . chat [ idx < 0 ? 0 : idx ] ;
if ( ! mes . extra ) {
mes . extra = { } ;
}
mes . extra . memory = value ;
saveChatDebounced ( ) ;
}
}
2023-10-09 21:49:35 +02:00
function doPopout ( e ) {
const target = e . target ;
//repurposes the zoomed avatar template to server as a floating div
if ( $ ( "#summaryExtensionPopout" ) . length === 0 ) {
console . debug ( 'did not see popout yet, creating' )
const originalHTMLClone = $ ( target ) . parent ( ) . parent ( ) . parent ( ) . find ( '.inline-drawer-content' ) . html ( )
const originalElement = $ ( target ) . parent ( ) . parent ( ) . parent ( ) . find ( '.inline-drawer-content' )
const template = $ ( '#zoomed_avatar_template' ) . html ( ) ;
const controlBarHtml = ` <div class="panelControlBar flex-container">
< div id = "summaryExtensionPopoutheader" class = "fa-solid fa-grip drag-grabber hoverglow" > < / d i v >
2023-10-13 17:29:41 +02:00
< div id = "summaryExtensionPopoutClose" class = "fa-solid fa-circle-xmark hoverglow dragClose" > < / d i v >
2023-10-09 21:49:35 +02:00
< / d i v > `
const newElement = $ ( template ) ;
2023-10-13 17:29:41 +02:00
newElement . attr ( 'id' , 'summaryExtensionPopout' )
. removeClass ( 'zoomed_avatar' )
. addClass ( 'draggable' )
. empty ( )
2023-10-09 21:49:35 +02:00
const prevSummaryBoxContents = $ ( '#memory_contents' ) . val ( ) ; //copy summary box before emptying
originalElement . empty ( ) ;
originalElement . html ( ` <div class="flex-container alignitemscenter justifyCenter wide100p"><small>Currently popped out</small></div> ` )
newElement . append ( controlBarHtml ) . append ( originalHTMLClone )
$ ( 'body' ) . append ( newElement ) ;
$ ( "#summaryExtensionDrawerContents" ) . addClass ( 'scrollableInnerFull' )
setMemoryContext ( prevSummaryBoxContents , false ) ; //paste prev summary box contents into popout box
setupListeners ( ) ;
loadSettings ( ) ;
loadMovingUIState ( ) ;
$ ( "#summaryExtensionPopout" ) . fadeIn ( 250 ) ;
dragElement ( newElement ) ;
//setup listener for close button to restore extensions menu
$ ( '#summaryExtensionPopoutClose' ) . off ( 'click' ) . on ( 'click' , function ( ) {
$ ( "#summaryExtensionDrawerContents" ) . removeClass ( 'scrollableInnerFull' )
const summaryPopoutHTML = $ ( "#summaryExtensionDrawerContents" )
$ ( "#summaryExtensionPopout" ) . fadeOut ( 250 , ( ) => {
originalElement . empty ( ) ;
originalElement . html ( summaryPopoutHTML ) ;
$ ( "#summaryExtensionPopout" ) . remove ( )
} )
loadSettings ( ) ;
} )
} else {
console . debug ( 'saw existing popout, removing' )
$ ( "#summaryExtensionPopout" ) . fadeOut ( 250 , ( ) => { $ ( "#summaryExtensionPopoutClose" ) . trigger ( 'click' ) } ) ;
}
}
function setupListeners ( ) {
//setup shared listeners for popout and regular ext menu
$ ( '#memory_restore' ) . off ( 'click' ) . on ( 'click' , onMemoryRestoreClick ) ;
$ ( '#memory_contents' ) . off ( 'click' ) . on ( 'input' , onMemoryContentInput ) ;
$ ( '#memory_long_length' ) . off ( 'click' ) . on ( 'input' , onMemoryLongInput ) ;
$ ( '#memory_short_length' ) . off ( 'click' ) . on ( 'input' , onMemoryShortInput ) ;
$ ( '#memory_repetition_penalty' ) . off ( 'click' ) . on ( 'input' , onMemoryRepetitionPenaltyInput ) ;
$ ( '#memory_temperature' ) . off ( 'click' ) . on ( 'input' , onMemoryTemperatureInput ) ;
$ ( '#memory_length_penalty' ) . off ( 'click' ) . on ( 'input' , onMemoryLengthPenaltyInput ) ;
$ ( '#memory_frozen' ) . off ( 'click' ) . on ( 'input' , onMemoryFrozenInput ) ;
2023-10-11 12:44:22 +02:00
$ ( '#memory_skipWIAN' ) . off ( 'click' ) . on ( 'input' , onMemorySkipWIANInput ) ;
2023-10-09 21:49:35 +02:00
$ ( '#summary_source' ) . off ( 'click' ) . on ( 'change' , onSummarySourceChange ) ;
$ ( '#memory_prompt_words' ) . off ( 'click' ) . on ( 'input' , onMemoryPromptWordsInput ) ;
$ ( '#memory_prompt_interval' ) . off ( 'click' ) . on ( 'input' , onMemoryPromptIntervalInput ) ;
$ ( '#memory_prompt' ) . off ( 'click' ) . on ( 'input' , onMemoryPromptInput ) ;
$ ( '#memory_force_summarize' ) . off ( 'click' ) . on ( 'click' , forceSummarizeChat ) ;
$ ( '#memory_template' ) . off ( 'click' ) . on ( 'input' , onMemoryTemplateInput ) ;
$ ( '#memory_depth' ) . off ( 'click' ) . on ( 'input' , onMemoryDepthInput ) ;
$ ( 'input[name="memory_position"]' ) . off ( 'click' ) . on ( 'change' , onMemoryPositionChange ) ;
$ ( '#memory_prompt_words_force' ) . off ( 'click' ) . on ( 'input' , onMemoryPromptWordsForceInput ) ;
$ ( "#summarySettingsBlockToggle" ) . off ( 'click' ) . on ( 'click' , function ( ) {
console . log ( 'saw settings button click' )
$ ( "#summarySettingsBlock" ) . slideToggle ( 200 , "swing" ) ; //toggleClass("hidden");
} ) ;
}
2023-07-20 19:32:15 +02:00
jQuery ( function ( ) {
function addExtensionControls ( ) {
const settingsHtml = `
< div id = "memory_settings" >
< div class = "inline-drawer" >
< div class = "inline-drawer-toggle inline-drawer-header" >
2023-10-09 21:49:35 +02:00
< div class = "flex-container alignitemscenter margin0" > < b > Summarize < /b><i id="summaryExtensionPopoutButton" class="fa-solid fa-window-restore menu_button margin0"></i > < / d i v >
2023-07-20 19:32:15 +02:00
< div class = "inline-drawer-icon fa-solid fa-circle-chevron-down down" > < / d i v >
< / d i v >
< div class = "inline-drawer-content" >
2023-10-09 21:49:35 +02:00
< div id = "summaryExtensionDrawerContents" >
< label for = "summary_source" > Summarize with : < / l a b e l >
< select id = "summary_source" >
< option value = "main" > Main API < / o p t i o n >
< option value = "extras" > Extras API < / o p t i o n >
< / s e l e c t > < b r >
2023-11-15 01:16:42 +01:00
2023-10-09 21:49:35 +02:00
< div class = "flex-container justifyspacebetween alignitemscenter" >
< span class = "flex1" > Current summary : < / s p a n >
< div id = "memory_restore" class = "menu_button flex1 margin0" > < span > Restore Previous < / s p a n > < / d i v >
< / d i v >
2023-11-15 01:16:42 +01:00
2023-10-09 21:49:35 +02:00
< textarea id = "memory_contents" class = "text_pole textarea_compact" rows = "6" placeholder = "Summary will be generated here..." > < / t e x t a r e a >
< div class = "memory_contents_controls" >
2023-07-20 19:32:15 +02:00
< div id = "memory_force_summarize" class = "menu_button menu_button_icon" >
2023-10-11 12:44:22 +02:00
< i class = "fa-solid fa-database" > < / i >
< span > Summarize now < / s p a n >
< / d i v >
2023-10-09 21:49:35 +02:00
< label for = "memory_frozen" > < input id = "memory_frozen" type = "checkbox" / > Pause < / l a b e l >
2023-10-11 12:44:22 +02:00
< label for = "memory_skipWIAN" > < input id = "memory_skipWIAN" type = "checkbox" / > No WI / AN < / l a b e l >
2023-10-09 21:49:35 +02:00
< / d i v >
< div class = "memory_contents_controls" >
2023-11-15 01:16:42 +01:00
< div id = "summarySettingsBlockToggle" class = "menu_button menu_button_icon" title = "Edit summarization prompt, insertion position, etc." >
< i class = "fa-solid fa-cog" > < / i >
< span > Summary Settings < / s p a n >
< / d i v >
2023-10-09 21:49:35 +02:00
< / d i v >
2023-11-15 01:16:42 +01:00
< div id = "summarySettingsBlock" style = "display:none;" >
2023-10-09 21:49:35 +02:00
< div class = "memory_template" >
2023-11-15 01:16:42 +01:00
< label for = "memory_template" > Insertion Template < / l a b e l >
2023-10-09 21:49:35 +02:00
< textarea id = "memory_template" class = "text_pole textarea_compact" rows = "2" placeholder = "{{summary}} will resolve to the current summary contents." > < / t e x t a r e a >
2023-07-20 19:32:15 +02:00
< / d i v >
2023-11-15 01:16:42 +01:00
< label for = "memory_position" > Injection Position < / l a b e l >
2023-10-09 21:49:35 +02:00
< div class = "radio_group" >
< label >
< input type = "radio" name = "memory_position" value = "2" / >
Before Main Prompt / Story String
< / l a b e l >
< label >
< input type = "radio" name = "memory_position" value = "0" / >
After Main Prompt / Story String
< / l a b e l >
< label >
< input type = "radio" name = "memory_position" value = "1" / >
In - chat @ Depth < input id = "memory_depth" class = "text_pole widthUnset" type = "number" min = "0" max = "999" / >
< / l a b e l >
< / d i v >
< div data - source = "main" class = "memory_contents_controls" >
< / d i v >
< div data - source = "main" >
< label for = "memory_prompt" class = "title_restorable" >
Summary Prompt
< / l a b e l >
< textarea id = "memory_prompt" class = "text_pole textarea_compact" rows = "6" placeholder = "This prompt will be sent to AI to request the summary generation. {{words}} will resolve to the 'Number of words' parameter." > < / t e x t a r e a >
< label for = "memory_prompt_words" > Summary length ( < span id = "memory_prompt_words_value" > < / s p a n > w o r d s ) < / l a b e l >
< input id = "memory_prompt_words" type = "range" value = "${defaultSettings.promptWords}" min = "${defaultSettings.promptMinWords}" max = "${defaultSettings.promptMaxWords}" step = "${defaultSettings.promptWordsStep}" / >
< label for = "memory_prompt_interval" > Update every < span id = "memory_prompt_interval_value" > < / s p a n > m e s s a g e s < / l a b e l >
< small > 0 = disable < / s m a l l >
< input id = "memory_prompt_interval" type = "range" value = "${defaultSettings.promptInterval}" min = "${defaultSettings.promptMinInterval}" max = "${defaultSettings.promptMaxInterval}" step = "${defaultSettings.promptIntervalStep}" / >
< label for = "memory_prompt_words_force" > Update every < span id = "memory_prompt_words_force_value" > < / s p a n > w o r d s < / l a b e l >
< small > 0 = disable < / s m a l l >
< input id = "memory_prompt_words_force" type = "range" value = "${defaultSettings.promptForceWords}" min = "${defaultSettings.promptMinForceWords}" max = "${defaultSettings.promptMaxForceWords}" step = "${defaultSettings.promptForceWordsStep}" / >
< small > If both sliders are non - zero , then both will trigger summary updates a their respective intervals . < / s m a l l >
< / d i v >
< div data - source = "extras" >
< label for = "memory_short_length" > Chat to Summarize buffer length ( < span id = "memory_short_length_tokens" > < / s p a n > t o k e n s ) < / l a b e l >
< input id = "memory_short_length" type = "range" value = "${defaultSettings.shortMemoryLength}" min = "${defaultSettings.minShortMemory}" max = "${defaultSettings.maxShortMemory}" step = "${defaultSettings.shortMemoryStep}" / >
< label for = "memory_long_length" > Summary output length ( < span id = "memory_long_length_tokens" > < / s p a n > t o k e n s ) < / l a b e l >
< input id = "memory_long_length" type = "range" value = "${defaultSettings.longMemoryLength}" min = "${defaultSettings.minLongMemory}" max = "${defaultSettings.maxLongMemory}" step = "${defaultSettings.longMemoryStep}" / >
< label for = "memory_temperature" > Temperature ( < span id = "memory_temperature_value" > < / s p a n > ) < / l a b e l >
< input id = "memory_temperature" type = "range" value = "${defaultSettings.temperature}" min = "${defaultSettings.minTemperature}" max = "${defaultSettings.maxTemperature}" step = "${defaultSettings.temperatureStep}" / >
< label for = "memory_repetition_penalty" > Repetition penalty ( < span id = "memory_repetition_penalty_value" > < / s p a n > ) < / l a b e l >
< input id = "memory_repetition_penalty" type = "range" value = "${defaultSettings.repetitionPenalty}" min = "${defaultSettings.minRepetitionPenalty}" max = "${defaultSettings.maxRepetitionPenalty}" step = "${defaultSettings.repetitionPenaltyStep}" / >
< label for = "memory_length_penalty" > Length preference < small > [ higher = longer summaries ] < / s m a l l > ( < s p a n i d = " m e m o r y _ l e n g t h _ p e n a l t y _ v a l u e " > < / s p a n > ) < / l a b e l >
< input id = "memory_length_penalty" type = "range" value = "${defaultSettings.lengthPenalty}" min = "${defaultSettings.minLengthPenalty}" max = "${defaultSettings.maxLengthPenalty}" step = "${defaultSettings.lengthPenaltyStep}" / >
< / d i v >
< / d i v >
2023-07-20 19:32:15 +02:00
< / d i v >
< / d i v >
< / d i v >
< / d i v >
` ;
$ ( '#extensions_settings2' ) . append ( settingsHtml ) ;
2023-10-09 21:49:35 +02:00
setupListeners ( ) ;
$ ( "#summaryExtensionPopoutButton" ) . off ( 'click' ) . on ( 'click' , function ( e ) {
doPopout ( e ) ;
e . stopPropagation ( ) ;
} ) ;
2023-07-20 19:32:15 +02:00
}
addExtensionControls ( ) ;
loadSettings ( ) ;
eventSource . on ( event _types . MESSAGE _RECEIVED , onChatEvent ) ;
eventSource . on ( event _types . MESSAGE _DELETED , onChatEvent ) ;
eventSource . on ( event _types . MESSAGE _EDITED , onChatEvent ) ;
eventSource . on ( event _types . MESSAGE _SWIPED , onChatEvent ) ;
eventSource . on ( event _types . CHAT _CHANGED , onChatEvent ) ;
2023-10-07 18:25:36 +02:00
registerSlashCommand ( 'summarize' , forceSummarizeChat , [ ] , '– forces the summarization of the current chat using the Main API' , true , true ) ;
2023-07-20 19:32:15 +02:00
} ) ;