@nxuss/lemma 0.5.0 → 0.5.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 +61 -8
- package/dashboard/dist/assets/{index-B4TA31pA.js → index-CIlkFwDs.js} +98 -98
- package/dashboard/dist/assets/index-CIlkFwDs.js.map +1 -0
- package/dashboard/dist/index.html +1 -1
- package/dist/cjs/cli/lemma-proxy.d.ts +2 -0
- package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/cjs/cli/lemma-proxy.js +243 -37
- package/dist/cjs/cli/lemma-proxy.js.map +1 -1
- package/dist/cjs/mcp/index.js +81 -0
- package/dist/cjs/mcp/index.js.map +1 -1
- package/dist/cjs/utils/ClipboardWatcher.d.ts.map +1 -1
- package/dist/cjs/utils/ClipboardWatcher.js +3 -0
- package/dist/cjs/utils/ClipboardWatcher.js.map +1 -1
- package/dist/cjs/utils/SavingsLedger.d.ts +52 -0
- package/dist/cjs/utils/SavingsLedger.d.ts.map +1 -0
- package/dist/cjs/utils/SavingsLedger.js +101 -0
- package/dist/cjs/utils/SavingsLedger.js.map +1 -0
- package/dist/cjs/utils/reportSavings.d.ts +24 -0
- package/dist/cjs/utils/reportSavings.d.ts.map +1 -0
- package/dist/cjs/utils/reportSavings.js +53 -0
- package/dist/cjs/utils/reportSavings.js.map +1 -0
- package/dist/esm/cli/lemma-proxy.d.ts +2 -0
- package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/esm/cli/lemma-proxy.js +241 -37
- package/dist/esm/cli/lemma-proxy.js.map +1 -1
- package/dist/esm/mcp/index.js +81 -0
- package/dist/esm/mcp/index.js.map +1 -1
- package/dist/esm/utils/ClipboardWatcher.d.ts.map +1 -1
- package/dist/esm/utils/ClipboardWatcher.js +3 -0
- package/dist/esm/utils/ClipboardWatcher.js.map +1 -1
- package/dist/esm/utils/SavingsLedger.d.ts +52 -0
- package/dist/esm/utils/SavingsLedger.d.ts.map +1 -0
- package/dist/esm/utils/SavingsLedger.js +98 -0
- package/dist/esm/utils/SavingsLedger.js.map +1 -0
- package/dist/esm/utils/reportSavings.d.ts +24 -0
- package/dist/esm/utils/reportSavings.d.ts.map +1 -0
- package/dist/esm/utils/reportSavings.js +47 -0
- package/dist/esm/utils/reportSavings.js.map +1 -0
- package/package.json +2 -2
- package/dashboard/dist/assets/index-B4TA31pA.js.map +0 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>lemma Dashboard - Agent Orchestration Hub</title>
|
|
8
|
-
<script type="module" crossorigin src="/dashboard/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/dashboard/assets/index-CIlkFwDs.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/dashboard/assets/index-DNqq3gA9.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lemma-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/lemma-proxy.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"lemma-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/lemma-proxy.ts"],"names":[],"mappings":";AAoNA,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CA0I3D;AAED,wBAAgB,+BAA+B,IAAI,IAAI,CAyCtD;AAmsCD,wBAAsB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6KhL"}
|
|
@@ -4,6 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.autoConfigureAll = autoConfigureAll;
|
|
8
|
+
exports.startBackgroundClipboardWatcher = startBackgroundClipboardWatcher;
|
|
7
9
|
exports.performAutoHeal = performAutoHeal;
|
|
8
10
|
const commander_1 = require("commander");
|
|
9
11
|
const express_1 = __importDefault(require("express"));
|
|
@@ -30,7 +32,7 @@ function getVersion() {
|
|
|
30
32
|
catch { }
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
|
-
return '0.
|
|
35
|
+
return '0.5.2';
|
|
34
36
|
}
|
|
35
37
|
const VERSION = getVersion();
|
|
36
38
|
const ComplexityRouter_1 = __importDefault(require("../proxy/ComplexityRouter"));
|
|
@@ -38,6 +40,7 @@ const SemanticScrubber_1 = __importDefault(require("../security/SemanticScrubber
|
|
|
38
40
|
const CloudSyncClient_1 = __importDefault(require("../cloud/CloudSyncClient"));
|
|
39
41
|
const ContextSqueezer_1 = require("../utils/ContextSqueezer");
|
|
40
42
|
const AgentMultiplexer_1 = require("../proxy/AgentMultiplexer");
|
|
43
|
+
const SavingsLedger_1 = require("../utils/SavingsLedger");
|
|
41
44
|
const chroma = new chromadb_1.ChromaClient({ host: 'localhost', port: 8000 });
|
|
42
45
|
const dummyEmbeddingFunction = { generate: (texts) => Promise.resolve([]) };
|
|
43
46
|
const complexityRouter = new ComplexityRouter_1.default();
|
|
@@ -59,6 +62,13 @@ function logEvent(event) {
|
|
|
59
62
|
EVENT_LOG.push(ev);
|
|
60
63
|
if (EVENT_LOG.length > MAX_EVENTS)
|
|
61
64
|
EVENT_LOG.shift();
|
|
65
|
+
// Print a terminal savings summary every 10 events
|
|
66
|
+
if (EVENT_LOG.length > 0 && EVENT_LOG.length % 10 === 0) {
|
|
67
|
+
const snap = SavingsLedger_1.savingsLedger.getSnapshot();
|
|
68
|
+
if (snap.total.tokensSaved > 0) {
|
|
69
|
+
console.log('\n' + SavingsLedger_1.savingsLedger.getTerminalSummary() + '\n');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
62
72
|
}
|
|
63
73
|
const FREE_LIMIT = 500;
|
|
64
74
|
const WARN_PCT = 0.8;
|
|
@@ -199,6 +209,182 @@ function ensureGitIgnore() {
|
|
|
199
209
|
catch { }
|
|
200
210
|
return added;
|
|
201
211
|
}
|
|
212
|
+
const CLIPBOARD_PID_FILE = path_1.default.join(CACHE_DIR, 'clipboard.pid');
|
|
213
|
+
function autoConfigureAll(projectName) {
|
|
214
|
+
const project = projectName || detectProject();
|
|
215
|
+
const HOME = process.env.HOME || process.env.USERPROFILE || '~';
|
|
216
|
+
// 1. Claude Desktop Config
|
|
217
|
+
try {
|
|
218
|
+
const isWin = process.platform === 'win32';
|
|
219
|
+
const claudePath = isWin
|
|
220
|
+
? path_1.default.join(process.env.APPDATA || '', 'Claude/claude_desktop_config.json')
|
|
221
|
+
: path_1.default.join(HOME, 'Library/Application Support/Claude/claude_desktop_config.json');
|
|
222
|
+
if (fs_1.default.existsSync(path_1.default.dirname(claudePath))) {
|
|
223
|
+
let config = { mcpServers: {} };
|
|
224
|
+
if (fs_1.default.existsSync(claudePath)) {
|
|
225
|
+
try {
|
|
226
|
+
config = JSON.parse(fs_1.default.readFileSync(claudePath, 'utf8'));
|
|
227
|
+
}
|
|
228
|
+
catch { }
|
|
229
|
+
}
|
|
230
|
+
if (!config.mcpServers)
|
|
231
|
+
config.mcpServers = {};
|
|
232
|
+
config.mcpServers.lemma = {
|
|
233
|
+
command: 'npx',
|
|
234
|
+
args: ['-y', '@nxuss/lemma', 'mcp'],
|
|
235
|
+
env: { LEMMA_PROJECT: project }
|
|
236
|
+
};
|
|
237
|
+
fs_1.default.writeFileSync(claudePath, JSON.stringify(config, null, 2));
|
|
238
|
+
console.log(`✅ [Claude Desktop] Configured automatically! (Restart Claude to activate)`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
console.log(`⚠️ Could not auto-configure Claude Desktop: ${e.message}`);
|
|
243
|
+
}
|
|
244
|
+
// 2. Shell Profiles Environment Override
|
|
245
|
+
try {
|
|
246
|
+
const profiles = [
|
|
247
|
+
path_1.default.join(HOME, '.zshrc'),
|
|
248
|
+
path_1.default.join(HOME, '.bashrc'),
|
|
249
|
+
path_1.default.join(HOME, '.bash_profile'),
|
|
250
|
+
path_1.default.join(HOME, '.profile')
|
|
251
|
+
];
|
|
252
|
+
const lines = [
|
|
253
|
+
'',
|
|
254
|
+
'# Lemma AI Gateway Overrides',
|
|
255
|
+
'export OPENAI_BASE_URL="http://localhost:8081/v1"',
|
|
256
|
+
'export ANTHROPIC_BASE_URL="http://localhost:8081"',
|
|
257
|
+
'export LEMMA_PROJECT="' + project + '"',
|
|
258
|
+
''
|
|
259
|
+
].join('\n');
|
|
260
|
+
for (const profile of profiles) {
|
|
261
|
+
if (fs_1.default.existsSync(profile)) {
|
|
262
|
+
try {
|
|
263
|
+
const content = fs_1.default.readFileSync(profile, 'utf8');
|
|
264
|
+
if (!content.includes('OPENAI_BASE_URL') && !content.includes('LEMMA_PROJECT')) {
|
|
265
|
+
fs_1.default.appendFileSync(profile, lines);
|
|
266
|
+
console.log(`✅ [Shell Profile] Configured ${path_1.default.basename(profile)} with local redirect variables!`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
catch { }
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
catch (e) {
|
|
274
|
+
console.log(`⚠️ Could not auto-configure shell profiles: ${e.message}`);
|
|
275
|
+
}
|
|
276
|
+
// 3. Cursor & Windsurf settings.json updates
|
|
277
|
+
try {
|
|
278
|
+
const isWin = process.platform === 'win32';
|
|
279
|
+
const isMac = process.platform === 'darwin';
|
|
280
|
+
const candidates = [];
|
|
281
|
+
if (isMac) {
|
|
282
|
+
candidates.push({
|
|
283
|
+
name: 'Cursor',
|
|
284
|
+
path: path_1.default.join(HOME, 'Library/Application Support/Cursor/User/settings.json')
|
|
285
|
+
});
|
|
286
|
+
candidates.push({
|
|
287
|
+
name: 'Windsurf',
|
|
288
|
+
path: path_1.default.join(HOME, 'Library/Application Support/Windsurf/User/settings.json')
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
else if (isWin) {
|
|
292
|
+
const appData = process.env.APPDATA || '';
|
|
293
|
+
candidates.push({
|
|
294
|
+
name: 'Cursor',
|
|
295
|
+
path: path_1.default.join(appData, 'Cursor/User/settings.json')
|
|
296
|
+
});
|
|
297
|
+
candidates.push({
|
|
298
|
+
name: 'Windsurf',
|
|
299
|
+
path: path_1.default.join(appData, 'Windsurf/User/settings.json')
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
candidates.push({
|
|
304
|
+
name: 'Cursor',
|
|
305
|
+
path: path_1.default.join(HOME, '.config/Cursor/User/settings.json')
|
|
306
|
+
});
|
|
307
|
+
candidates.push({
|
|
308
|
+
name: 'Windsurf',
|
|
309
|
+
path: path_1.default.join(HOME, '.config/Windsurf/User/settings.json')
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
for (const cand of candidates) {
|
|
313
|
+
const dir = path_1.default.dirname(cand.path);
|
|
314
|
+
if (fs_1.default.existsSync(dir)) {
|
|
315
|
+
let settings = {};
|
|
316
|
+
if (fs_1.default.existsSync(cand.path)) {
|
|
317
|
+
try {
|
|
318
|
+
settings = JSON.parse(fs_1.default.readFileSync(cand.path, 'utf8'));
|
|
319
|
+
}
|
|
320
|
+
catch { }
|
|
321
|
+
}
|
|
322
|
+
let updated = false;
|
|
323
|
+
// Settings configuration to route custom openai/anthropic models through the proxy
|
|
324
|
+
const updates = {
|
|
325
|
+
"openai.baseURL": "http://localhost:8081/v1",
|
|
326
|
+
"openai.apiKey": "dummy-key-for-lemma",
|
|
327
|
+
"anthropic.baseURL": "http://localhost:8081",
|
|
328
|
+
"anthropic.apiKey": "dummy-key-for-lemma"
|
|
329
|
+
};
|
|
330
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
331
|
+
if (settings[key] !== value) {
|
|
332
|
+
settings[key] = value;
|
|
333
|
+
updated = true;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (updated) {
|
|
337
|
+
fs_1.default.writeFileSync(cand.path, JSON.stringify(settings, null, 2));
|
|
338
|
+
console.log(`✅ [${cand.name}] Configured editor settings to route via local gateway!`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
catch (e) {
|
|
344
|
+
console.log(`⚠️ Could not auto-configure editor settings: ${e.message}`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
function startBackgroundClipboardWatcher() {
|
|
348
|
+
try {
|
|
349
|
+
if (fs_1.default.existsSync(CLIPBOARD_PID_FILE)) {
|
|
350
|
+
const oldPid = fs_1.default.readFileSync(CLIPBOARD_PID_FILE, 'utf8');
|
|
351
|
+
try {
|
|
352
|
+
process.kill(parseInt(oldPid, 10), 0); // Check if process is still alive
|
|
353
|
+
console.log(`✅ [Clipboard] Watcher is already running in background (PID: ${oldPid})`);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
// Process is dead, clean up pid file
|
|
358
|
+
try {
|
|
359
|
+
fs_1.default.unlinkSync(CLIPBOARD_PID_FILE);
|
|
360
|
+
}
|
|
361
|
+
catch { }
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
console.log(`🔄 Starting Clipboard Watcher in background...`);
|
|
365
|
+
const { spawn } = require('child_process');
|
|
366
|
+
// Resolve path of lemma command or script
|
|
367
|
+
const scriptPath = fs_1.default.existsSync(path_1.default.join(__dirname, 'dist', 'cjs', 'cli', 'lemma-proxy.js'))
|
|
368
|
+
? path_1.default.join(__dirname, 'dist', 'cjs', 'cli', 'lemma-proxy.js')
|
|
369
|
+
: (fs_1.default.existsSync(path_1.default.join(__dirname, 'lemma-proxy.ts')) ? path_1.default.join(__dirname, 'lemma-proxy.ts') : __filename);
|
|
370
|
+
const isTs = scriptPath.endsWith('.ts');
|
|
371
|
+
const cmd = isTs ? 'npx' : 'node';
|
|
372
|
+
const args = isTs ? ['tsx', scriptPath, 'clipboard'] : [scriptPath, 'clipboard'];
|
|
373
|
+
const cp = spawn(cmd, args, {
|
|
374
|
+
stdio: 'ignore',
|
|
375
|
+
detached: true,
|
|
376
|
+
env: { ...process.env }
|
|
377
|
+
});
|
|
378
|
+
cp.unref();
|
|
379
|
+
if (cp.pid) {
|
|
380
|
+
fs_1.default.writeFileSync(CLIPBOARD_PID_FILE, String(cp.pid));
|
|
381
|
+
console.log(`✅ [Clipboard] Watcher has been started (PID: ${cp.pid})`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
catch (err) {
|
|
385
|
+
console.error(`❌ Failed to automatically start Clipboard Watcher in background: ${err.message}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
202
388
|
// ── License helpers ────────────────────────────────────────────────────────────
|
|
203
389
|
async function loadLicense() {
|
|
204
390
|
return readJson(LICENSE_FILE, { isPro: false });
|
|
@@ -703,6 +889,7 @@ class LemmaServer {
|
|
|
703
889
|
const count = CACHE.size;
|
|
704
890
|
CACHE.clear();
|
|
705
891
|
EVENT_LOG.length = 0; // Clear live event log
|
|
892
|
+
SavingsLedger_1.savingsLedger.reset(); // Reset savings counters
|
|
706
893
|
// Reset and persist statistics for the current project
|
|
707
894
|
if (this.stats[this.projectName]) {
|
|
708
895
|
this.stats[this.projectName] = {
|
|
@@ -717,6 +904,25 @@ class LemmaServer {
|
|
|
717
904
|
}
|
|
718
905
|
res.json({ success: true, clearedEntries: count });
|
|
719
906
|
});
|
|
907
|
+
// Savings breakdown by source for the dashboard
|
|
908
|
+
this.app.get('/api/savings-breakdown', (req, res) => {
|
|
909
|
+
res.json(SavingsLedger_1.savingsLedger.getSnapshot());
|
|
910
|
+
});
|
|
911
|
+
// Cross-process savings reporter — MCP and other processes POST here
|
|
912
|
+
this.app.post('/api/savings-record', (req, res) => {
|
|
913
|
+
const { source, charsBefore, charsAfter, tokens } = req.body || {};
|
|
914
|
+
const validSources = ['clipboard', 'contextSqueeze', 'historyPrune', 'complexityRouting', 'cache'];
|
|
915
|
+
if (!source || !validSources.includes(source)) {
|
|
916
|
+
return res.status(400).json({ error: 'Invalid source' });
|
|
917
|
+
}
|
|
918
|
+
if (typeof tokens === 'number' && tokens > 0) {
|
|
919
|
+
SavingsLedger_1.savingsLedger.recordTokens(source, tokens);
|
|
920
|
+
}
|
|
921
|
+
else if (typeof charsBefore === 'number' && typeof charsAfter === 'number') {
|
|
922
|
+
SavingsLedger_1.savingsLedger.record(source, charsBefore, charsAfter);
|
|
923
|
+
}
|
|
924
|
+
res.json({ ok: true, snapshot: SavingsLedger_1.savingsLedger.getSnapshot().total });
|
|
925
|
+
});
|
|
720
926
|
this.app.get('/dashboard/*', (req, res) => res.sendFile(path_1.default.join(this.dashboardPath, 'index.html')));
|
|
721
927
|
}
|
|
722
928
|
}
|
|
@@ -744,6 +950,13 @@ class LemmaServer {
|
|
|
744
950
|
const model = routingDecision.model;
|
|
745
951
|
if (req.body.model)
|
|
746
952
|
req.body.model = model;
|
|
953
|
+
// Record complexity routing savings when model is downgraded
|
|
954
|
+
if (routingDecision.complexity === 'low' && model !== originalModel) {
|
|
955
|
+
// Estimated token savings: cheap model costs ~5x less, so avg prompt of ~800 tokens saves ~640 tokens
|
|
956
|
+
const estimatedPromptTokens = Math.floor(prompt.length / 4);
|
|
957
|
+
const routingSavings = Math.floor(estimatedPromptTokens * 0.8); // conservative 80% cost reduction
|
|
958
|
+
SavingsLedger_1.savingsLedger.recordTokens('complexityRouting', routingSavings);
|
|
959
|
+
}
|
|
747
960
|
// Apply the Agent Multiplexer to local-verify the prompt in parallel
|
|
748
961
|
const enrichedPrompt = await agentMultiplexer.multiplexPrompt(prompt, model);
|
|
749
962
|
// Resolve conversation session key and retrieve/create the fileHistory map
|
|
@@ -766,6 +979,7 @@ class LemmaServer {
|
|
|
766
979
|
const squeezedPrompt = squeezeResult.squeezed;
|
|
767
980
|
const compressionSavings = squeezeResult.originalSize - squeezeResult.squeezedSize;
|
|
768
981
|
if (compressionSavings > 0) {
|
|
982
|
+
SavingsLedger_1.savingsLedger.record('contextSqueeze', squeezeResult.originalSize, squeezeResult.squeezedSize);
|
|
769
983
|
console.log(`⚡ [Squeezer] Compressed prompt from ${squeezeResult.originalSize} to ${squeezeResult.squeezedSize} chars (Saved ${(squeezeResult.compressionRatio * 100).toFixed(1)}% context tokens!)`);
|
|
770
984
|
}
|
|
771
985
|
if (provider === 'openai' || provider === 'anthropic') {
|
|
@@ -775,6 +989,9 @@ class LemmaServer {
|
|
|
775
989
|
const pruneResult = (0, ContextSqueezer_1.pruneHistoryMessages)(req.body.messages);
|
|
776
990
|
req.body.messages = pruneResult.messages;
|
|
777
991
|
historyTokensSaved = pruneResult.tokensSavedEstimate + Math.floor(compressionSavings / 4);
|
|
992
|
+
if (pruneResult.tokensSavedEstimate > 0) {
|
|
993
|
+
SavingsLedger_1.savingsLedger.recordTokens('historyPrune', pruneResult.tokensSavedEstimate);
|
|
994
|
+
}
|
|
778
995
|
}
|
|
779
996
|
}
|
|
780
997
|
else if (provider === 'gemini') {
|
|
@@ -787,7 +1004,9 @@ class LemmaServer {
|
|
|
787
1004
|
}
|
|
788
1005
|
const hit = cacheGet(provider, prompt);
|
|
789
1006
|
if (hit) {
|
|
790
|
-
|
|
1007
|
+
const cacheTokensSaved = 2000 + historyTokensSaved;
|
|
1008
|
+
SavingsLedger_1.savingsLedger.recordTokens('cache', cacheTokensSaved);
|
|
1009
|
+
await recordStat(this.stats, this.projectName, true, Date.now() - t0, provider, cacheTokensSaved);
|
|
791
1010
|
const unmaskedData = semanticScrubber.unmask(hit.data, tokenMap);
|
|
792
1011
|
if (isStream)
|
|
793
1012
|
return simulateHitStream(res, unmaskedData, provider, model, tier, 1.0);
|
|
@@ -1052,10 +1271,17 @@ commander_1.program.command('start')
|
|
|
1052
1271
|
if (resp.data && resp.data.status === 'ok') {
|
|
1053
1272
|
console.log(`\n⚠️ Lemma Proxy is already running on port ${port} (Project: ${resp.data.project})`);
|
|
1054
1273
|
console.log(`💡 Use 'lemma status' for details or 'lemma stop' to restart.\n`);
|
|
1274
|
+
// Keep configurations up to date even if server was already started
|
|
1275
|
+
const runningProject = resp.data.project || detectProject();
|
|
1276
|
+
autoConfigureAll(runningProject);
|
|
1277
|
+
startBackgroundClipboardWatcher();
|
|
1055
1278
|
process.exit(0);
|
|
1056
1279
|
}
|
|
1057
1280
|
}
|
|
1058
1281
|
catch { }
|
|
1282
|
+
const startProject = opts.project || detectProject();
|
|
1283
|
+
autoConfigureAll(startProject);
|
|
1284
|
+
startBackgroundClipboardWatcher();
|
|
1059
1285
|
// Automatically enable autopilot if stack is enabled and user is Pro
|
|
1060
1286
|
const runAutopilot = opts.autopilot || opts.stack;
|
|
1061
1287
|
if (runAutopilot) {
|
|
@@ -1154,6 +1380,19 @@ commander_1.program.command('stop')
|
|
|
1154
1380
|
}
|
|
1155
1381
|
if (fs_1.default.existsSync(PID_FILE))
|
|
1156
1382
|
fs_1.default.unlinkSync(PID_FILE);
|
|
1383
|
+
// Stop background Clipboard Watcher if active
|
|
1384
|
+
try {
|
|
1385
|
+
if (fs_1.default.existsSync(CLIPBOARD_PID_FILE)) {
|
|
1386
|
+
const cbPid = fs_1.default.readFileSync(CLIPBOARD_PID_FILE, 'utf8');
|
|
1387
|
+
try {
|
|
1388
|
+
process.kill(parseInt(cbPid, 10), 'SIGTERM');
|
|
1389
|
+
console.log(`✅ Stopped background Clipboard Watcher (PID: ${cbPid})`);
|
|
1390
|
+
}
|
|
1391
|
+
catch { }
|
|
1392
|
+
fs_1.default.unlinkSync(CLIPBOARD_PID_FILE);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
catch { }
|
|
1157
1396
|
});
|
|
1158
1397
|
commander_1.program.command('status')
|
|
1159
1398
|
.description('Check proxy status')
|
|
@@ -1247,41 +1486,8 @@ commander_1.program.command('init')
|
|
|
1247
1486
|
fs_1.default.writeFileSync(envFile, lemmaConfig);
|
|
1248
1487
|
console.log('✅ Created .env with Lemma configuration');
|
|
1249
1488
|
}
|
|
1250
|
-
console.log('\n🧠 \x1b[35mAuto-Setup MCP for AI IDEs
|
|
1251
|
-
|
|
1252
|
-
const { exec } = require('child_process');
|
|
1253
|
-
const isWin = process.platform === 'win32';
|
|
1254
|
-
const claudePath = isWin
|
|
1255
|
-
? path_1.default.join(process.env.APPDATA || '', 'Claude/claude_desktop_config.json')
|
|
1256
|
-
: path_1.default.join(process.env.HOME || '~', 'Library/Application Support/Claude/claude_desktop_config.json');
|
|
1257
|
-
if (fs_1.default.existsSync(path_1.default.dirname(claudePath))) {
|
|
1258
|
-
try {
|
|
1259
|
-
let config = { mcpServers: {} };
|
|
1260
|
-
if (fs_1.default.existsSync(claudePath)) {
|
|
1261
|
-
config = JSON.parse(fs_1.default.readFileSync(claudePath, 'utf8'));
|
|
1262
|
-
}
|
|
1263
|
-
if (!config.mcpServers)
|
|
1264
|
-
config.mcpServers = {};
|
|
1265
|
-
config.mcpServers.lemma = {
|
|
1266
|
-
command: 'npx',
|
|
1267
|
-
args: ['-y', '@nxuss/lemma', 'mcp'],
|
|
1268
|
-
env: { LEMMA_PROJECT: project }
|
|
1269
|
-
};
|
|
1270
|
-
fs_1.default.writeFileSync(claudePath, JSON.stringify(config, null, 2));
|
|
1271
|
-
console.log(`✅ \x1b[32mClaude Desktop configured automatically!\x1b[0m (Restart Claude to activate)`);
|
|
1272
|
-
}
|
|
1273
|
-
catch (e) {
|
|
1274
|
-
console.log('⚠️ Could not auto-configure Claude Desktop. No worries, you can do it manually.');
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
console.log('🚀 Opening IDE configuration pages...');
|
|
1278
|
-
const urls = [
|
|
1279
|
-
'https://docs.anthropic.com/en/docs/agents-and-tools/mcp#using-mcp-in-claude-desktop',
|
|
1280
|
-
'https://cursor.com',
|
|
1281
|
-
'https://codeium.com/windsurf'
|
|
1282
|
-
];
|
|
1283
|
-
const opener = process.platform === 'darwin' ? 'open' : (process.platform === 'win32' ? 'start' : 'xdg-open');
|
|
1284
|
-
urls.forEach(url => exec(`${opener} ${url}`));
|
|
1489
|
+
console.log('\n🧠 \x1b[35mAuto-Setup MCP and redirection overrides for AI IDEs...\x1b[0m');
|
|
1490
|
+
autoConfigureAll(project);
|
|
1285
1491
|
console.log('\n✨ Project initialized for the Agentic Era!');
|
|
1286
1492
|
console.log('🚀 Run "lemma start" to begin.\n');
|
|
1287
1493
|
});
|