agentgui 1.0.183 → 1.0.185

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.183",
3
+ "version": "1.0.185",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -536,30 +536,30 @@ const server = http.createServer(async (req, res) => {
536
536
  return;
537
537
  }
538
538
 
539
- if (routePath === '/api/agents' && req.method === 'GET') {
539
+ if (pathOnly === '/api/agents' && req.method === 'GET') {
540
540
  sendJSON(req, res, 200, { agents: discoveredAgents });
541
541
  return;
542
542
  }
543
543
 
544
544
 
545
- if (routePath === '/api/import/claude-code' && req.method === 'GET') {
545
+ if (pathOnly === '/api/import/claude-code' && req.method === 'GET') {
546
546
  const result = queries.importClaudeCodeConversations();
547
547
  sendJSON(req, res, 200, { imported: result });
548
548
  return;
549
549
  }
550
550
 
551
- if (routePath === '/api/discover/claude-code' && req.method === 'GET') {
551
+ if (pathOnly === '/api/discover/claude-code' && req.method === 'GET') {
552
552
  const discovered = queries.discoverClaudeCodeConversations();
553
553
  sendJSON(req, res, 200, { discovered });
554
554
  return;
555
555
  }
556
556
 
557
- if (routePath === '/api/home' && req.method === 'GET') {
557
+ if (pathOnly === '/api/home' && req.method === 'GET') {
558
558
  sendJSON(req, res, 200, { home: os.homedir(), cwd: STARTUP_CWD });
559
559
  return;
560
560
  }
561
561
 
562
- if (routePath === '/api/stt' && req.method === 'POST') {
562
+ if (pathOnly === '/api/stt' && req.method === 'POST') {
563
563
  try {
564
564
  const chunks = [];
565
565
  for await (const chunk of req) chunks.push(chunk);
@@ -578,7 +578,7 @@ const server = http.createServer(async (req, res) => {
578
578
  return;
579
579
  }
580
580
 
581
- if (routePath === '/api/voices' && req.method === 'GET') {
581
+ if (pathOnly === '/api/voices' && req.method === 'GET') {
582
582
  try {
583
583
  const { getVoices } = await getSpeech();
584
584
  sendJSON(req, res, 200, { ok: true, voices: getVoices() });
@@ -588,7 +588,7 @@ const server = http.createServer(async (req, res) => {
588
588
  return;
589
589
  }
590
590
 
591
- if (routePath === '/api/tts' && req.method === 'POST') {
591
+ if (pathOnly === '/api/tts' && req.method === 'POST') {
592
592
  try {
593
593
  const body = await parseBody(req);
594
594
  const text = body.text || '';
@@ -615,7 +615,7 @@ const server = http.createServer(async (req, res) => {
615
615
  return;
616
616
  }
617
617
 
618
- if (routePath === '/api/tts-stream' && req.method === 'POST') {
618
+ if (pathOnly === '/api/tts-stream' && req.method === 'POST') {
619
619
  try {
620
620
  const body = await parseBody(req);
621
621
  const text = body.text || '';
@@ -653,7 +653,7 @@ const server = http.createServer(async (req, res) => {
653
653
  return;
654
654
  }
655
655
 
656
- if (routePath === '/api/speech-status' && req.method === 'GET') {
656
+ if (pathOnly === '/api/speech-status' && req.method === 'GET') {
657
657
  try {
658
658
  const { getStatus } = await getSpeech();
659
659
  sendJSON(req, res, 200, getStatus());
@@ -663,7 +663,7 @@ const server = http.createServer(async (req, res) => {
663
663
  return;
664
664
  }
665
665
 
666
- if (routePath === '/api/folders' && req.method === 'POST') {
666
+ if (pathOnly === '/api/folders' && req.method === 'POST') {
667
667
  const body = await parseBody(req);
668
668
  const folderPath = body.path || STARTUP_CWD;
669
669
  try {
@@ -860,6 +860,8 @@ async function processMessageWithStreaming(conversationId, messageId, sessionId,
860
860
  debugLog(`[stream] Event ${eventCount}: type=${parsed.type}`);
861
861
 
862
862
  if (parsed.type === 'system') {
863
+ if (parsed.subtype === 'task_notification') return;
864
+
863
865
  const systemBlock = {
864
866
  type: 'system',
865
867
  subtype: parsed.subtype,
@@ -0,0 +1,18 @@
1
+ class RecorderProcessor extends AudioWorkletProcessor {
2
+ constructor() {
3
+ super();
4
+ this._stopped = false;
5
+ this.port.onmessage = (e) => {
6
+ if (e.data === 'stop') this._stopped = true;
7
+ };
8
+ }
9
+ process(inputs) {
10
+ if (this._stopped) return false;
11
+ const input = inputs[0];
12
+ if (input && input[0] && input[0].length > 0) {
13
+ this.port.postMessage(new Float32Array(input[0]));
14
+ }
15
+ return true;
16
+ }
17
+ }
18
+ registerProcessor('recorder-processor', RecorderProcessor);
@@ -9,7 +9,7 @@
9
9
  var currentAudio = null;
10
10
  var mediaStream = null;
11
11
  var audioContext = null;
12
- var scriptNode = null;
12
+ var workletNode = null;
13
13
  var recordedChunks = [];
14
14
  var TARGET_SAMPLE_RATE = 16000;
15
15
  var spokenChunks = new Set();
@@ -208,14 +208,13 @@
208
208
  mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
209
209
  audioContext = new (window.AudioContext || window.webkitAudioContext)();
210
210
  var source = audioContext.createMediaStreamSource(mediaStream);
211
- scriptNode = audioContext.createScriptProcessor(4096, 1, 1);
212
211
  recordedChunks = [];
213
- scriptNode.onaudioprocess = function(e) {
214
- var data = e.inputBuffer.getChannelData(0);
215
- recordedChunks.push(new Float32Array(data));
212
+ await audioContext.audioWorklet.addModule(BASE + '/js/audio-recorder-processor.js');
213
+ workletNode = new AudioWorkletNode(audioContext, 'recorder-processor');
214
+ workletNode.port.onmessage = function(e) {
215
+ recordedChunks.push(e.data);
216
216
  };
217
- source.connect(scriptNode);
218
- scriptNode.connect(audioContext.destination);
217
+ source.connect(workletNode);
219
218
  isRecording = true;
220
219
  var micBtn = document.getElementById('voiceMicBtn');
221
220
  if (micBtn) micBtn.classList.add('recording');
@@ -231,7 +230,7 @@
231
230
  var micBtn = document.getElementById('voiceMicBtn');
232
231
  if (micBtn) micBtn.classList.remove('recording');
233
232
  var el = document.getElementById('voiceTranscript');
234
- if (scriptNode) { scriptNode.disconnect(); scriptNode = null; }
233
+ if (workletNode) { workletNode.port.postMessage('stop'); workletNode.disconnect(); workletNode = null; }
235
234
  if (mediaStream) {
236
235
  mediaStream.getTracks().forEach(function(t) { t.stop(); });
237
236
  mediaStream = null;
@@ -321,6 +320,7 @@
321
320
  var TTS_MAX_FAILURES = 3;
322
321
  var ttsDisabledUntilReset = false;
323
322
  var streamingSupported = true;
323
+ var streamingFailedAt = 0;
324
324
 
325
325
  function playNextChunk() {
326
326
  if (audioChunkQueue.length === 0) {
@@ -392,7 +392,8 @@
392
392
  }
393
393
 
394
394
  function tryStreaming() {
395
- if (!streamingSupported) { tryNonStreaming(text); return; }
395
+ if (!streamingSupported && (Date.now() - streamingFailedAt < 30000)) { tryNonStreaming(text); return; }
396
+ streamingSupported = true;
396
397
  fetch(BASE + '/api/tts-stream', {
397
398
  method: 'POST',
398
399
  headers: { 'Content-Type': 'application/json' },
@@ -400,6 +401,7 @@
400
401
  }).then(function(resp) {
401
402
  if (!resp.ok) {
402
403
  streamingSupported = false;
404
+ streamingFailedAt = Date.now();
403
405
  throw new Error('TTS stream failed: ' + resp.status);
404
406
  }
405
407
  var reader = resp.body.getReader();