agentgui 1.0.776 → 1.0.778
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/lib/speech-manager.js +6 -3
- package/lib/tool-spawner.js +4 -0
- package/lib/ws-handlers-session.js +18 -1
- package/package.json +1 -1
- package/server.js +18 -19
- package/static/js/client.js +1 -1
- package/static/js/voice.js +4 -2
package/lib/speech-manager.js
CHANGED
|
@@ -65,7 +65,8 @@ export const modelDownloadState = {
|
|
|
65
65
|
error: null,
|
|
66
66
|
complete: false,
|
|
67
67
|
startTime: null,
|
|
68
|
-
downloadMetrics: new Map()
|
|
68
|
+
downloadMetrics: new Map(),
|
|
69
|
+
waiters: []
|
|
69
70
|
};
|
|
70
71
|
|
|
71
72
|
export function broadcastModelProgress(progress) {
|
|
@@ -116,8 +117,7 @@ async function validateAndCleanupModels(modelsDir) {
|
|
|
116
117
|
|
|
117
118
|
export async function ensureModelsDownloaded() {
|
|
118
119
|
if (modelDownloadState.downloading) {
|
|
119
|
-
|
|
120
|
-
return modelDownloadState.complete;
|
|
120
|
+
return new Promise(resolve => { modelDownloadState.waiters.push(resolve); });
|
|
121
121
|
}
|
|
122
122
|
modelDownloadState.downloading = true;
|
|
123
123
|
modelDownloadState.error = null;
|
|
@@ -147,6 +147,9 @@ export async function ensureModelsDownloaded() {
|
|
|
147
147
|
return false;
|
|
148
148
|
} finally {
|
|
149
149
|
modelDownloadState.downloading = false;
|
|
150
|
+
const result = modelDownloadState.complete;
|
|
151
|
+
for (const resolve of modelDownloadState.waiters) resolve(result);
|
|
152
|
+
modelDownloadState.waiters = [];
|
|
150
153
|
}
|
|
151
154
|
}
|
|
152
155
|
|
package/lib/tool-spawner.js
CHANGED
|
@@ -100,9 +100,11 @@ export function createInstaller(getTool, statusCache, checkToolStatusAsync) {
|
|
|
100
100
|
toolInstallMachine.send(toolId, { type: 'INSTALL_COMPLETE', version: fresh.version });
|
|
101
101
|
return fresh;
|
|
102
102
|
}
|
|
103
|
+
clearVersionCache();
|
|
103
104
|
toolInstallMachine.send(toolId, { type: 'FAILED', error: result.error });
|
|
104
105
|
return result;
|
|
105
106
|
} catch (err) {
|
|
107
|
+
clearVersionCache();
|
|
106
108
|
toolInstallMachine.send(toolId, { type: 'FAILED', error: err.message });
|
|
107
109
|
return { success: false, error: err.message };
|
|
108
110
|
}
|
|
@@ -122,9 +124,11 @@ export function createInstaller(getTool, statusCache, checkToolStatusAsync) {
|
|
|
122
124
|
toolInstallMachine.send(toolId, { type: 'UPDATE_COMPLETE', version: fresh.version });
|
|
123
125
|
return fresh;
|
|
124
126
|
}
|
|
127
|
+
clearVersionCache();
|
|
125
128
|
toolInstallMachine.send(toolId, { type: 'FAILED', error: result.error });
|
|
126
129
|
return result;
|
|
127
130
|
} catch (err) {
|
|
131
|
+
clearVersionCache();
|
|
128
132
|
toolInstallMachine.send(toolId, { type: 'FAILED', error: err.message });
|
|
129
133
|
return { success: false, error: err.message };
|
|
130
134
|
}
|
|
@@ -99,7 +99,24 @@ export function register(router, deps) {
|
|
|
99
99
|
router.handle('sess.exec', (p) => {
|
|
100
100
|
const limit = Math.min(parseInt(p.limit || '1000'), 5000);
|
|
101
101
|
const offset = Math.max(parseInt(p.offset || '0'), 0);
|
|
102
|
-
|
|
102
|
+
const session = db.getSession(p.id);
|
|
103
|
+
const allChunks = session ? (db.getChunksSince(p.id, 0) || []) : [];
|
|
104
|
+
const filterType = p.filterType;
|
|
105
|
+
const filtered = filterType ? allChunks.filter(e => e.type === filterType) : allChunks;
|
|
106
|
+
return {
|
|
107
|
+
sessionId: p.id,
|
|
108
|
+
events: filtered.slice(offset, offset + limit),
|
|
109
|
+
total: filtered.length,
|
|
110
|
+
limit,
|
|
111
|
+
offset,
|
|
112
|
+
hasMore: offset + limit < filtered.length,
|
|
113
|
+
metadata: {
|
|
114
|
+
status: session?.status || 'unknown',
|
|
115
|
+
startTime: session?.created_at || null,
|
|
116
|
+
duration: session?.completed_at && session?.created_at ? session.completed_at - session.created_at : 0,
|
|
117
|
+
eventCount: filtered.length
|
|
118
|
+
}
|
|
119
|
+
};
|
|
103
120
|
});
|
|
104
121
|
|
|
105
122
|
router.handle('agent.ls', () => {
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -143,10 +143,13 @@ function cleanupExecution(conversationId, broadcastCompletion = false) {
|
|
|
143
143
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
144
144
|
const rootDir = process.env.PORTABLE_EXE_DIR || __dirname;
|
|
145
145
|
const PORT = process.env.PORT || 3000;
|
|
146
|
-
const BASE_URL = (process.env.BASE_URL || '/gm').replace(/\/+$/, '');
|
|
146
|
+
const BASE_URL = (process.env.BASE_URL || '/gm').replace(/\/+/g, '/').replace(/\/+$/, '');
|
|
147
147
|
const watch = process.argv.includes('--no-watch') ? false : (process.argv.includes('--watch') || process.env.HOT_RELOAD !== 'false');
|
|
148
148
|
|
|
149
|
-
const STARTUP_CWD =
|
|
149
|
+
const STARTUP_CWD = (() => {
|
|
150
|
+
const cwd = process.env.STARTUP_CWD || process.cwd();
|
|
151
|
+
try { fs.accessSync(cwd, fs.constants.R_OK); return cwd; } catch { console.warn(`[server] STARTUP_CWD "${cwd}" not accessible, falling back to ${process.cwd()}`); return process.cwd(); }
|
|
152
|
+
})();
|
|
150
153
|
const staticDir = path.join(rootDir, 'static');
|
|
151
154
|
if (!fs.existsSync(staticDir)) fs.mkdirSync(staticDir, { recursive: true });
|
|
152
155
|
|
|
@@ -654,7 +657,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
654
657
|
sendJSON(req, res, 200, { message: userMessage, session, streamId: session.id });
|
|
655
658
|
|
|
656
659
|
processMessageWithStreaming(conversationId, userMessage.id, session.id, prompt, agentId, model, subAgent)
|
|
657
|
-
.catch(err => debugLog(`[stream] Uncaught error: ${err.message}`));
|
|
660
|
+
.catch(err => debugLog(`[stream] Uncaught error: ${err.stack || err.message}`));
|
|
658
661
|
return;
|
|
659
662
|
}
|
|
660
663
|
|
|
@@ -812,29 +815,25 @@ const server = http.createServer(async (req, res) => {
|
|
|
812
815
|
const filterType = url.searchParams.get('filterType');
|
|
813
816
|
|
|
814
817
|
try {
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
+
const session = queries.getSession(sessionId);
|
|
819
|
+
const allChunks = session ? (queries.getChunksSince(sessionId, 0) || []) : [];
|
|
820
|
+
const filtered = filterType ? allChunks.filter(e => e.type === filterType) : allChunks;
|
|
818
821
|
const executionData = {
|
|
819
822
|
sessionId,
|
|
820
|
-
events:
|
|
821
|
-
total:
|
|
823
|
+
events: filtered.slice(offset, offset + limit),
|
|
824
|
+
total: filtered.length,
|
|
822
825
|
limit,
|
|
823
826
|
offset,
|
|
824
|
-
hasMore:
|
|
827
|
+
hasMore: offset + limit < filtered.length,
|
|
825
828
|
metadata: {
|
|
826
|
-
status: '
|
|
827
|
-
startTime:
|
|
828
|
-
duration: 0,
|
|
829
|
-
eventCount:
|
|
830
|
-
|
|
829
|
+
status: session?.status || 'unknown',
|
|
830
|
+
startTime: session?.created_at || null,
|
|
831
|
+
duration: session?.completed_at && session?.created_at ? session.completed_at - session.created_at : 0,
|
|
832
|
+
eventCount: filtered.length
|
|
833
|
+
}
|
|
831
834
|
};
|
|
832
835
|
|
|
833
|
-
|
|
834
|
-
executionData.events = executionData.events.filter(e => e.type === filterType);
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
sendJSON(req, res, 200, executionData);
|
|
836
|
+
sendJSON(req, res, 200, executionData);
|
|
838
837
|
} catch (err) {
|
|
839
838
|
sendJSON(req, res, 400, { error: err.message });
|
|
840
839
|
}
|
package/static/js/client.js
CHANGED
|
@@ -94,7 +94,7 @@ class AgentGUIClient {
|
|
|
94
94
|
this._debug = typeof localStorage !== 'undefined' && localStorage.getItem('debug') === '1';
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
_dbg(...args) { if (this._debug)
|
|
97
|
+
_dbg(...args) { if (this._debug) console.log('[AgentGUI]', ...args); }
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
100
|
* Initialize the client
|
package/static/js/voice.js
CHANGED
|
@@ -57,8 +57,9 @@
|
|
|
57
57
|
|
|
58
58
|
function _doSpeak(text) {
|
|
59
59
|
audioChunkQueue = [];
|
|
60
|
-
var
|
|
61
|
-
|
|
60
|
+
var cacheKey = selectedVoiceId + ':' + text;
|
|
61
|
+
var cached = ttsAudioCache.get(cacheKey);
|
|
62
|
+
if (cached) { ttsAudioCache.delete(cacheKey); ttsAudioCache.set(cacheKey, cached); audioChunkQueue.push(cached); playNextChunk(); return; }
|
|
62
63
|
function stream() {
|
|
63
64
|
if (!streamingSupported) { nonStream(text); return; }
|
|
64
65
|
fetch(BASE + '/api/tts-stream', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: text, voiceId: selectedVoiceId }) })
|
|
@@ -71,6 +72,7 @@
|
|
|
71
72
|
buf = cat(buf, res.value);
|
|
72
73
|
while (buf.length >= 4) {
|
|
73
74
|
var len = new DataView(buf.buffer, buf.byteOffset, 4).getUint32(0, false);
|
|
75
|
+
if (len > 10 * 1024 * 1024) { buf = new Uint8Array(0); if (api()) api().send({ type: 'PLAYBACK_ERROR' }); return; }
|
|
74
76
|
if (buf.length < 4 + len) break;
|
|
75
77
|
audioChunkQueue.push(new Blob([buf.slice(4, 4 + len)], { type: 'audio/wav' }));
|
|
76
78
|
buf = buf.slice(4 + len);
|