lemonade-interactive-loader 1.0.2 → 1.0.3
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 +2 -2
- package/package.json +1 -1
- package/src/cli/menu.js +19 -3
- package/src/cli/setup-wizard.js +1 -1
- package/src/config/constants.js +3 -3
- package/src/services/download.js +1 -1
- package/src/services/server.js +19 -9
package/README.md
CHANGED
|
@@ -169,7 +169,7 @@ Point Lemonade Server to your existing model directory (like LM Studio's):
|
|
|
169
169
|
|
|
170
170
|
Configuration is automatically saved and loaded:
|
|
171
171
|
|
|
172
|
-
- **Location**: `~/.lemonade-launcher/config.json` (Linux/macOS) or `%USERPROFILE%\.lemonade-launcher\config.json` (Windows)
|
|
172
|
+
- **Location**: `~/.lemonade-interactive-launcher/config.json` (Linux/macOS) or `%USERPROFILE%\.lemonade-interactive-launcher\config.json` (Windows)
|
|
173
173
|
- **Format**: JSON
|
|
174
174
|
- **Auto-saved**: After every setup or edit
|
|
175
175
|
|
|
@@ -250,7 +250,7 @@ Run Command Prompt or PowerShell as Administrator.
|
|
|
250
250
|
|
|
251
251
|
#### Build download fails
|
|
252
252
|
- Check your internet connection
|
|
253
|
-
- Ensure you have write permissions to `~/.lemonade-launcher/`
|
|
253
|
+
- Ensure you have write permissions to `~/.lemonade-interactive-launcher/`
|
|
254
254
|
- Try downloading the asset manually from GitHub
|
|
255
255
|
|
|
256
256
|
#### Server won't start
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lemonade-interactive-loader",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
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
|
@@ -263,15 +263,20 @@ async function resetConfiguration() {
|
|
|
263
263
|
/**
|
|
264
264
|
* Handle main menu command
|
|
265
265
|
* @param {string} command - Selected command
|
|
266
|
+
* @returns {Promise<boolean>} True if should exit the app
|
|
266
267
|
*/
|
|
267
268
|
async function handleCommand(command) {
|
|
269
|
+
let shouldExit = false;
|
|
270
|
+
|
|
268
271
|
switch (command) {
|
|
269
272
|
case 'setup':
|
|
270
273
|
await runSetupWizard(false);
|
|
271
274
|
if (await askLaunchServer()) {
|
|
272
275
|
const config = loadConfig();
|
|
273
276
|
if (Object.keys(config).length > 0) {
|
|
277
|
+
setupShutdownHandlers();
|
|
274
278
|
await launchLemonadeServer(config);
|
|
279
|
+
shouldExit = true;
|
|
275
280
|
}
|
|
276
281
|
}
|
|
277
282
|
break;
|
|
@@ -281,7 +286,9 @@ async function handleCommand(command) {
|
|
|
281
286
|
if (await askLaunchServer()) {
|
|
282
287
|
const config = loadConfig();
|
|
283
288
|
if (Object.keys(config).length > 0) {
|
|
289
|
+
setupShutdownHandlers();
|
|
284
290
|
await launchLemonadeServer(config);
|
|
291
|
+
shouldExit = true;
|
|
285
292
|
}
|
|
286
293
|
}
|
|
287
294
|
break;
|
|
@@ -294,7 +301,7 @@ async function handleCommand(command) {
|
|
|
294
301
|
await resetConfiguration();
|
|
295
302
|
break;
|
|
296
303
|
|
|
297
|
-
|
|
304
|
+
|
|
298
305
|
|
|
299
306
|
case 'manage':
|
|
300
307
|
let manageAction;
|
|
@@ -319,13 +326,17 @@ async function handleCommand(command) {
|
|
|
319
326
|
const config = loadConfig();
|
|
320
327
|
if (Object.keys(config).length === 0) {
|
|
321
328
|
console.log('No configuration found. Please run "setup" first.');
|
|
322
|
-
return;
|
|
329
|
+
return false;
|
|
323
330
|
}
|
|
324
331
|
// Set up shutdown handlers to kill server on exit
|
|
325
332
|
setupShutdownHandlers();
|
|
326
333
|
await launchLemonadeServer(config);
|
|
334
|
+
// After server exits, exit the app completely
|
|
335
|
+
shouldExit = true;
|
|
327
336
|
break;
|
|
328
337
|
}
|
|
338
|
+
|
|
339
|
+
return shouldExit;
|
|
329
340
|
}
|
|
330
341
|
|
|
331
342
|
/**
|
|
@@ -336,7 +347,12 @@ async function runCLI() {
|
|
|
336
347
|
|
|
337
348
|
while (continueRunning) {
|
|
338
349
|
const command = await showMainMenu();
|
|
339
|
-
await handleCommand(command);
|
|
350
|
+
const shouldExit = await handleCommand(command);
|
|
351
|
+
|
|
352
|
+
// Exit the app if we just exited from the server
|
|
353
|
+
if (shouldExit) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
340
356
|
|
|
341
357
|
const { continueRunning: shouldContinue } = await inquirer.prompt([
|
|
342
358
|
{
|
package/src/cli/setup-wizard.js
CHANGED
package/src/config/constants.js
CHANGED
|
@@ -2,14 +2,14 @@ const path = require('path');
|
|
|
2
2
|
const os = require('os');
|
|
3
3
|
|
|
4
4
|
// Configuration directories
|
|
5
|
-
const USER_CONFIG_DIR = path.join(os.homedir(), '.lemonade-launcher');
|
|
5
|
+
const USER_CONFIG_DIR = path.join(os.homedir(), '.lemonade-interactive-launcher');
|
|
6
6
|
const USER_CONFIG_FILE = path.join(USER_CONFIG_DIR, 'config.json');
|
|
7
|
-
const DEFAULT_LLAMACPP_INSTALL_DIR = path.join(os.homedir(), '.lemonade-launcher', 'llama-cpp');
|
|
7
|
+
const DEFAULT_LLAMACPP_INSTALL_DIR = path.join(os.homedir(), '.lemonade-interactive-launcher', 'llama-cpp');
|
|
8
8
|
|
|
9
9
|
// GitHub API
|
|
10
10
|
const GITHUB_RELEASES_URL = 'https://api.github.com/repos/ggml-org/llama.cpp/releases';
|
|
11
11
|
const GITHUB_API_HEADERS = {
|
|
12
|
-
'User-Agent': 'lemonade-launcher',
|
|
12
|
+
'User-Agent': 'lemonade-interactive-launcher',
|
|
13
13
|
'Accept': 'application/vnd.github.v3+json'
|
|
14
14
|
};
|
|
15
15
|
|
package/src/services/download.js
CHANGED
|
@@ -20,7 +20,7 @@ function downloadFile(url, outputPath) {
|
|
|
20
20
|
|
|
21
21
|
const file = fs.createWriteStream(outputPath);
|
|
22
22
|
|
|
23
|
-
const req = protocol.get(url, { headers: { 'User-Agent': 'lemonade-launcher' } }, (res) => {
|
|
23
|
+
const req = protocol.get(url, { headers: { 'User-Agent': 'lemonade-interactive-launcher' } }, (res) => {
|
|
24
24
|
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
25
25
|
downloadFile(res.headers.location, outputPath)
|
|
26
26
|
.then(resolve)
|
package/src/services/server.js
CHANGED
|
@@ -157,25 +157,35 @@ async function launchLemonadeServer(config) {
|
|
|
157
157
|
console.log('\nStarting server...\n');
|
|
158
158
|
|
|
159
159
|
try {
|
|
160
|
+
// Build the command for spawning
|
|
161
|
+
const commandStr = formatCommand(serverPath, args, {});
|
|
162
|
+
|
|
160
163
|
// Parse the command into executable and arguments
|
|
161
|
-
const parts =
|
|
164
|
+
const parts = commandStr.trim().split(/\s+/);
|
|
162
165
|
const executable = parts[0];
|
|
163
166
|
const execArgs = parts.slice(1);
|
|
164
167
|
|
|
168
|
+
console.log(`Spawning: ${executable} ${execArgs.join(' ')}`);
|
|
169
|
+
|
|
165
170
|
// Spawn the server process
|
|
166
171
|
serverProcess = spawn(executable, execArgs, {
|
|
167
172
|
stdio: 'inherit',
|
|
168
173
|
env: process.env
|
|
169
174
|
});
|
|
170
175
|
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
// Wait for the process to exit (blocking)
|
|
177
|
+
await new Promise((resolve, reject) => {
|
|
178
|
+
serverProcess.on('close', (code) => {
|
|
179
|
+
console.log(`\nServer exited with code ${code}`);
|
|
180
|
+
serverProcess = null;
|
|
181
|
+
resolve(code);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
serverProcess.on('error', (err) => {
|
|
185
|
+
console.error(`Server process error: ${err.message}`);
|
|
186
|
+
serverProcess = null;
|
|
187
|
+
reject(err);
|
|
188
|
+
});
|
|
179
189
|
});
|
|
180
190
|
|
|
181
191
|
} catch (error) {
|