lemonade-interactive-loader 1.0.1 → 1.0.2
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/README.md +1 -1
- package/package.json +1 -1
- package/src/cli/menu.js +7 -1
- package/src/services/server.js +67 -5
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ The main menu adapts based on whether you have a configuration saved:
|
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
| Command | Description |
|
|
76
|
-
|
|
76
|
+
|---------|-------------|
|
|
77
77
|
| **▶️ Start Server** | Launch Lemonade Server with saved config (when config exists) |
|
|
78
78
|
| **✏️ Edit Configuration** | Update your saved settings interactively |
|
|
79
79
|
| **👁️ View Configuration** | See your current configuration and installed builds |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lemonade-interactive-loader",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Interactive CLI tool to launch Lemonade Server with custom arguments and download llama.cpp releases - Cross-platform (Windows/Linux)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
package/src/cli/menu.js
CHANGED
|
@@ -3,7 +3,7 @@ const { loadConfig } = require('../config');
|
|
|
3
3
|
const { getAllInstalledAssets, getLlamaServerPath, downloadAndExtractLlamaCpp, deleteInstalledAsset } = require('../services/asset-manager');
|
|
4
4
|
const { selectLlamaCppRelease, selectAsset, askLaunchServer } = require('./prompts');
|
|
5
5
|
const { runSetupWizard } = require('./setup-wizard');
|
|
6
|
-
const { launchLemonadeServer } = require('../services/server');
|
|
6
|
+
const { launchLemonadeServer, setupShutdownHandlers } = require('../services/server');
|
|
7
7
|
const { inferBackendType, formatBytes } = require('../utils/system');
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -321,6 +321,8 @@ async function handleCommand(command) {
|
|
|
321
321
|
console.log('No configuration found. Please run "setup" first.');
|
|
322
322
|
return;
|
|
323
323
|
}
|
|
324
|
+
// Set up shutdown handlers to kill server on exit
|
|
325
|
+
setupShutdownHandlers();
|
|
324
326
|
await launchLemonadeServer(config);
|
|
325
327
|
break;
|
|
326
328
|
}
|
|
@@ -349,6 +351,10 @@ async function runCLI() {
|
|
|
349
351
|
}
|
|
350
352
|
|
|
351
353
|
console.log('\n👋 Goodbye!\n');
|
|
354
|
+
|
|
355
|
+
// Ensure server is shut down when exiting the CLI
|
|
356
|
+
const { shutdownLemonadeServer } = require('../services/server');
|
|
357
|
+
shutdownLemonadeServer();
|
|
352
358
|
}
|
|
353
359
|
|
|
354
360
|
module.exports = {
|
package/src/services/server.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
-
const { execSync } = require('child_process');
|
|
2
|
+
const { execSync, spawn } = require('child_process');
|
|
3
3
|
const { LEMONADE_SERVER_DEFAULT_PATH } = require('../config/constants');
|
|
4
4
|
const { findLlamaServer } = require('../utils/system');
|
|
5
5
|
const { getLlamaServerPath } = require('./asset-manager');
|
|
6
6
|
|
|
7
|
+
// Track the server process for graceful shutdown
|
|
8
|
+
let serverProcess = null;
|
|
9
|
+
|
|
7
10
|
/**
|
|
8
11
|
* Build server command arguments
|
|
9
12
|
* @param {Object} config - Server configuration
|
|
@@ -154,21 +157,80 @@ async function launchLemonadeServer(config) {
|
|
|
154
157
|
console.log('\nStarting server...\n');
|
|
155
158
|
|
|
156
159
|
try {
|
|
157
|
-
|
|
158
|
-
|
|
160
|
+
// Parse the command into executable and arguments
|
|
161
|
+
const parts = command.trim().split(/\s+/);
|
|
162
|
+
const executable = parts[0];
|
|
163
|
+
const execArgs = parts.slice(1);
|
|
164
|
+
|
|
165
|
+
// Spawn the server process
|
|
166
|
+
serverProcess = spawn(executable, execArgs, {
|
|
159
167
|
stdio: 'inherit',
|
|
160
168
|
env: process.env
|
|
161
169
|
});
|
|
170
|
+
|
|
171
|
+
// Handle process exit
|
|
172
|
+
serverProcess.on('close', (code) => {
|
|
173
|
+
console.log(`\nServer exited with code ${code}`);
|
|
174
|
+
serverProcess = null;
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
serverProcess.on('error', (err) => {
|
|
178
|
+
console.error(`Server process error: ${err.message}`);
|
|
179
|
+
});
|
|
180
|
+
|
|
162
181
|
} catch (error) {
|
|
163
|
-
console.error(`Server exited with error
|
|
182
|
+
console.error(`Server exited with error: ${error.message}`);
|
|
164
183
|
if (error.status !== null) {
|
|
165
184
|
process.exit(error.status);
|
|
166
185
|
}
|
|
167
186
|
}
|
|
168
187
|
}
|
|
169
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Gracefully shutdown the lemonade server
|
|
191
|
+
*/
|
|
192
|
+
function shutdownLemonadeServer() {
|
|
193
|
+
if (serverProcess) {
|
|
194
|
+
console.log('\n\nShutting down Lemonade Server...');
|
|
195
|
+
|
|
196
|
+
// Try graceful shutdown first (SIGTERM)
|
|
197
|
+
serverProcess.on('exit', () => {
|
|
198
|
+
console.log('Server shut down successfully.');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
serverProcess.on('error', (err) => {
|
|
202
|
+
console.error(`Error shutting down server: ${err.message}`);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Send SIGTERM signal
|
|
206
|
+
serverProcess.kill('SIGTERM');
|
|
207
|
+
|
|
208
|
+
// Force kill after 5 seconds if still running
|
|
209
|
+
setTimeout(() => {
|
|
210
|
+
if (serverProcess && !serverProcess.killed) {
|
|
211
|
+
console.log('Force killing server...');
|
|
212
|
+
serverProcess.kill('SIGKILL');
|
|
213
|
+
}
|
|
214
|
+
}, 5000);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Set up signal handlers for graceful shutdown
|
|
219
|
+
function setupShutdownHandlers() {
|
|
220
|
+
const shutdown = (signal) => {
|
|
221
|
+
console.log(`\n\nReceived ${signal}. Shutting down...`);
|
|
222
|
+
shutdownLemonadeServer();
|
|
223
|
+
setTimeout(() => process.exit(0), 2000);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
process.on('SIGINT', () => shutdown('SIGINT')); // Ctrl+C
|
|
227
|
+
process.on('SIGTERM', () => shutdown('SIGTERM')); // Termination signal
|
|
228
|
+
}
|
|
229
|
+
|
|
170
230
|
module.exports = {
|
|
171
231
|
buildServerArgs,
|
|
172
232
|
formatCommand,
|
|
173
|
-
launchLemonadeServer
|
|
233
|
+
launchLemonadeServer,
|
|
234
|
+
shutdownLemonadeServer,
|
|
235
|
+
setupShutdownHandlers
|
|
174
236
|
};
|