@nxuss/lemma 0.4.2 → 0.4.4
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/lemma-proxy.cjs +60 -8
- package/package.json +2 -1
package/lemma-proxy.cjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
/**
|
|
4
|
-
* Lemma Proxy
|
|
4
|
+
* Lemma Proxy — Universal AI Cache CLI
|
|
5
5
|
* Commands: start, stop, stats, status, activate <key>
|
|
6
6
|
*/
|
|
7
|
+
const pkg = require('./package.json');
|
|
8
|
+
const VERSION = pkg.version;
|
|
7
9
|
|
|
8
10
|
const { program } = require('commander');
|
|
9
11
|
const express = require('express');
|
|
@@ -76,6 +78,21 @@ function ensureProjectDir(name) {
|
|
|
76
78
|
return dir;
|
|
77
79
|
}
|
|
78
80
|
|
|
81
|
+
function getPidByPort(port) {
|
|
82
|
+
const { execSync } = require('child_process');
|
|
83
|
+
try {
|
|
84
|
+
if (process.platform === 'win32') {
|
|
85
|
+
const out = execSync(`netstat -ano | findstr :${port}`).toString();
|
|
86
|
+
const lines = out.split('\n').filter(l => l.includes('LISTENING'));
|
|
87
|
+
if (lines.length > 0) return lines[0].trim().split(/\s+/).pop();
|
|
88
|
+
} else {
|
|
89
|
+
const out = execSync(`lsof -t -i :${port}`).toString().trim();
|
|
90
|
+
return out.split('\n')[0]; // Take first if multiple
|
|
91
|
+
}
|
|
92
|
+
} catch { return null; }
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
79
96
|
// ── License helpers ────────────────────────────────────────────────────────────
|
|
80
97
|
function loadLicense() {
|
|
81
98
|
return readJson(LICENSE_FILE, { isPro: false });
|
|
@@ -87,7 +104,7 @@ async function validateKeyRemote(key) {
|
|
|
87
104
|
const body = JSON.stringify({ key });
|
|
88
105
|
const u = new URL(VALIDATE_URL);
|
|
89
106
|
const req = https.request({ hostname: u.hostname, port: 443, path: u.pathname, method: 'POST',
|
|
90
|
-
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), 'User-Agent':
|
|
107
|
+
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), 'User-Agent': `lemma-proxy/${VERSION}` }
|
|
91
108
|
}, res => {
|
|
92
109
|
let d = '';
|
|
93
110
|
res.on('data', c => d += c);
|
|
@@ -464,17 +481,25 @@ class LemmaServer {
|
|
|
464
481
|
|
|
465
482
|
start() {
|
|
466
483
|
const server = http.createServer(this.app);
|
|
484
|
+
server.on('error', (e) => {
|
|
485
|
+
if (e.code === 'EADDRINUSE') {
|
|
486
|
+
console.error(`\n❌ Error: Port ${this.port} is already in use.`);
|
|
487
|
+
console.error(`💡 Try stopping the existing process with 'lemma stop' or use a different port with '--port <number>'.\n`);
|
|
488
|
+
process.exit(1);
|
|
489
|
+
}
|
|
490
|
+
throw e;
|
|
491
|
+
});
|
|
467
492
|
server.listen(this.port, () => {
|
|
468
493
|
fs.writeFileSync(PID_FILE, String(process.pid));
|
|
469
494
|
fs.writeFileSync(PORT_FILE, String(this.port));
|
|
470
|
-
console.log(`\n🚀 Lemma Proxy
|
|
495
|
+
console.log(`\n🚀 Lemma Proxy v${VERSION}\n📁 Project : ${this.projectName}\n🔌 Port : ${this.port}\n`);
|
|
471
496
|
});
|
|
472
497
|
process.on('SIGTERM', () => server.close());
|
|
473
498
|
}
|
|
474
499
|
}
|
|
475
500
|
|
|
476
501
|
// ── CLI ────────────────────────────────────────────────────────────────────────
|
|
477
|
-
program.name('lemma').description('Lemma Proxy CLI — Intelligent AI Gateway').version(
|
|
502
|
+
program.name('lemma').description('Lemma Proxy CLI — Intelligent AI Gateway').version(VERSION);
|
|
478
503
|
|
|
479
504
|
program.command('start')
|
|
480
505
|
.description('Start the proxy server')
|
|
@@ -484,6 +509,16 @@ program.command('start')
|
|
|
484
509
|
.action(async (opts) => {
|
|
485
510
|
const port = parseInt(opts.port, 10);
|
|
486
511
|
|
|
512
|
+
// Check if already running
|
|
513
|
+
try {
|
|
514
|
+
const resp = await axios.get(`http://localhost:${port}/health`, { timeout: 500 });
|
|
515
|
+
if (resp.data && resp.data.status === 'ok') {
|
|
516
|
+
console.log(`\n⚠️ Lemma Proxy is already running on port ${port} (Project: ${resp.data.project})`);
|
|
517
|
+
console.log(`💡 Use 'lemma status' for details or 'lemma stop' to restart.\n`);
|
|
518
|
+
process.exit(0);
|
|
519
|
+
}
|
|
520
|
+
} catch {}
|
|
521
|
+
|
|
487
522
|
if (opts.stack) {
|
|
488
523
|
const { spawn } = require('child_process');
|
|
489
524
|
console.log('🚀 Launching Lemma Full Stack...');
|
|
@@ -534,15 +569,32 @@ program.command('start')
|
|
|
534
569
|
|
|
535
570
|
program.command('stop')
|
|
536
571
|
.description('Stop the proxy server')
|
|
537
|
-
.
|
|
572
|
+
.option('-p, --port <number>', 'Port to check', '8081')
|
|
573
|
+
.action((opts) => {
|
|
574
|
+
const port = parseInt(opts.port, 10);
|
|
575
|
+
let stopped = false;
|
|
538
576
|
try {
|
|
539
577
|
if (fs.existsSync(PID_FILE)) {
|
|
540
578
|
const pid = fs.readFileSync(PID_FILE, 'utf8');
|
|
541
|
-
|
|
579
|
+
try {
|
|
580
|
+
process.kill(parseInt(pid), 'SIGTERM');
|
|
581
|
+
stopped = true;
|
|
582
|
+
} catch {}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
if (!stopped) {
|
|
586
|
+
const pidByPort = getPidByPort(port);
|
|
587
|
+
if (pidByPort) {
|
|
588
|
+
process.kill(parseInt(pidByPort), 'SIGTERM');
|
|
589
|
+
console.log(`✅ Stopped process ${pidByPort} on port ${port}`);
|
|
590
|
+
stopped = true;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
if (stopped) {
|
|
542
595
|
console.log('✅ Stopped');
|
|
543
596
|
} else {
|
|
544
|
-
console.log('⚠️ No
|
|
545
|
-
// Fallback for windows/mac: kill by port or name
|
|
597
|
+
console.log('⚠️ No running process found.');
|
|
546
598
|
}
|
|
547
599
|
} catch { console.log('⚠️ Could not stop process.'); }
|
|
548
600
|
if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxuss/lemma",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Intelligent AI Gateway — Semantic cache, Privacy Firewall, and Autonomous Cost-Optimization for AI Agents.",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -161,6 +161,7 @@
|
|
|
161
161
|
"homepage": "https://github.com/Nxusbets/lemma#readme",
|
|
162
162
|
"dependencies": {
|
|
163
163
|
"@chroma-core/default-embed": "^0.1.9",
|
|
164
|
+
"@nxuss/lemma": "^0.4.3",
|
|
164
165
|
"@types/cors": "^2.8.19",
|
|
165
166
|
"axios": "^1.6.0",
|
|
166
167
|
"commander": "^14.0.3",
|