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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.513",
3
+ "version": "1.0.514",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
@@ -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
+ }