@nxuss/lemma 0.5.1 → 0.5.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 +1 -1
- 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 +416 -121
- package/dist/cjs/cli/lemma-proxy.js.map +1 -1
- package/dist/cjs/config/index.d.ts.map +1 -1
- package/dist/cjs/config/index.js +2 -1
- package/dist/cjs/config/index.js.map +1 -1
- package/dist/cjs/errors/LemmaError.d.ts +52 -0
- package/dist/cjs/errors/LemmaError.d.ts.map +1 -0
- package/dist/cjs/errors/LemmaError.js +84 -0
- package/dist/cjs/errors/LemmaError.js.map +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +24 -22
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/mcp/index.js +81 -0
- package/dist/cjs/mcp/index.js.map +1 -1
- package/dist/cjs/subconscious/SemanticCache.d.ts +4 -4
- package/dist/cjs/subconscious/SemanticCache.d.ts.map +1 -1
- package/dist/cjs/subconscious/SemanticCache.js +14 -10
- package/dist/cjs/subconscious/SemanticCache.js.map +1 -1
- package/dist/cjs/types/index.d.ts +8 -8
- package/dist/cjs/types/index.d.ts.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/logger.d.ts +27 -6
- package/dist/cjs/utils/logger.d.ts.map +1 -1
- package/dist/cjs/utils/logger.js +96 -28
- package/dist/cjs/utils/logger.js.map +1 -1
- 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 +414 -121
- package/dist/esm/cli/lemma-proxy.js.map +1 -1
- package/dist/esm/config/index.d.ts.map +1 -1
- package/dist/esm/config/index.js +2 -1
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/errors/LemmaError.d.ts +52 -0
- package/dist/esm/errors/LemmaError.d.ts.map +1 -0
- package/dist/esm/errors/LemmaError.js +75 -0
- package/dist/esm/errors/LemmaError.js.map +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +24 -22
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/mcp/index.js +81 -0
- package/dist/esm/mcp/index.js.map +1 -1
- package/dist/esm/subconscious/SemanticCache.d.ts +4 -4
- package/dist/esm/subconscious/SemanticCache.d.ts.map +1 -1
- package/dist/esm/subconscious/SemanticCache.js +14 -10
- package/dist/esm/subconscious/SemanticCache.js.map +1 -1
- package/dist/esm/types/index.d.ts +8 -8
- package/dist/esm/types/index.d.ts.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/logger.d.ts +27 -6
- package/dist/esm/utils/logger.d.ts.map +1 -1
- package/dist/esm/utils/logger.js +93 -28
- package/dist/esm/utils/logger.js.map +1 -1
- 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 +27 -24
- package/dashboard/dist/assets/index-B4TA31pA.js.map +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SavingsLedger — Singleton accumulator for token savings across all Lemma modules.
|
|
3
|
+
*
|
|
4
|
+
* Every module (ClipboardWatcher, ContextSqueezer, ComplexityRouter, SemanticCache)
|
|
5
|
+
* calls `ledger.record(source, charsBefore, charsAfter)` — no one knows about the dashboard.
|
|
6
|
+
*
|
|
7
|
+
* The proxy exposes the ledger via GET /api/savings-breakdown for the dashboard to consume.
|
|
8
|
+
*/
|
|
9
|
+
export type SavingsSource = 'clipboard' | 'contextSqueeze' | 'historyPrune' | 'complexityRouting' | 'cache';
|
|
10
|
+
export interface SourceStats {
|
|
11
|
+
/** How many individual savings events were recorded */
|
|
12
|
+
events: number;
|
|
13
|
+
/** Estimated tokens saved (chars / 4) */
|
|
14
|
+
tokensSaved: number;
|
|
15
|
+
/** Estimated USD saved (tokensSaved * avg price per token) */
|
|
16
|
+
costSaved: number;
|
|
17
|
+
}
|
|
18
|
+
export interface SavingsSnapshot {
|
|
19
|
+
clipboard: SourceStats;
|
|
20
|
+
contextSqueeze: SourceStats;
|
|
21
|
+
historyPrune: SourceStats;
|
|
22
|
+
complexityRouting: SourceStats;
|
|
23
|
+
cache: SourceStats;
|
|
24
|
+
total: SourceStats;
|
|
25
|
+
sessionStartedAt: string;
|
|
26
|
+
}
|
|
27
|
+
declare class SavingsLedger {
|
|
28
|
+
private sources;
|
|
29
|
+
private readonly sessionStartedAt;
|
|
30
|
+
constructor();
|
|
31
|
+
/**
|
|
32
|
+
* Record a savings event by char counts (automatically converts to token estimate).
|
|
33
|
+
* @param source Which module recorded the savings
|
|
34
|
+
* @param charsBefore Original char count before compression/routing
|
|
35
|
+
* @param charsAfter Resulting char count after compression/routing
|
|
36
|
+
*/
|
|
37
|
+
record(source: SavingsSource, charsBefore: number, charsAfter: number): void;
|
|
38
|
+
/**
|
|
39
|
+
* Record a savings event directly in tokens (for sources that already know their token count).
|
|
40
|
+
*/
|
|
41
|
+
recordTokens(source: SavingsSource, tokensSaved: number): void;
|
|
42
|
+
/** Returns a full snapshot including computed totals */
|
|
43
|
+
getSnapshot(): SavingsSnapshot;
|
|
44
|
+
/** Returns a pretty terminal summary block */
|
|
45
|
+
getTerminalSummary(): string;
|
|
46
|
+
/** Reset all counters (e.g., on cache clear) */
|
|
47
|
+
reset(): void;
|
|
48
|
+
}
|
|
49
|
+
/** Global singleton — import this everywhere */
|
|
50
|
+
export declare const savingsLedger: SavingsLedger;
|
|
51
|
+
export default savingsLedger;
|
|
52
|
+
//# sourceMappingURL=SavingsLedger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SavingsLedger.d.ts","sourceRoot":"","sources":["../../../src/utils/SavingsLedger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,gBAAgB,GAAG,cAAc,GAAG,mBAAmB,GAAG,OAAO,CAAC;AAE5G,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,WAAW,CAAC;IACvB,cAAc,EAAE,WAAW,CAAC;IAC5B,YAAY,EAAE,WAAW,CAAC;IAC1B,iBAAiB,EAAE,WAAW,CAAC;IAC/B,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAKD,cAAM,aAAa;IACjB,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;;IAa1C;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAY5E;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAQ9D,wDAAwD;IACxD,WAAW,IAAI,eAAe;IAgB9B,8CAA8C;IAC9C,kBAAkB,IAAI,MAAM;IA+B5B,gDAAgD;IAChD,KAAK,IAAI,IAAI;CAKd;AAED,gDAAgD;AAChD,eAAO,MAAM,aAAa,eAAsB,CAAC;AACjD,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SavingsLedger — Singleton accumulator for token savings across all Lemma modules.
|
|
3
|
+
*
|
|
4
|
+
* Every module (ClipboardWatcher, ContextSqueezer, ComplexityRouter, SemanticCache)
|
|
5
|
+
* calls `ledger.record(source, charsBefore, charsAfter)` — no one knows about the dashboard.
|
|
6
|
+
*
|
|
7
|
+
* The proxy exposes the ledger via GET /api/savings-breakdown for the dashboard to consume.
|
|
8
|
+
*/
|
|
9
|
+
/** Average blended cost per input token across GPT-4o / Claude Sonnet / Gemini Pro */
|
|
10
|
+
const AVG_COST_PER_TOKEN = 0.000008; // $0.008 per 1K tokens
|
|
11
|
+
class SavingsLedger {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.sessionStartedAt = new Date().toISOString();
|
|
14
|
+
this.sources = {
|
|
15
|
+
clipboard: { events: 0, tokensSaved: 0, costSaved: 0 },
|
|
16
|
+
contextSqueeze: { events: 0, tokensSaved: 0, costSaved: 0 },
|
|
17
|
+
historyPrune: { events: 0, tokensSaved: 0, costSaved: 0 },
|
|
18
|
+
complexityRouting: { events: 0, tokensSaved: 0, costSaved: 0 },
|
|
19
|
+
cache: { events: 0, tokensSaved: 0, costSaved: 0 },
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Record a savings event by char counts (automatically converts to token estimate).
|
|
24
|
+
* @param source Which module recorded the savings
|
|
25
|
+
* @param charsBefore Original char count before compression/routing
|
|
26
|
+
* @param charsAfter Resulting char count after compression/routing
|
|
27
|
+
*/
|
|
28
|
+
record(source, charsBefore, charsAfter) {
|
|
29
|
+
const charsSaved = Math.max(0, charsBefore - charsAfter);
|
|
30
|
+
if (charsSaved === 0)
|
|
31
|
+
return;
|
|
32
|
+
const tokensSaved = Math.floor(charsSaved / 4);
|
|
33
|
+
const costSaved = tokensSaved * AVG_COST_PER_TOKEN;
|
|
34
|
+
this.sources[source].events++;
|
|
35
|
+
this.sources[source].tokensSaved += tokensSaved;
|
|
36
|
+
this.sources[source].costSaved += costSaved;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Record a savings event directly in tokens (for sources that already know their token count).
|
|
40
|
+
*/
|
|
41
|
+
recordTokens(source, tokensSaved) {
|
|
42
|
+
if (tokensSaved <= 0)
|
|
43
|
+
return;
|
|
44
|
+
const costSaved = tokensSaved * AVG_COST_PER_TOKEN;
|
|
45
|
+
this.sources[source].events++;
|
|
46
|
+
this.sources[source].tokensSaved += tokensSaved;
|
|
47
|
+
this.sources[source].costSaved += costSaved;
|
|
48
|
+
}
|
|
49
|
+
/** Returns a full snapshot including computed totals */
|
|
50
|
+
getSnapshot() {
|
|
51
|
+
const total = { events: 0, tokensSaved: 0, costSaved: 0 };
|
|
52
|
+
for (const src of Object.values(this.sources)) {
|
|
53
|
+
total.events += src.events;
|
|
54
|
+
total.tokensSaved += src.tokensSaved;
|
|
55
|
+
total.costSaved += src.costSaved;
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
...this.sources,
|
|
59
|
+
total,
|
|
60
|
+
sessionStartedAt: this.sessionStartedAt,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Returns a pretty terminal summary block */
|
|
64
|
+
getTerminalSummary() {
|
|
65
|
+
const snap = this.getSnapshot();
|
|
66
|
+
const fmt = (n) => n.toLocaleString('en-US');
|
|
67
|
+
const fmtUSD = (n) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 4 }).format(n);
|
|
68
|
+
const rows = [
|
|
69
|
+
['📋 Clipboard Squeeze', snap.clipboard.tokensSaved, snap.clipboard.costSaved],
|
|
70
|
+
['🗜️ Context Squeeze ', snap.contextSqueeze.tokensSaved, snap.contextSqueeze.costSaved],
|
|
71
|
+
['📜 History Prune ', snap.historyPrune.tokensSaved, snap.historyPrune.costSaved],
|
|
72
|
+
['🔀 Model Routing ', snap.complexityRouting.tokensSaved, snap.complexityRouting.costSaved],
|
|
73
|
+
['⚡ Semantic Cache ', snap.cache.tokensSaved, snap.cache.costSaved],
|
|
74
|
+
];
|
|
75
|
+
const lines = [
|
|
76
|
+
'┌──────────────────────────────────────────────────────┐',
|
|
77
|
+
'│ 💰 Lemma Savings Report (this session) │',
|
|
78
|
+
'├──────────────────────────────────────────────────────┤',
|
|
79
|
+
...rows
|
|
80
|
+
.filter(([, tokens]) => tokens > 0)
|
|
81
|
+
.map(([label, tokens, cost]) => `│ ${label} ${fmt(tokens).padStart(7)} tokens ${fmtUSD(cost).padStart(10)} │`),
|
|
82
|
+
'│ ────────────────────────────────────────────────── │',
|
|
83
|
+
`│ TOTAL ${fmt(snap.total.tokensSaved).padStart(7)} tokens ${fmtUSD(snap.total.costSaved).padStart(10)} │`,
|
|
84
|
+
'└──────────────────────────────────────────────────────┘',
|
|
85
|
+
];
|
|
86
|
+
return lines.join('\n');
|
|
87
|
+
}
|
|
88
|
+
/** Reset all counters (e.g., on cache clear) */
|
|
89
|
+
reset() {
|
|
90
|
+
for (const key of Object.keys(this.sources)) {
|
|
91
|
+
this.sources[key] = { events: 0, tokensSaved: 0, costSaved: 0 };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Global singleton — import this everywhere */
|
|
96
|
+
export const savingsLedger = new SavingsLedger();
|
|
97
|
+
export default savingsLedger;
|
|
98
|
+
//# sourceMappingURL=SavingsLedger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SavingsLedger.js","sourceRoot":"","sources":["../../../src/utils/SavingsLedger.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,24 +8,45 @@ export declare enum LogLevel {
|
|
|
8
8
|
DEBUG = 3
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Structured Logger Entry Schema
|
|
12
|
+
*/
|
|
13
|
+
export interface LogEntry {
|
|
14
|
+
timestamp: string;
|
|
15
|
+
level: string;
|
|
16
|
+
context: string;
|
|
17
|
+
message: string;
|
|
18
|
+
meta?: any;
|
|
19
|
+
error?: {
|
|
20
|
+
message: string;
|
|
21
|
+
stack?: string;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Enterprise Structured Logger supporting standard console and file output streams.
|
|
12
26
|
*/
|
|
13
27
|
declare class Logger {
|
|
14
28
|
private level;
|
|
15
29
|
private context;
|
|
30
|
+
private format;
|
|
31
|
+
private logFilePath;
|
|
32
|
+
private disableConsole;
|
|
16
33
|
constructor(context?: string);
|
|
17
34
|
/**
|
|
18
35
|
* Parse log level from string
|
|
19
36
|
*/
|
|
20
37
|
private parseLogLevel;
|
|
21
38
|
/**
|
|
22
|
-
* Format
|
|
39
|
+
* Format text log line with color
|
|
23
40
|
*/
|
|
24
|
-
private
|
|
41
|
+
private formatText;
|
|
25
42
|
/**
|
|
26
|
-
*
|
|
43
|
+
* Safe file appending utility
|
|
27
44
|
*/
|
|
28
|
-
private
|
|
45
|
+
private appendToFile;
|
|
46
|
+
/**
|
|
47
|
+
* Unified writer for standard and file streams
|
|
48
|
+
*/
|
|
49
|
+
private log;
|
|
29
50
|
/**
|
|
30
51
|
* Log error message
|
|
31
52
|
*/
|
|
@@ -47,7 +68,7 @@ declare class Logger {
|
|
|
47
68
|
*/
|
|
48
69
|
metric(name: string, value: number, unit?: string): void;
|
|
49
70
|
/**
|
|
50
|
-
* Create child logger with
|
|
71
|
+
* Create child logger with parent context chaining
|
|
51
72
|
*/
|
|
52
73
|
child(context: string): Logger;
|
|
53
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAcD;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;GAEG;AACH,cAAM,MAAM;IACV,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAkB;gBAE5B,OAAO,GAAE,MAAc;IAsBnC;;OAEG;IACH,OAAO,CAAC,aAAa;IAerB;;OAEG;IACH,OAAO,CAAC,UAAU;IAKlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAWpB;;OAEG;IACH,OAAO,CAAC,GAAG;IAkDX;;OAEG;IACI,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,GAAG,GAAG,IAAI;IAIxD;;OAEG;IACI,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAI9C;;OAEG;IACI,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAI9C;;OAEG;IACI,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAI/C;;OAEG;IACI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,MAAa,GAAG,IAAI;IAKrE;;OAEG;IACI,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAGtC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,MAAc,GAAG,MAAM,CAE5D;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,QAAqC,CAAC"}
|
package/dist/esm/utils/logger.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
1
3
|
import { config } from '../config';
|
|
2
4
|
/**
|
|
3
5
|
* Log levels
|
|
@@ -21,12 +23,29 @@ const colors = {
|
|
|
21
23
|
gray: '\x1b[90m',
|
|
22
24
|
};
|
|
23
25
|
/**
|
|
24
|
-
*
|
|
26
|
+
* Enterprise Structured Logger supporting standard console and file output streams.
|
|
25
27
|
*/
|
|
26
28
|
class Logger {
|
|
27
29
|
constructor(context = 'App') {
|
|
30
|
+
this.logFilePath = null;
|
|
31
|
+
this.disableConsole = false;
|
|
28
32
|
this.context = context;
|
|
29
|
-
|
|
33
|
+
// Resolve runtime settings dynamically
|
|
34
|
+
const rawLevel = process.env.LEMMA_LOG_LEVEL || process.env.LOG_LEVEL || config?.logLevel || 'info';
|
|
35
|
+
this.level = this.parseLogLevel(rawLevel);
|
|
36
|
+
this.format = (process.env.LEMMA_LOG_FORMAT || process.env.LOG_FORMAT || 'text').toLowerCase() === 'json' ? 'json' : 'text';
|
|
37
|
+
this.logFilePath = process.env.LEMMA_LOG_FILE || process.env.LOG_FILE || null;
|
|
38
|
+
this.disableConsole = (process.env.LEMMA_LOG_DISABLE_CONSOLE || 'false').toLowerCase() === 'true';
|
|
39
|
+
// Proactively construct base directory for log files if specified
|
|
40
|
+
if (this.logFilePath) {
|
|
41
|
+
try {
|
|
42
|
+
const dir = path.dirname(path.resolve(this.logFilePath));
|
|
43
|
+
if (!fs.existsSync(dir)) {
|
|
44
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch { }
|
|
48
|
+
}
|
|
30
49
|
}
|
|
31
50
|
/**
|
|
32
51
|
* Parse log level from string
|
|
@@ -46,64 +65,110 @@ class Logger {
|
|
|
46
65
|
}
|
|
47
66
|
}
|
|
48
67
|
/**
|
|
49
|
-
* Format
|
|
68
|
+
* Format text log line with color
|
|
50
69
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
70
|
+
formatText(level, message, metaStr, colorCode) {
|
|
71
|
+
const timestamp = new Date().toISOString();
|
|
72
|
+
return `${colorCode}[${timestamp}] [${level}] [${this.context}] ${message}${metaStr}${colors.reset}`;
|
|
53
73
|
}
|
|
54
74
|
/**
|
|
55
|
-
*
|
|
75
|
+
* Safe file appending utility
|
|
56
76
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
77
|
+
appendToFile(entry) {
|
|
78
|
+
if (!this.logFilePath)
|
|
79
|
+
return;
|
|
80
|
+
try {
|
|
81
|
+
const line = this.format === 'json'
|
|
82
|
+
? JSON.stringify(entry)
|
|
83
|
+
: `[${entry.timestamp}] [${entry.level}] [${entry.context}] ${entry.message}${entry.meta ? ' ' + JSON.stringify(entry.meta) : ''}${entry.error ? ' error: ' + entry.error.message + '\n' + (entry.error.stack || '') : ''}`;
|
|
84
|
+
fs.appendFileSync(this.logFilePath, line + '\n', 'utf8');
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Unified writer for standard and file streams
|
|
90
|
+
*/
|
|
91
|
+
log(levelStr, levelVal, message, colorCode, meta, errObj) {
|
|
92
|
+
if (levelVal > this.level)
|
|
93
|
+
return;
|
|
94
|
+
const timestamp = new Date().toISOString();
|
|
95
|
+
const entry = {
|
|
96
|
+
timestamp,
|
|
97
|
+
level: levelStr,
|
|
98
|
+
context: this.context,
|
|
99
|
+
message,
|
|
100
|
+
};
|
|
101
|
+
if (meta !== undefined) {
|
|
102
|
+
entry.meta = meta;
|
|
103
|
+
}
|
|
104
|
+
if (errObj) {
|
|
105
|
+
entry.error = {
|
|
106
|
+
message: errObj instanceof Error ? errObj.message : String(errObj),
|
|
107
|
+
stack: errObj instanceof Error ? errObj.stack : undefined,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Output to Console
|
|
111
|
+
if (!this.disableConsole) {
|
|
112
|
+
if (this.format === 'json') {
|
|
113
|
+
const jsonLine = JSON.stringify(entry);
|
|
114
|
+
if (levelVal === LogLevel.ERROR) {
|
|
115
|
+
console.error(jsonLine);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
console.log(jsonLine);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
const metaStr = meta ? ` ${JSON.stringify(meta)}` : '';
|
|
123
|
+
const colorLine = this.formatText(levelStr, message, metaStr, colorCode);
|
|
124
|
+
if (levelVal === LogLevel.ERROR) {
|
|
125
|
+
console.error(colorLine);
|
|
126
|
+
if (errObj && errObj.stack) {
|
|
127
|
+
console.error(`${colors.red}${errObj.stack}${colors.reset}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log(colorLine);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Write to File Sink
|
|
136
|
+
this.appendToFile(entry);
|
|
61
137
|
}
|
|
62
138
|
/**
|
|
63
139
|
* Log error message
|
|
64
140
|
*/
|
|
65
141
|
error(message, error) {
|
|
66
|
-
|
|
67
|
-
return;
|
|
68
|
-
const meta = error instanceof Error
|
|
69
|
-
? { error: error.message, stack: error.stack }
|
|
70
|
-
: error;
|
|
71
|
-
console.error(`${colors.red}${this.format('ERROR', message, meta)}${colors.reset}`);
|
|
142
|
+
this.log('ERROR', LogLevel.ERROR, message, colors.red, undefined, error);
|
|
72
143
|
}
|
|
73
144
|
/**
|
|
74
145
|
* Log warning message
|
|
75
146
|
*/
|
|
76
147
|
warn(message, meta) {
|
|
77
|
-
|
|
78
|
-
return;
|
|
79
|
-
console.warn(`${colors.yellow}${this.format('WARN', message, meta)}${colors.reset}`);
|
|
148
|
+
this.log('WARN', LogLevel.WARN, message, colors.yellow, meta);
|
|
80
149
|
}
|
|
81
150
|
/**
|
|
82
151
|
* Log info message
|
|
83
152
|
*/
|
|
84
153
|
info(message, meta) {
|
|
85
|
-
|
|
86
|
-
return;
|
|
87
|
-
console.log(`${colors.blue}${this.format('INFO', message, meta)}${colors.reset}`);
|
|
154
|
+
this.log('INFO', LogLevel.INFO, message, colors.blue, meta);
|
|
88
155
|
}
|
|
89
156
|
/**
|
|
90
157
|
* Log debug message
|
|
91
158
|
*/
|
|
92
159
|
debug(message, meta) {
|
|
93
|
-
|
|
94
|
-
return;
|
|
95
|
-
console.log(`${colors.gray}${this.format('DEBUG', message, meta)}${colors.reset}`);
|
|
160
|
+
this.log('DEBUG', LogLevel.DEBUG, message, colors.gray, meta);
|
|
96
161
|
}
|
|
97
162
|
/**
|
|
98
163
|
* Log performance metric
|
|
99
164
|
*/
|
|
100
165
|
metric(name, value, unit = 'ms') {
|
|
101
|
-
if (
|
|
166
|
+
if (LogLevel.INFO > this.level)
|
|
102
167
|
return;
|
|
103
|
-
|
|
168
|
+
this.log('METRIC', LogLevel.INFO, `${name}: ${value}${unit}`, colors.cyan);
|
|
104
169
|
}
|
|
105
170
|
/**
|
|
106
|
-
* Create child logger with
|
|
171
|
+
* Create child logger with parent context chaining
|
|
107
172
|
*/
|
|
108
173
|
child(context) {
|
|
109
174
|
return new Logger(`${this.context}:${context}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC;;GAEG;AACH,MAAM,CAAN,IAAY,QAKX;AALD,WAAY,QAAQ;IAClB,yCAAS,CAAA;IACT,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,yCAAS,CAAA;AACX,CAAC,EALW,QAAQ,KAAR,QAAQ,QAKnB;AAED;;GAEG;AACH,MAAM,MAAM,GAAG;IACb,KAAK,EAAE,SAAS;IAChB,GAAG,EAAE,UAAU;IACf,MAAM,EAAE,UAAU;IAClB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;CACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* reportSavings — Fire-and-forget helper to report token savings to the proxy's SavingsLedger.
|
|
3
|
+
*
|
|
4
|
+
* Used by processes that run separately from the proxy (e.g., MCP server, CLI tools).
|
|
5
|
+
* The proxy accumulates all savings in its in-memory SavingsLedger and serves them to the dashboard.
|
|
6
|
+
*/
|
|
7
|
+
type SavingsSource = 'clipboard' | 'contextSqueeze' | 'historyPrune' | 'complexityRouting' | 'cache';
|
|
8
|
+
interface ReportByChars {
|
|
9
|
+
source: SavingsSource;
|
|
10
|
+
charsBefore: number;
|
|
11
|
+
charsAfter: number;
|
|
12
|
+
}
|
|
13
|
+
interface ReportByTokens {
|
|
14
|
+
source: SavingsSource;
|
|
15
|
+
tokens: number;
|
|
16
|
+
}
|
|
17
|
+
type ReportPayload = ReportByChars | ReportByTokens;
|
|
18
|
+
/**
|
|
19
|
+
* Report savings to the proxy's SavingsLedger via HTTP POST.
|
|
20
|
+
* Fire-and-forget — never throws, never blocks.
|
|
21
|
+
*/
|
|
22
|
+
export declare function reportSavings(payload: ReportPayload): void;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=reportSavings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reportSavings.d.ts","sourceRoot":"","sources":["../../../src/utils/reportSavings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,KAAK,aAAa,GAAG,WAAW,GAAG,gBAAgB,GAAG,cAAc,GAAG,mBAAmB,GAAG,OAAO,CAAC;AAErG,UAAU,aAAa;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,cAAc;IACtB,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,aAAa,GAAG,aAAa,GAAG,cAAc,CAAC;AAapD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAsB1D"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* reportSavings — Fire-and-forget helper to report token savings to the proxy's SavingsLedger.
|
|
3
|
+
*
|
|
4
|
+
* Used by processes that run separately from the proxy (e.g., MCP server, CLI tools).
|
|
5
|
+
* The proxy accumulates all savings in its in-memory SavingsLedger and serves them to the dashboard.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import http from 'http';
|
|
10
|
+
function getProxyPort() {
|
|
11
|
+
try {
|
|
12
|
+
const HOME = process.env.HOME || process.env.USERPROFILE || '~';
|
|
13
|
+
const portFile = path.join(HOME, '.lemma-cache/proxy.port');
|
|
14
|
+
if (fs.existsSync(portFile)) {
|
|
15
|
+
return fs.readFileSync(portFile, 'utf8').trim();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch { }
|
|
19
|
+
return '8081';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Report savings to the proxy's SavingsLedger via HTTP POST.
|
|
23
|
+
* Fire-and-forget — never throws, never blocks.
|
|
24
|
+
*/
|
|
25
|
+
export function reportSavings(payload) {
|
|
26
|
+
try {
|
|
27
|
+
const port = getProxyPort();
|
|
28
|
+
const body = JSON.stringify(payload);
|
|
29
|
+
const req = http.request({
|
|
30
|
+
hostname: '127.0.0.1',
|
|
31
|
+
port: parseInt(port),
|
|
32
|
+
path: '/api/savings-record',
|
|
33
|
+
method: 'POST',
|
|
34
|
+
headers: {
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
'Content-Length': Buffer.byteLength(body),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
req.on('error', () => { }); // Silently ignore if proxy isn't running
|
|
40
|
+
req.write(body);
|
|
41
|
+
req.end();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Never throw — savings reporting is non-critical
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=reportSavings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reportSavings.js","sourceRoot":"","sources":["../../../src/utils/reportSavings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,MAAM,CAAC;AAiBxB,SAAS,YAAY;IACnB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC;QAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;QAC5D,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAAsB;IAClD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAErC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC;YACvB,QAAQ,EAAE,WAAW;YACrB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;YACpB,IAAI,EAAE,qBAAqB;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;aAC1C;SACF,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,yCAAyC;QACpE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChB,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;IACpD,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxuss/lemma",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Intelligent AI Gateway for IDEs & Agents — Semantic cache, Privacy Firewall, and Autonomous Cost-Optimization.",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -102,37 +102,40 @@
|
|
|
102
102
|
"dev": "npx tsx start-dev.ts",
|
|
103
103
|
"start": "node dist/cjs/index.js",
|
|
104
104
|
"test": "jest",
|
|
105
|
+
"type-check": "tsc --noEmit",
|
|
106
|
+
"format": "prettier --check 'src/**/*.ts' 'tests/**/*.ts' 'examples/**/*.ts' 'scripts/**/*.ts'",
|
|
107
|
+
"format:fix": "prettier --write 'src/**/*.ts' 'tests/**/*.ts' 'examples/**/*.ts' 'scripts/**/*.ts'",
|
|
105
108
|
"lint": "eslint src/**/*.ts",
|
|
106
109
|
"clean": "rm -rf dist sdks/langchain/dist sdks/crewai/dist",
|
|
107
110
|
"prepublishOnly": "npm run clean && npm run build && npm test",
|
|
108
111
|
"cloud:start": "node dist/cjs/cloud/server.js",
|
|
109
|
-
"cloud:dev": "
|
|
110
|
-
"demo": "
|
|
111
|
-
"demo:comparison": "
|
|
112
|
-
"example:simple": "
|
|
113
|
-
"example:swarm": "
|
|
114
|
-
"example:secure": "
|
|
115
|
-
"example:langchain": "
|
|
116
|
-
"example:crewai": "
|
|
117
|
-
"example:speculative": "
|
|
118
|
-
"example:consensus": "
|
|
119
|
-
"example:semantic": "
|
|
120
|
-
"test:quick": "
|
|
121
|
-
"test:real:ollama:1min": "
|
|
122
|
-
"test:real:ollama": "
|
|
123
|
-
"test:real:1min": "
|
|
124
|
-
"test:real:openai": "
|
|
125
|
-
"test:real:anthropic": "
|
|
126
|
-
"test:real:multi-agent": "
|
|
112
|
+
"cloud:dev": "npx tsx src/cloud/server.ts",
|
|
113
|
+
"demo": "npx tsx examples/demo-visual.ts",
|
|
114
|
+
"demo:comparison": "npx tsx examples/demo-comparison.ts",
|
|
115
|
+
"example:simple": "npx tsx examples/simple-agent.ts",
|
|
116
|
+
"example:swarm": "npx tsx examples/agent-swarm.ts",
|
|
117
|
+
"example:secure": "npx tsx examples/secure-agent.ts",
|
|
118
|
+
"example:langchain": "npx tsx examples/langchain-example.ts",
|
|
119
|
+
"example:crewai": "npx tsx examples/crewai-example.ts",
|
|
120
|
+
"example:speculative": "npx tsx examples/phase3-speculative.ts",
|
|
121
|
+
"example:consensus": "npx tsx examples/phase3-consensus.ts",
|
|
122
|
+
"example:semantic": "npx tsx examples/semantic-cache-demo.ts",
|
|
123
|
+
"test:quick": "npx tsx examples/quick-test.ts",
|
|
124
|
+
"test:real:ollama:1min": "npx tsx examples/real-world-ollama-1min.ts",
|
|
125
|
+
"test:real:ollama": "npx tsx examples/real-world-ollama.ts",
|
|
126
|
+
"test:real:1min": "npx tsx examples/real-world-1min.ts",
|
|
127
|
+
"test:real:openai": "npx tsx examples/real-world-openai.ts",
|
|
128
|
+
"test:real:anthropic": "npx tsx examples/real-world-anthropic.ts",
|
|
129
|
+
"test:real:multi-agent": "npx tsx examples/real-world-multi-agent.ts",
|
|
127
130
|
"dashboard": "cd dashboard && npm run dev",
|
|
128
131
|
"dashboard:build": "cd dashboard && npm run build",
|
|
129
132
|
"stack:all": "bash scripts/launch-all.sh",
|
|
130
133
|
"sdk:langchain:build": "cd sdks/langchain && npm run build",
|
|
131
134
|
"sdk:crewai:build": "cd sdks/crewai && npm run build",
|
|
132
135
|
"sdk:build": "npm run sdk:langchain:build && npm run sdk:crewai:build",
|
|
133
|
-
"keys:generate": "
|
|
134
|
-
"keys:list": "
|
|
135
|
-
"keys:revoke": "
|
|
136
|
+
"keys:generate": "npx tsx scripts/manage-keys.ts generate",
|
|
137
|
+
"keys:list": "npx tsx scripts/manage-keys.ts list",
|
|
138
|
+
"keys:revoke": "npx tsx scripts/manage-keys.ts revoke"
|
|
136
139
|
},
|
|
137
140
|
"keywords": [
|
|
138
141
|
"semantic-cache",
|
|
@@ -162,8 +165,6 @@
|
|
|
162
165
|
"dependencies": {
|
|
163
166
|
"@chroma-core/default-embed": "^0.1.9",
|
|
164
167
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
165
|
-
"@nxuss/lemma": "^0.5.1",
|
|
166
|
-
"@types/cors": "^2.8.19",
|
|
167
168
|
"axios": "^1.6.0",
|
|
168
169
|
"commander": "^14.0.3",
|
|
169
170
|
"cors": "^2.8.6",
|
|
@@ -180,6 +181,7 @@
|
|
|
180
181
|
"ws": "^8.16.0"
|
|
181
182
|
},
|
|
182
183
|
"devDependencies": {
|
|
184
|
+
"@types/cors": "^2.8.19",
|
|
183
185
|
"@types/express": "^4.17.21",
|
|
184
186
|
"@types/jest": "^29.5.11",
|
|
185
187
|
"@types/node": "^20.11.0",
|
|
@@ -187,6 +189,7 @@
|
|
|
187
189
|
"@types/uuid": "^10.0.0",
|
|
188
190
|
"@types/ws": "^8.5.10",
|
|
189
191
|
"jest": "^29.7.0",
|
|
192
|
+
"prettier": "^3.0.0",
|
|
190
193
|
"ts-jest": "^29.1.1",
|
|
191
194
|
"ts-node": "^10.9.2",
|
|
192
195
|
"typescript": "^5.3.3"
|