agentgui 1.0.180 → 1.0.181
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/pocket-sidecar.js +38 -7
- package/package.json +1 -1
package/lib/pocket-sidecar.js
CHANGED
|
@@ -6,7 +6,6 @@ import { fileURLToPath } from 'url';
|
|
|
6
6
|
import http from 'http';
|
|
7
7
|
|
|
8
8
|
const ROOT = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
9
|
-
const POCKET_BIN = path.join(ROOT, 'data', 'pocket-venv', 'bin', 'pocket-tts');
|
|
10
9
|
const PORT = 8787;
|
|
11
10
|
|
|
12
11
|
const FALLBACK_VOICE = 'alba';
|
|
@@ -15,11 +14,21 @@ const state = {
|
|
|
15
14
|
restartCount: 0, failureCount: 0, lastError: null,
|
|
16
15
|
healthy: false, voicePath: null, starting: false,
|
|
17
16
|
shutdownRequested: false, healthTimer: null, restartTimer: null,
|
|
18
|
-
voiceCloning: false,
|
|
17
|
+
voiceCloning: false, adopted: false,
|
|
19
18
|
};
|
|
20
19
|
globalThis.__pocketSidecar = state;
|
|
21
20
|
|
|
22
|
-
function
|
|
21
|
+
function findBinary() {
|
|
22
|
+
const candidates = [
|
|
23
|
+
path.join(ROOT, 'data', 'pocket-venv', 'bin', 'pocket-tts'),
|
|
24
|
+
'/config/workspace/agentgui/data/pocket-venv/bin/pocket-tts',
|
|
25
|
+
path.join(os.homedir(), '.gmgui', 'pocket-venv', 'bin', 'pocket-tts'),
|
|
26
|
+
];
|
|
27
|
+
for (const p of candidates) if (fs.existsSync(p)) return p;
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isInstalled() { return !!findBinary(); }
|
|
23
32
|
|
|
24
33
|
function findVoiceFile(voiceId) {
|
|
25
34
|
if (!voiceId || voiceId === 'default') return null;
|
|
@@ -54,21 +63,24 @@ function killProcess() {
|
|
|
54
63
|
|
|
55
64
|
function scheduleRestart() {
|
|
56
65
|
if (state.shutdownRequested) return;
|
|
57
|
-
killProcess();
|
|
66
|
+
if (!state.adopted) killProcess();
|
|
58
67
|
const delay = Math.min(1000 * Math.pow(2, state.restartCount), 30000);
|
|
59
68
|
state.restartCount++;
|
|
60
69
|
console.log(`[POCKET-TTS] Restart in ${delay}ms (attempt ${state.restartCount})`);
|
|
61
70
|
state.restartTimer = setTimeout(() => {
|
|
62
71
|
state.restartTimer = null;
|
|
72
|
+
state.adopted = false;
|
|
63
73
|
start(state.voicePath).catch(e => console.error('[POCKET-TTS] Restart failed:', e.message));
|
|
64
74
|
}, delay);
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
function spawnSidecar(voice) {
|
|
78
|
+
const bin = findBinary();
|
|
79
|
+
if (!bin) throw new Error('pocket-tts binary not found');
|
|
68
80
|
const args = ['serve', '--host', '0.0.0.0', '--port', String(PORT)];
|
|
69
81
|
if (voice) args.push('--voice', voice);
|
|
70
|
-
console.log('[POCKET-TTS] Starting:',
|
|
71
|
-
return spawn(
|
|
82
|
+
console.log('[POCKET-TTS] Starting:', bin, args.join(' '));
|
|
83
|
+
return spawn(bin, args, {
|
|
72
84
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
73
85
|
env: { ...process.env, PYTHONUNBUFFERED: '1' },
|
|
74
86
|
});
|
|
@@ -92,10 +104,29 @@ async function waitForReady(proc, timeoutSec) {
|
|
|
92
104
|
return false;
|
|
93
105
|
}
|
|
94
106
|
|
|
107
|
+
async function adoptRunning() {
|
|
108
|
+
if (await healthCheck()) {
|
|
109
|
+
state.status = 'running'; state.healthy = true; state.adopted = true;
|
|
110
|
+
state.restartCount = 0; state.failureCount = 0; state.lastError = null;
|
|
111
|
+
if (!state.healthTimer) state.healthTimer = setInterval(async () => {
|
|
112
|
+
if (state.status !== 'running') return;
|
|
113
|
+
const ok = await healthCheck();
|
|
114
|
+
if (!ok && !state.shutdownRequested) {
|
|
115
|
+
state.failureCount++;
|
|
116
|
+
if (state.failureCount >= 3) { state.adopted = false; scheduleRestart(); }
|
|
117
|
+
} else if (ok) state.failureCount = 0;
|
|
118
|
+
}, 10000);
|
|
119
|
+
console.log('[POCKET-TTS] Adopted existing instance on port', PORT);
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
95
125
|
async function start(voicePath) {
|
|
96
|
-
if (!isInstalled()) { state.lastError = 'not installed'; state.status = 'unavailable'; return false; }
|
|
97
126
|
if (state.starting) return false;
|
|
98
127
|
if (state.status === 'running' && state.healthy) return true;
|
|
128
|
+
if (await adoptRunning()) return true;
|
|
129
|
+
if (!isInstalled()) { state.lastError = 'not installed'; state.status = 'unavailable'; return false; }
|
|
99
130
|
state.starting = true; state.shutdownRequested = false;
|
|
100
131
|
const requestedVoice = voicePath || state.voicePath;
|
|
101
132
|
try {
|