Compare commits

..

2 Commits

Author SHA1 Message Date
1c5bbf63a5 Added missing animations
All checks were successful
Build and publish / Build Container (push) Successful in 1m32s
2026-03-03 20:33:51 -05:00
6c2c3a0d07 Small tts fix
All checks were successful
Build and publish / Build Container (push) Successful in 1m26s
2026-03-03 20:23:59 -05:00
2 changed files with 23 additions and 22 deletions

View File

@@ -101,7 +101,7 @@ export class TTS {
} }
async speak(t) { async speak(t) {
if (!t.trim()) return; if(!t.trim()) return;
await this._voicesLoaded; await this._voicesLoaded;
if(this._currentUtterance && !this._isStreaming) this.stop(); if(this._currentUtterance && !this._isStreaming) this.stop();
return new Promise((res, rej) => { return new Promise((res, rej) => {
@@ -118,7 +118,8 @@ export class TTS {
else rej(e); else rej(e);
}; };
window.speechSynthesis.speak(u); window.speechSynthesis.speak(u);
}); this._emit('onSentenceStart', {sentence: t});
}).finally(() => this._emit('onSentenceEnd', {sentence: t}));
} }
stop() { stop() {
@@ -143,11 +144,7 @@ export class TTS {
if(ss) { if(ss) {
ss.forEach(s => { ss.forEach(s => {
const sentence = s.trim(); const sentence = s.trim();
sentenceQueue = sentenceQueue.then(async () => { sentenceQueue = sentenceQueue.then(async () => this.speak(sentence));
this._emit('onSentenceStart', { sentence });
await this.speak(sentence);
this._emit('onSentenceEnd', { sentence });
});
}); });
} }
buf = buf.replace(rx, ''); buf = buf.replace(rx, '');
@@ -155,11 +152,7 @@ export class TTS {
done: async () => { done: async () => {
if (buf.trim()) { if (buf.trim()) {
const sentence = buf.trim(); const sentence = buf.trim();
sentenceQueue = sentenceQueue.then(async () => { sentenceQueue = sentenceQueue.then(async () => this.speak(sentence));
this._emit('onSentenceStart', { sentence });
await this.speak(sentence);
this._emit('onSentenceEnd', { sentence });
});
buf = ''; buf = '';
} }
await sentenceQueue; await sentenceQueue;

View File

@@ -44,12 +44,20 @@ let orgSettings, orgMemories, memories = [], settings = {
personality: '- Keep your responses the same length or shorter than the previous user message', personality: '- Keep your responses the same length or shorter than the previous user message',
animations: { animations: {
emote: { emote: {
dead: {"x": 52, "y": 6}, "dead": {"x": 50, "y": 17},
grey: {}, "grey": {},
realization: {"x": 64, "y": -5}, "realization": {"x": 64, "y": -5},
sigh: {"x": 55, "y": 20}, "sigh": {"x": 57, "y": 30},
sweat: {"x": 59, "y": 5}, "sweat": {"x": 55, "y": 20},
stress: {"x": 58, "y": 4} "blush": {"x": 43, "y": 25, "r": 15},
"mouth": {"x": 53, "y": 31.75, "r": 20},
"question": [{"x": 10, "y": 10, "r": -40}, {"x": 26, "y": 6, "r": -20}, {"x": 50, "y": 5, "r": 10}, {"x": 70, "y": 10, "r": 40}],
"cry": [{"x": 25.5, "y": 26.75}, {"x": 37, "y": 27.75}],
"drool": {"x": 26, "y": 27.5},
"love": [{"x": 49, "y": 24, "r": 15}, {"x": 38.5, "y": 23, "r": 15}],
"realize": {"x": 65, "y": 12},
"stress": {"x": 55, "y": 19},
"tear": {"x": 23, "y": 25.5}
} }
}, },
theme: { theme: {
@@ -107,10 +115,10 @@ const ai = new Ai({
emote: {type: 'string', description: 'Emote to the user', required: true, enum: ['none', ...Object.keys(settings.animations.emote)]} emote: {type: 'string', description: 'Emote to the user', required: true, enum: ['none', ...Object.keys(settings.animations.emote)]}
}, },
fn: (args, stream) => { fn: (args, stream) => {
if(!['none', ...Object.keys(settings.animations.emote)].includes(args.emote)) const exists = ['none', ...Object.keys(settings.animations.emote)].includes(args.emote);
throw new Error(`Invalid emote, must be one of: ${['none', ...Object.keys(settings.animations.emote)].join(', ')}`) if(!exists) stream({emote: 'none'});
stream({emote: args.emote}); else stream({emote: args.emote});
return 'done!'; return exists ? 'done!' : `Invalid emote: ${args.emote}`;
} }
}, { }, {
name: 'personalize', name: 'personalize',