diff --git a/scripts/restore-chat-js-with-preview.py b/scripts/restore-chat-js-with-preview.py
index 9709d70..af0f26c 100644
--- a/scripts/restore-chat-js-with-preview.py
+++ b/scripts/restore-chat-js-with-preview.py
@@ -352,7 +352,7 @@ CHAT_HTML_AND_JS = r"""
if (!skipSave && role !== 'thinking') {
session.messages = session.messages || [];
session.messages.push({ role: role, text: text });
- if (session.messages.length > 40) session.messages = session.messages.slice(-40);
+ if (session.messages.length > 200) session.messages = session.messages.slice(-200);
saveSession(session);
}
return el;
@@ -388,26 +388,36 @@ CHAT_HTML_AND_JS = r"""
}
if (turnstileVerified && !session._cfSent) { session._cfSent = true; }
try {
- var hist = (session.messages || []).slice(-20).filter(function(m){ return m.role !== 'thinking'; }).map(function(m){
+ var hist = (session.messages || []).slice(-50).filter(function(m){ return m.role !== 'thinking'; }).map(function(m){
return {role: m.role === 'ai' ? 'assistant' : 'user', content: m.text};
});
var activated_nodes = _ra(session._m, msg);
var questionsRemaining = (MAX - msgCount) - 1;
if (questionsRemaining < 0) questionsRemaining = 0;
- var r = await fetch('/api/demo', {
- method: 'POST',
- headers: {'Content-Type': 'application/json'},
- body: JSON.stringify({
- message: msg,
- history: hist,
- cf_token: turnstileVerified && !session._cfSent ? turnstileToken : '',
- uid: session.uid || '',
- activated_nodes: activated_nodes,
- engram_node_count: (session._m && session._m.nodes) ? session._m.nodes.length : 0,
- questions_remaining: questionsRemaining,
- is_last_question: questionsRemaining === 0
- })
- });
+ // 30s frontend timeout — surfaces a real error if the soul hangs
+ // instead of leaving the thinking bubble spinning forever.
+ var ctrl = new AbortController();
+ var timeoutId = setTimeout(function() { ctrl.abort(); }, 30000);
+ var r;
+ try {
+ r = await fetch('/api/demo', {
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ signal: ctrl.signal,
+ body: JSON.stringify({
+ message: msg,
+ history: hist,
+ cf_token: turnstileVerified && !session._cfSent ? turnstileToken : '',
+ uid: session.uid || '',
+ activated_nodes: activated_nodes,
+ engram_node_count: (session._m && session._m.nodes) ? session._m.nodes.length : 0,
+ questions_remaining: questionsRemaining,
+ is_last_question: questionsRemaining === 0
+ })
+ });
+ } finally {
+ clearTimeout(timeoutId);
+ }
var d = await r.json();
if (thinking) thinking.remove();
_um(session, d.sn, d.se);
@@ -426,7 +436,10 @@ CHAT_HTML_AND_JS = r"""
addMsg('ai', reply || 'Stepped out for a moment. Try again.');
} catch(e) {
if (thinking) thinking.remove();
- addMsg('ai', 'Stepped out for a moment. Try again.');
+ var msg = (e && e.name === 'AbortError')
+ ? 'Took too long to respond — try again.'
+ : 'Stepped out for a moment. Try again.';
+ addMsg('ai', msg);
}
if (msgCount < MAX && btn) btn.disabled = false;
if (input) input.focus();
@@ -451,12 +464,41 @@ OLD_LINE = ''
def main():
src = STYLES_EL.read_text(encoding="utf-8")
- if MARKER in src:
- print("styles.el already contains the share preview modal - skipping")
+ # If the anchor `
+