agentgui 1.0.484 → 1.0.486

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.484",
3
+ "version": "1.0.486",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/static/index.html CHANGED
@@ -1199,13 +1199,21 @@
1199
1199
  overflow-y: auto;
1200
1200
  white-space: pre-wrap;
1201
1201
  word-break: break-word;
1202
+ font-family: inherit;
1203
+ border: 1px solid var(--color-border);
1204
+ resize: none;
1202
1205
  }
1203
1206
 
1204
- .voice-transcript:empty::before {
1205
- content: attr(data-placeholder);
1207
+ .voice-transcript::placeholder {
1206
1208
  color: var(--color-text-secondary);
1207
1209
  }
1208
1210
 
1211
+ .voice-transcript:focus {
1212
+ outline: none;
1213
+ border-color: var(--color-primary);
1214
+ background: var(--color-bg-primary);
1215
+ }
1216
+
1209
1217
  .voice-mic-btn {
1210
1218
  display: flex;
1211
1219
  align-items: center;
@@ -3169,10 +3177,10 @@
3169
3177
  </div>
3170
3178
  <div class="voice-input-section">
3171
3179
  <div class="voice-input-wrapper">
3172
- <select class="agent-selector voice-agent-selector" data-voice-agent-selector title="Select agent"></select>
3173
- <select class="agent-selector voice-cli-selector" data-voice-cli-selector title="Select CLI tool"></select>
3180
+ <select class="agent-selector voice-agent-selector" data-voice-agent-selector title="Select agent"></select>
3181
+ <select class="agent-selector voice-cli-selector" data-voice-cli-selector title="Select CLI tool"></select>
3174
3182
  <select class="agent-selector voice-model-selector" data-voice-model-selector title="Select model"></select>
3175
- <div class="voice-transcript" id="voiceTranscript" data-placeholder="Tap mic and speak..."></div>
3183
+ <textarea class="voice-transcript" id="voiceTranscript" placeholder="Type or tap mic and speak..." spellcheck="true"></textarea>
3176
3184
  <button class="voice-mic-btn" id="voiceMicBtn" title="Toggle recording" aria-label="Voice input">
3177
3185
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3178
3186
  <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
@@ -260,6 +260,15 @@
260
260
  if (sendBtn) {
261
261
  sendBtn.addEventListener('click', sendVoiceMessage);
262
262
  }
263
+ var transcript = document.getElementById('voiceTranscript');
264
+ if (transcript) {
265
+ transcript.addEventListener('keydown', function(e) {
266
+ if (e.ctrlKey && e.key === 'Enter' || e.metaKey && e.key === 'Enter') {
267
+ e.preventDefault();
268
+ sendVoiceMessage();
269
+ }
270
+ });
271
+ }
263
272
  }
264
273
 
265
274
  function resampleBuffer(inputBuffer, fromRate, toRate) {
@@ -310,8 +319,12 @@
310
319
  if (isRecording) return;
311
320
  var el = document.getElementById('voiceTranscript');
312
321
  if (el) {
313
- el.textContent = '';
314
- el.setAttribute('data-final', '');
322
+ if (el.value !== undefined) {
323
+ el.value = '';
324
+ } else {
325
+ el.textContent = '';
326
+ el.setAttribute('data-final', '');
327
+ }
315
328
  }
316
329
  try {
317
330
  mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
@@ -357,7 +370,13 @@
357
370
  }
358
371
  recordedChunks = [];
359
372
  var resampled = resampleBuffer(merged, sourceSampleRate, TARGET_SAMPLE_RATE);
360
- if (el) el.textContent = 'Transcribing...';
373
+ if (el) {
374
+ if (el.value !== undefined) {
375
+ el.value = 'Transcribing...';
376
+ } else {
377
+ el.textContent = 'Transcribing...';
378
+ }
379
+ }
361
380
  try {
362
381
  var wavBuffer = encodeWav(resampled, TARGET_SAMPLE_RATE);
363
382
  var resp = await fetch(BASE + '/api/stt', {
@@ -368,27 +387,53 @@
368
387
  var data = await resp.json();
369
388
  if (data.text) {
370
389
  if (el) {
371
- el.textContent = data.text;
372
- el.setAttribute('data-final', data.text);
390
+ if (el.value !== undefined) {
391
+ el.value = data.text;
392
+ } else {
393
+ el.textContent = data.text;
394
+ el.setAttribute('data-final', data.text);
395
+ }
373
396
  }
374
397
  } else if (data.error) {
375
- if (el) el.textContent = 'Error: ' + data.error;
398
+ if (el) {
399
+ if (el.value !== undefined) {
400
+ el.value = 'Error: ' + data.error;
401
+ } else {
402
+ el.textContent = 'Error: ' + data.error;
403
+ }
404
+ }
376
405
  } else {
377
- if (el) el.textContent = '';
406
+ if (el) {
407
+ if (el.value !== undefined) {
408
+ el.value = '';
409
+ } else {
410
+ el.textContent = '';
411
+ }
412
+ }
378
413
  }
379
414
  } catch (e) {
380
- if (el) el.textContent = 'Transcription failed: ' + e.message;
415
+ if (el) {
416
+ if (el.value !== undefined) {
417
+ el.value = 'Transcription failed: ' + e.message;
418
+ } else {
419
+ el.textContent = 'Transcription failed: ' + e.message;
420
+ }
421
+ }
381
422
  }
382
423
  }
383
424
 
384
425
  function sendVoiceMessage() {
385
426
  var el = document.getElementById('voiceTranscript');
386
427
  if (!el) return;
387
- var text = el.textContent.trim();
428
+ var text = (el.value || el.textContent || '').trim();
388
429
  if (!text || text.startsWith('Transcribing') || text.startsWith('Error')) return;
389
430
  addVoiceBlock(text, true);
390
- el.textContent = '';
391
- el.setAttribute('data-final', '');
431
+ if (el.value !== undefined) {
432
+ el.value = '';
433
+ } else {
434
+ el.textContent = '';
435
+ el.setAttribute('data-final', '');
436
+ }
392
437
  if (typeof agentGUIClient !== 'undefined' && agentGUIClient) {
393
438
  var input = agentGUIClient.ui.messageInput;
394
439
  if (input) {
@@ -463,6 +508,11 @@
463
508
  var streamingSupported = true;
464
509
  var streamingFailedAt = 0;
465
510
 
511
+ function optimizePromptForSpeech(text) {
512
+ var optimizationInstructions = ' [Optimize for speech: Keep it short. Use simple words. Use short sentences. Focus on clarity.]';
513
+ return text + optimizationInstructions;
514
+ }
515
+
466
516
  function playNextChunk() {
467
517
  if (audioChunkQueue.length === 0) {
468
518
  isPlayingChunk = false;
@@ -537,6 +587,7 @@
537
587
  }
538
588
 
539
589
  var remainingText = uncachedText.join(' ');
590
+ var optimizedText = optimizePromptForSpeech(remainingText);
540
591
 
541
592
  function onTtsSuccess() {
542
593
  ttsConsecutiveFailures = 0;
@@ -557,11 +608,11 @@
557
608
  }
558
609
 
559
610
  function tryStreaming() {
560
- if (!streamingSupported) { tryNonStreaming(remainingText); return; }
611
+ if (!streamingSupported) { tryNonStreaming(optimizedText); return; }
561
612
  fetch(BASE + '/api/tts-stream', {
562
613
  method: 'POST',
563
614
  headers: { 'Content-Type': 'application/json' },
564
- body: JSON.stringify({ text: remainingText, voiceId: selectedVoiceId })
615
+ body: JSON.stringify({ text: optimizedText, voiceId: selectedVoiceId })
565
616
  }).then(function(resp) {
566
617
  if (!resp.ok) {
567
618
  streamingSupported = false;
@@ -769,6 +820,13 @@
769
820
  if (data.seq !== undefined) renderedSeqs.add(data.seq);
770
821
  handleVoiceBlock(data.block, true, data.blockRole);
771
822
  }
823
+ if (data.type === 'message_created' && data.message) {
824
+ if (data.conversationId && data.conversationId !== currentConversationId) return;
825
+ var message = data.message;
826
+ if (message.role === 'user' && message.content) {
827
+ handleVoiceBlock({ type: 'text', text: message.content }, true, 'user');
828
+ }
829
+ }
772
830
  if (data.type === 'streaming_start') {
773
831
  if (data.conversationId && data.conversationId !== currentConversationId) return;
774
832
  spokenChunks = new Set();