v1.4 - New setting: Endless Surprises

- New setting available: Endless Surprises. A new surprise is silently queued the moment the previous one fires. Can be enabled or disabled.
This commit is contained in:
mattjaybe 2026-03-01 14:29:45 -05:00 committed by GitHub
parent 4be4e84e94
commit 423b7dbb5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 93 additions and 4 deletions

View file

@ -114,7 +114,8 @@
hide_animated_bar: false,
surprise_depth_min: 2, // minimum messages away (used for random range or fixed min)
surprise_depth_max: 6, // maximum messages away (used for random range or fixed max)
surprise_randomize: true // randomize depth between min and max
surprise_randomize: true, // randomize depth between min and max
surprise_endless: false // auto-rearm a new surprise after each one fires
});
@ -1466,6 +1467,9 @@ GUIDELINES:
<i class="fa-solid fa-wand-sparkles"></i> Surprise Me
<span class="pw_setting_tooltip_icon" title="Surprise Me secretly injects an AI-generated suggestion into the chat context a set number of messages before it fires. Pick a style, and Pathweaver will quietly arm a hidden prompt. When the countdown hits, the suggestion appears naturally — like the story took an unexpected turn on its own.">?</span>
</div>
${settings.surprise_endless ? `<div class="pw_surprise_endless_badge">
<i class="fa-solid fa-infinity"></i> Endless Surprises active
</div>` : ''}
${surpriseCount > 0 ? `<div class="pw_surprise_active_info">
<span class="pw_surprise_active_info_label">
<i class="fa-solid fa-circle-check" style="color: var(--pw-success);"></i>
@ -2509,6 +2513,15 @@ GUIDELINES:
<i class="fa-solid fa-wand-sparkles"></i> Surprise Me
<span class="pw_setting_tooltip_icon" title="Surprise Me secretly injects an AI-generated suggestion into the chat context a set number of messages before it fires. Pick a style, and Pathweaver will quietly arm a hidden prompt. When the countdown hits, the suggestion appears naturally — like the story took an unexpected turn on its own.">?</span>
</h4>
<div class="pw_setting_row">
<span class="pw_setting_label"><i class="fa-solid fa-infinity"></i> Endless Surprises
<span class="pw_setting_tooltip_icon" title="Automatically generates and arms a fresh surprise the moment the previous one fires. The story never stops surprising you — until you turn this off.">?</span>
</span>
<div class="pw_toggle ${settings.surprise_endless ? 'active' : ''}" data-setting="surprise_endless"></div>
</div>
<p class="pw_setting_hint" style="margin: -4px 0 10px 0; font-size: 0.78rem; opacity: 0.8;">
A new surprise is silently queued the moment the previous one fires.
</p>
<div class="pw_setting_row">
<span class="pw_setting_label"><i class="fa-solid fa-shuffle"></i> Randomize depth</span>
<div class="pw_toggle ${settings.surprise_randomize ? 'active' : ''}" data-setting="surprise_randomize"></div>
@ -3681,6 +3694,7 @@ GUIDELINES:
fetchAndPopulateOllamaModels('#pw_ollama_model');
}
renderSurpriseQueue();
jQuery('#pw_surprise_endless').prop('checked', settings.surprise_endless);
}
function updateProviderVisibility(source) {
@ -3765,6 +3779,7 @@ GUIDELINES:
jQuery('#pw_stream_suggestions').prop('checked', settings.stream_suggestions);
// Surprise Me
jQuery('#pw_surprise_randomize').prop('checked', settings.surprise_randomize);
jQuery('#pw_surprise_endless').prop('checked', settings.surprise_endless);
jQuery('#pw_surprise_depth_min').val(settings.surprise_depth_min);
jQuery('#pw_surprise_depth_max').val(settings.surprise_depth_max);
if (settings.surprise_randomize) {
@ -3810,6 +3825,7 @@ GUIDELINES:
// Surprise Me
jQuery('.pw_toggle[data-setting="surprise_randomize"]').toggleClass('active', settings.surprise_randomize);
jQuery('.pw_toggle[data-setting="surprise_endless"]').toggleClass('active', settings.surprise_endless);
jQuery('#pw_sm_surprise_depth_min').val(settings.surprise_depth_min);
jQuery('#pw_sm_surprise_depth_max').val(settings.surprise_depth_max);
if (settings.surprise_randomize) {
@ -4051,9 +4067,18 @@ GUIDELINES:
openStyleEditor();
});
// Surprise Me: endless toggle
jQuery('#pw_surprise_endless').on('change', function () {
settings.surprise_endless = this.checked;
saveSettings();
syncSettingsToModal();
if (this.checked) {
showToast('Endless Surprises enabled — surprises will keep arming themselves!');
}
});
// Surprise Me: randomize toggle
jQuery('#pw_surprise_randomize').on('change', function () {
settings.surprise_randomize = this.checked;
jQuery('#pw_surprise_randomize').on('change', function () { settings.surprise_randomize = this.checked;
if (settings.surprise_randomize) {
jQuery('#pw_surprise_range_rows').show();
jQuery('#pw_surprise_fixed_hint').hide();
@ -4159,9 +4184,15 @@ GUIDELINES:
if (s.injected) {
clearSurprisePrompt(s.key);
const firedCategory = s.category; // capture before splice
activeSurprises.splice(i, 1);
changed = true;
log('Surprise', s.key, 'cleared after firing');
// Endless Surprises: silently queue a fresh one with the same style
if (settings.surprise_endless) {
scheduleEndlessSurprise(firedCategory);
}
} else if (newMessages >= s.triggerAfter) {
const ok = injectSurprisePrompt(s.text, 1, s.key);
if (ok) {
@ -4179,6 +4210,39 @@ GUIDELINES:
}
}
/**
* Silently generate and arm a new surprise for the given category.
* Used by Endless Surprises to keep the queue perpetually loaded
* without interrupting the user.
*/
async function scheduleEndlessSurprise(category) {
log('Endless Surprises: scheduling background surprise for category', category);
try {
const endlessAbort = new AbortController();
const text = await generateSurpriseText(category, endlessAbort.signal);
const dMin = Math.max(1, Math.min(12, settings.surprise_depth_min || 2));
const dMax = Math.max(dMin, Math.min(12, settings.surprise_depth_max || 6));
const triggerAfter = settings.surprise_randomize
? Math.floor(Math.random() * (dMax - dMin + 1)) + dMin
: dMin;
const stContext = SillyTavern.getContext();
const baseMessageCount = stContext?.chat?.length ?? 0;
const key = `pathweaver_surprise_${surpriseKeyCounter++}`;
activeSurprises.push({ key, category, triggerAfter, baseMessageCount, text, injected: false });
saveSurpriseQueue();
renderSurpriseQueue();
createActionBar();
log('Endless Surprises: new surprise armed for category', category, '— fires in', triggerAfter, 'messages');
} catch (err) {
if (err.name === 'AbortError') return;
warn('Endless Surprises: background generation failed:', err.message);
}
}
const handleProfileMousedown = () => {
populateConnectionProfiles();
};

View file

@ -6,7 +6,7 @@
"js": "index.js",
"css": "style.css",
"author": "mattjaybe",
"version": "1.3.0",
"version": "1.4",
"homePage": "https://github.com/mattjaybe/SillyTavern-Pathweaver",
"auto_update": true
}

View file

@ -228,6 +228,14 @@
<span class="pw_setting_tooltip_icon" title="Surprise Me secretly injects an AI-generated suggestion into the chat context a set number of messages before it fires. Pick a style, and Pathweaver will quietly arm a hidden prompt. When the countdown hits, the suggestion appears naturally — like the story took an unexpected turn on its own.">?</span>
</h4>
<label class="checkbox_label pw_checkbox_row" for="pw_surprise_endless">
<input id="pw_surprise_endless" type="checkbox" class="checkbox">
<span><i class="fa-solid fa-infinity"></i> Endless Surprises</span>
</label>
<p class="pw_setting_hint" style="margin: 2px 0 10px 0; font-size: 0.78rem; opacity: 0.8;">
When enabled, a new surprise is silently generated and armed as soon as the previous one fires — keeping the story perpetually on the edge.
</p>
<label class="checkbox_label pw_checkbox_row" for="pw_surprise_randomize">
<input id="pw_surprise_randomize" type="checkbox" class="checkbox">
<span><i class="fa-solid fa-shuffle"></i> Randomize depth</span>

View file

@ -3220,6 +3220,23 @@
color: var(--pw-text-secondary);
}
.pw_surprise_endless_badge {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.75rem;
padding: 5px 10px;
border-bottom: 1px solid var(--pw-glass-border);
margin-bottom: 4px;
color: var(--pw-accent, #a78bfa);
opacity: 0.9;
letter-spacing: 0.02em;
}
.pw_surprise_endless_badge i {
font-size: 0.85em;
}
.pw_surprise_clear_btn {
background: none;
border: 1px solid var(--pw-danger, #ef4444);