agentgui 1.0.513 → 1.0.514
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/static/js/voice.js +38 -0
- package/test-fixes.mjs +103 -0
package/package.json
CHANGED
package/static/js/voice.js
CHANGED
|
@@ -453,6 +453,43 @@
|
|
|
453
453
|
});
|
|
454
454
|
}
|
|
455
455
|
|
|
456
|
+
function preGenerateTTS(text) {
|
|
457
|
+
if (!ttsEnabled) return;
|
|
458
|
+
var clean = text.replace(/<[^>]*>/g, '').trim();
|
|
459
|
+
if (!clean) return;
|
|
460
|
+
var parts = [];
|
|
461
|
+
if (typeof agentGUIClient !== 'undefined' && agentGUIClient && typeof agentGUIClient.parseMarkdownCodeBlocks === 'function') {
|
|
462
|
+
parts = agentGUIClient.parseMarkdownCodeBlocks(clean);
|
|
463
|
+
} else {
|
|
464
|
+
parts = [{ type: 'text', content: clean }];
|
|
465
|
+
}
|
|
466
|
+
parts.forEach(function(part) {
|
|
467
|
+
if (part.type === 'code') return;
|
|
468
|
+
var segment = part.content.trim();
|
|
469
|
+
if (!segment) return;
|
|
470
|
+
var cacheKey = selectedVoiceId + ':' + segment;
|
|
471
|
+
if (ttsAudioCache.has(cacheKey)) return;
|
|
472
|
+
var optimizedText = optimizePromptForSpeech(segment);
|
|
473
|
+
fetch(BASE + '/api/tts', {
|
|
474
|
+
method: 'POST',
|
|
475
|
+
headers: { 'Content-Type': 'application/json' },
|
|
476
|
+
body: JSON.stringify({ text: optimizedText, voiceId: selectedVoiceId })
|
|
477
|
+
}).then(function(resp) {
|
|
478
|
+
if (!resp.ok) throw new Error('TTS pre-generation failed: ' + resp.status);
|
|
479
|
+
return resp.arrayBuffer();
|
|
480
|
+
}).then(function(buf) {
|
|
481
|
+
var blob = new Blob([buf], { type: 'audio/wav' });
|
|
482
|
+
if (ttsAudioCache.size >= TTS_CLIENT_CACHE_MAX) {
|
|
483
|
+
var oldest = ttsAudioCache.keys().next().value;
|
|
484
|
+
ttsAudioCache.delete(oldest);
|
|
485
|
+
}
|
|
486
|
+
ttsAudioCache.set(cacheKey, blob);
|
|
487
|
+
}).catch(function(err) {
|
|
488
|
+
console.warn('[Voice] TTS pre-generation failed:', err);
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
|
|
456
493
|
function processQueue() {
|
|
457
494
|
if (isSpeaking || speechQueue.length === 0) return;
|
|
458
495
|
if (ttsDisabledUntilReset) {
|
|
@@ -783,6 +820,7 @@
|
|
|
783
820
|
var div = addVoiceBlock(block.text, isUser);
|
|
784
821
|
if (div && isNew && ttsEnabled && blockRole === 'assistant') {
|
|
785
822
|
div.classList.add('speaking');
|
|
823
|
+
preGenerateTTS(block.text);
|
|
786
824
|
speak(block.text);
|
|
787
825
|
setTimeout(function() { div.classList.remove('speaking'); }, 2000);
|
|
788
826
|
}
|
package/test-fixes.mjs
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Test script for validating the two fixes:
|
|
5
|
+
* 1. Agent selector visibility in chat view
|
|
6
|
+
* 2. TTS streaming pre-generation
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import { execSync } from 'child_process';
|
|
11
|
+
|
|
12
|
+
console.log('=== AgentGUI Fix Validation ===\n');
|
|
13
|
+
|
|
14
|
+
// Test 1: Verify agent selectors are NOT hidden on desktop
|
|
15
|
+
console.log('Test 1: Agent Selector Visibility');
|
|
16
|
+
console.log('-----------------------------------');
|
|
17
|
+
const html = fs.readFileSync('./static/index.html', 'utf-8');
|
|
18
|
+
const beforeMobileMedia = html.substring(0, html.indexOf('@media (max-width: 480px)'));
|
|
19
|
+
const cliHiddenOnDesktop = beforeMobileMedia.includes('.cli-selector { display: none; }');
|
|
20
|
+
const modelHiddenOnDesktop = beforeMobileMedia.includes('.model-selector { display: none; }');
|
|
21
|
+
|
|
22
|
+
if (!cliHiddenOnDesktop && !modelHiddenOnDesktop) {
|
|
23
|
+
console.log('✓ PASS: Agent selectors are NOT hidden by CSS on desktop');
|
|
24
|
+
console.log(' - CLI selector will be visible when populated');
|
|
25
|
+
console.log(' - Model selector will be visible when populated');
|
|
26
|
+
} else {
|
|
27
|
+
console.log('❌ FAIL: Agent selectors are still hidden on desktop');
|
|
28
|
+
if (cliHiddenOnDesktop) console.log(' - .cli-selector has display:none');
|
|
29
|
+
if (modelHiddenOnDesktop) console.log(' - .model-selector has display:none');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Verify selectors are in HTML
|
|
33
|
+
const hasSelectors = html.includes('data-cli-selector') &&
|
|
34
|
+
html.includes('data-agent-selector') &&
|
|
35
|
+
html.includes('data-model-selector');
|
|
36
|
+
if (hasSelectors) {
|
|
37
|
+
console.log('✓ PASS: All selector elements are present in HTML');
|
|
38
|
+
} else {
|
|
39
|
+
console.log('❌ FAIL: Some selector elements are missing');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Test 2: Verify TTS pre-generation is implemented
|
|
43
|
+
console.log('\nTest 2: TTS Streaming Pre-generation');
|
|
44
|
+
console.log('--------------------------------------');
|
|
45
|
+
const voiceJs = fs.readFileSync('./static/js/voice.js', 'utf-8');
|
|
46
|
+
const hasPreGenerateFunction = voiceJs.includes('function preGenerateTTS(text)');
|
|
47
|
+
const callsPreGenerate = voiceJs.includes('preGenerateTTS(block.text)');
|
|
48
|
+
const usesCache = voiceJs.includes('if (ttsAudioCache.has(cacheKey)) return;');
|
|
49
|
+
const fetchesTTS = voiceJs.match(/fetch\(BASE \+ '\/api\/tts'/g)?.length >= 2; // Should be in both preGenerate and processQueue
|
|
50
|
+
|
|
51
|
+
if (hasPreGenerateFunction && callsPreGenerate && usesCache && fetchesTTS) {
|
|
52
|
+
console.log('✓ PASS: TTS pre-generation is fully implemented');
|
|
53
|
+
console.log(' - preGenerateTTS function exists');
|
|
54
|
+
console.log(' - Called when assistant text arrives');
|
|
55
|
+
console.log(' - Uses cache to avoid duplicate generation');
|
|
56
|
+
console.log(' - Audio generation happens in background');
|
|
57
|
+
} else {
|
|
58
|
+
console.log('❌ FAIL: TTS pre-generation incomplete');
|
|
59
|
+
if (!hasPreGenerateFunction) console.log(' - Missing preGenerateTTS function');
|
|
60
|
+
if (!callsPreGenerate) console.log(' - Not called in handleVoiceBlock');
|
|
61
|
+
if (!usesCache) console.log(' - Missing cache check');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Test 3: Check that client.js populates selectors correctly
|
|
65
|
+
console.log('\nTest 3: Selector Population Logic');
|
|
66
|
+
console.log('-----------------------------------');
|
|
67
|
+
const clientJs = fs.readFileSync('./static/js/client.js', 'utf-8');
|
|
68
|
+
const setsDisplay = clientJs.includes("this.ui.cliSelector.style.display = 'inline-block'");
|
|
69
|
+
const populatesOptions = clientJs.includes('.innerHTML = displayAgents');
|
|
70
|
+
|
|
71
|
+
if (setsDisplay && populatesOptions) {
|
|
72
|
+
console.log('✓ PASS: Client.js correctly populates and displays selectors');
|
|
73
|
+
console.log(' - Sets display to inline-block when agents loaded');
|
|
74
|
+
console.log(' - Populates options from agent list');
|
|
75
|
+
} else {
|
|
76
|
+
console.log('❌ FAIL: Selector population logic may be broken');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Summary
|
|
80
|
+
console.log('\n=== SUMMARY ===');
|
|
81
|
+
const allTestsPass = !cliHiddenOnDesktop && !modelHiddenOnDesktop &&
|
|
82
|
+
hasSelectors && hasPreGenerateFunction &&
|
|
83
|
+
callsPreGenerate && usesCache &&
|
|
84
|
+
setsDisplay && populatesOptions;
|
|
85
|
+
|
|
86
|
+
if (allTestsPass) {
|
|
87
|
+
console.log('✓ ALL TESTS PASSED\n');
|
|
88
|
+
console.log('Manual Testing Instructions:');
|
|
89
|
+
console.log('1. Start server: npm run dev');
|
|
90
|
+
console.log('2. Open http://localhost:3000/gm/');
|
|
91
|
+
console.log('3. Check chat input area - you should see:');
|
|
92
|
+
console.log(' - CLI selector dropdown (e.g., "Claude")');
|
|
93
|
+
console.log(' - Model selector dropdown (e.g., "Sonnet 4.5")');
|
|
94
|
+
console.log(' - Microphone button for voice input');
|
|
95
|
+
console.log('4. Open Voice tab and enable "Auto-speak responses"');
|
|
96
|
+
console.log('5. Send a message and observe:');
|
|
97
|
+
console.log(' - Text streams in as agent responds');
|
|
98
|
+
console.log(' - Voice playback starts immediately after completion (no delay)');
|
|
99
|
+
console.log(' - Audio was pre-generated during streaming');
|
|
100
|
+
} else {
|
|
101
|
+
console.log('❌ SOME TESTS FAILED - Review output above\n');
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|