@nxuss/lemma 0.1.0
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/LICENSE +21 -0
- package/README.md +311 -0
- package/dist/cloud/KeyManager.d.ts +29 -0
- package/dist/cloud/KeyManager.d.ts.map +1 -0
- package/dist/cloud/KeyManager.js +142 -0
- package/dist/cloud/KeyManager.js.map +1 -0
- package/dist/cloud/TenantCache.d.ts +29 -0
- package/dist/cloud/TenantCache.d.ts.map +1 -0
- package/dist/cloud/TenantCache.js +162 -0
- package/dist/cloud/TenantCache.js.map +1 -0
- package/dist/cloud/index.d.ts +4 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +23 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/cloud/server.d.ts +17 -0
- package/dist/cloud/server.d.ts.map +1 -0
- package/dist/cloud/server.js +189 -0
- package/dist/cloud/server.js.map +1 -0
- package/dist/cloud/types.d.ts +35 -0
- package/dist/cloud/types.d.ts.map +1 -0
- package/dist/cloud/types.js +14 -0
- package/dist/cloud/types.js.map +1 -0
- package/dist/config/index.d.ts +44 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +161 -0
- package/dist/config/index.js.map +1 -0
- package/dist/consensus/ConsensusEngine.d.ts +119 -0
- package/dist/consensus/ConsensusEngine.d.ts.map +1 -0
- package/dist/consensus/ConsensusEngine.js +314 -0
- package/dist/consensus/ConsensusEngine.js.map +1 -0
- package/dist/consensus/ModelPool.d.ts +103 -0
- package/dist/consensus/ModelPool.d.ts.map +1 -0
- package/dist/consensus/ModelPool.js +276 -0
- package/dist/consensus/ModelPool.js.map +1 -0
- package/dist/consensus/index.d.ts +8 -0
- package/dist/consensus/index.d.ts.map +1 -0
- package/dist/consensus/index.js +13 -0
- package/dist/consensus/index.js.map +1 -0
- package/dist/core/AgentRegistry.d.ts +89 -0
- package/dist/core/AgentRegistry.d.ts.map +1 -0
- package/dist/core/AgentRegistry.js +264 -0
- package/dist/core/AgentRegistry.js.map +1 -0
- package/dist/core/DashboardBroadcaster.d.ts +67 -0
- package/dist/core/DashboardBroadcaster.d.ts.map +1 -0
- package/dist/core/DashboardBroadcaster.js +264 -0
- package/dist/core/DashboardBroadcaster.js.map +1 -0
- package/dist/core/OrchestrationEngine.d.ts +84 -0
- package/dist/core/OrchestrationEngine.d.ts.map +1 -0
- package/dist/core/OrchestrationEngine.js +455 -0
- package/dist/core/OrchestrationEngine.js.map +1 -0
- package/dist/core/SubconsciousEngine.d.ts +53 -0
- package/dist/core/SubconsciousEngine.d.ts.map +1 -0
- package/dist/core/SubconsciousEngine.js +273 -0
- package/dist/core/SubconsciousEngine.js.map +1 -0
- package/dist/core/WebSocketServer.d.ts +89 -0
- package/dist/core/WebSocketServer.d.ts.map +1 -0
- package/dist/core/WebSocketServer.js +416 -0
- package/dist/core/WebSocketServer.js.map +1 -0
- package/dist/core/index.d.ts +15 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +24 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/router.d.ts +105 -0
- package/dist/core/router.d.ts.map +1 -0
- package/dist/core/router.js +420 -0
- package/dist/core/router.js.map +1 -0
- package/dist/embed/index.d.ts +153 -0
- package/dist/embed/index.d.ts.map +1 -0
- package/dist/embed/index.js +408 -0
- package/dist/embed/index.js.map +1 -0
- package/dist/embed.d.ts +11 -0
- package/dist/embed.d.ts.map +1 -0
- package/dist/embed.js +19 -0
- package/dist/embed.js.map +1 -0
- package/dist/index.d.ts +83 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +176 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/flows.d.ts +126 -0
- package/dist/protocol/flows.d.ts.map +1 -0
- package/dist/protocol/flows.js +347 -0
- package/dist/protocol/flows.js.map +1 -0
- package/dist/protocol/iap.d.ts +54 -0
- package/dist/protocol/iap.d.ts.map +1 -0
- package/dist/protocol/iap.js +108 -0
- package/dist/protocol/iap.js.map +1 -0
- package/dist/protocol/index.d.ts +23 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +45 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/types.d.ts +332 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/types.js +57 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/protocol/utils.d.ts +130 -0
- package/dist/protocol/utils.d.ts.map +1 -0
- package/dist/protocol/utils.js +292 -0
- package/dist/protocol/utils.js.map +1 -0
- package/dist/protocol/validators.d.ts +54 -0
- package/dist/protocol/validators.d.ts.map +1 -0
- package/dist/protocol/validators.js +344 -0
- package/dist/protocol/validators.js.map +1 -0
- package/dist/security/AuthManager.d.ts +73 -0
- package/dist/security/AuthManager.d.ts.map +1 -0
- package/dist/security/AuthManager.js +102 -0
- package/dist/security/AuthManager.js.map +1 -0
- package/dist/security/MessageSanitizer.d.ts +51 -0
- package/dist/security/MessageSanitizer.d.ts.map +1 -0
- package/dist/security/MessageSanitizer.js +166 -0
- package/dist/security/MessageSanitizer.js.map +1 -0
- package/dist/security/RateLimiter.d.ts +46 -0
- package/dist/security/RateLimiter.d.ts.map +1 -0
- package/dist/security/RateLimiter.js +133 -0
- package/dist/security/RateLimiter.js.map +1 -0
- package/dist/security/SecurityMiddleware.d.ts +88 -0
- package/dist/security/SecurityMiddleware.d.ts.map +1 -0
- package/dist/security/SecurityMiddleware.js +146 -0
- package/dist/security/SecurityMiddleware.js.map +1 -0
- package/dist/security/index.d.ts +35 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +42 -0
- package/dist/security/index.js.map +1 -0
- package/dist/speculative/PredictionEngine.d.ts +99 -0
- package/dist/speculative/PredictionEngine.d.ts.map +1 -0
- package/dist/speculative/PredictionEngine.js +291 -0
- package/dist/speculative/PredictionEngine.js.map +1 -0
- package/dist/speculative/SpeculativeCache.d.ts +117 -0
- package/dist/speculative/SpeculativeCache.d.ts.map +1 -0
- package/dist/speculative/SpeculativeCache.js +292 -0
- package/dist/speculative/SpeculativeCache.js.map +1 -0
- package/dist/speculative/SpeculativeEngine.d.ts +114 -0
- package/dist/speculative/SpeculativeEngine.d.ts.map +1 -0
- package/dist/speculative/SpeculativeEngine.js +244 -0
- package/dist/speculative/SpeculativeEngine.js.map +1 -0
- package/dist/speculative/WorkerPool.d.ts +109 -0
- package/dist/speculative/WorkerPool.d.ts.map +1 -0
- package/dist/speculative/WorkerPool.js +327 -0
- package/dist/speculative/WorkerPool.js.map +1 -0
- package/dist/speculative/index.d.ts +10 -0
- package/dist/speculative/index.d.ts.map +1 -0
- package/dist/speculative/index.js +17 -0
- package/dist/speculative/index.js.map +1 -0
- package/dist/subconscious/EmbeddingService.d.ts +73 -0
- package/dist/subconscious/EmbeddingService.d.ts.map +1 -0
- package/dist/subconscious/EmbeddingService.js +196 -0
- package/dist/subconscious/EmbeddingService.js.map +1 -0
- package/dist/subconscious/SemanticCache.d.ts +82 -0
- package/dist/subconscious/SemanticCache.d.ts.map +1 -0
- package/dist/subconscious/SemanticCache.js +164 -0
- package/dist/subconscious/SemanticCache.js.map +1 -0
- package/dist/subconscious/SubconsciousEngine.d.ts +121 -0
- package/dist/subconscious/SubconsciousEngine.d.ts.map +1 -0
- package/dist/subconscious/SubconsciousEngine.js +241 -0
- package/dist/subconscious/SubconsciousEngine.js.map +1 -0
- package/dist/subconscious/VectorStore.d.ts +54 -0
- package/dist/subconscious/VectorStore.d.ts.map +1 -0
- package/dist/subconscious/VectorStore.js +168 -0
- package/dist/subconscious/VectorStore.js.map +1 -0
- package/dist/subconscious/cache.d.ts +34 -0
- package/dist/subconscious/cache.d.ts.map +1 -0
- package/dist/subconscious/cache.js +156 -0
- package/dist/subconscious/cache.js.map +1 -0
- package/dist/subconscious/embeddings.d.ts +25 -0
- package/dist/subconscious/embeddings.d.ts.map +1 -0
- package/dist/subconscious/embeddings.js +65 -0
- package/dist/subconscious/embeddings.js.map +1 -0
- package/dist/subconscious/index.d.ts +12 -0
- package/dist/subconscious/index.d.ts.map +1 -0
- package/dist/subconscious/index.js +19 -0
- package/dist/subconscious/index.js.map +1 -0
- package/dist/types/index.d.ts +286 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +43 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +63 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +126 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +99 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nxus Studio
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# Lemma
|
|
2
|
+
|
|
3
|
+
**Stop paying for the same LLM call twice.**
|
|
4
|
+
|
|
5
|
+
Lemma is a semantic cache for AI apps. It recognizes when two prompts mean the same thing and returns the cached response — no LLM call, no cost, no wait.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { Lemma } from 'lemma/embed';
|
|
9
|
+
|
|
10
|
+
const lemma = await Lemma.create();
|
|
11
|
+
const ask = lemma.wrap(yourLLMFunction);
|
|
12
|
+
|
|
13
|
+
await ask('chicken and rice recipes'); // → calls your LLM, ~2s
|
|
14
|
+
await ask('rice with chicken ideas'); // → ⚡ cache hit, 0ms, $0
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## The problem
|
|
20
|
+
|
|
21
|
+
Every AI app has the same leak: users ask the same questions in different ways, and you pay full price every time.
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
1,000 users ask about "chicken recipes" → 1,000 LLM calls → $60/day
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Lemma understands that *"chicken and rice"*, *"rice with chicken"*, and *"what can I make with chicken and rice?"* are the same question. One LLM call. 999 cache hits.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
1,000 users ask about "chicken recipes" → 1 LLM call + 999 cache hits → $4/day
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install lemma
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
No config. No server. No Docker. Works in any Node.js project.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Quick start
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { Lemma } from 'lemma/embed';
|
|
49
|
+
|
|
50
|
+
const lemma = await Lemma.create();
|
|
51
|
+
|
|
52
|
+
const getAnswer = lemma.wrap(async (question: string) => {
|
|
53
|
+
return await llm.chat.completions.create({
|
|
54
|
+
model: 'gpt-4o-mini',
|
|
55
|
+
messages: [{ role: 'user', content: question }],
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const r1 = await getAnswer('what is the capital of France?');
|
|
60
|
+
console.log(r1.fromCache); // false — first call
|
|
61
|
+
|
|
62
|
+
const r2 = await getAnswer('capital city of France?');
|
|
63
|
+
console.log(r2.fromCache); // true — ⚡ 0ms, $0
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Drop into an existing Express app
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// Before — every request hits your LLM
|
|
70
|
+
app.post('/api/chat', async (req, res) => {
|
|
71
|
+
const response = await llm.chat.completions.create({ ... });
|
|
72
|
+
res.json(response);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// After — 3 lines changed, 70% fewer LLM calls
|
|
76
|
+
import { Lemma } from 'lemma/embed';
|
|
77
|
+
const lemma = await Lemma.create();
|
|
78
|
+
const cachedChat = lemma.wrap((msg: string) => llm.chat.completions.create({ ... }));
|
|
79
|
+
|
|
80
|
+
app.post('/api/chat', async (req, res) => {
|
|
81
|
+
const result = await cachedChat(req.body.message);
|
|
82
|
+
res.json(result.data);
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Storage modes
|
|
89
|
+
|
|
90
|
+
### `memory` — Zero dependencies (default)
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const lemma = await Lemma.create();
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- In-process, no external services
|
|
97
|
+
- Exact string matching (normalized)
|
|
98
|
+
- Resets on restart
|
|
99
|
+
- Best for: development, low-traffic apps, getting started
|
|
100
|
+
|
|
101
|
+
### `chroma` — Persistent semantic cache
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const lemma = await Lemma.create({
|
|
105
|
+
storage: 'chroma',
|
|
106
|
+
threshold: 0.90,
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
- Persists across restarts
|
|
111
|
+
- True semantic matching via vector embeddings — catches paraphrases, typos, language variations
|
|
112
|
+
- Requires ChromaDB + Ollama running locally
|
|
113
|
+
- Best for: production apps where users rephrase the same questions
|
|
114
|
+
|
|
115
|
+
> **Note:** The "chicken and rice" → "rice with chicken" magic only works in `chroma` mode.
|
|
116
|
+
> Memory mode does exact normalized matching only.
|
|
117
|
+
|
|
118
|
+
### `cloud` — Managed, zero infra
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
const lemma = await Lemma.create({
|
|
122
|
+
storage: 'cloud',
|
|
123
|
+
apiKey: 'lk_live_your_key_here',
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- No ChromaDB, no Ollama, no servers
|
|
128
|
+
- Persistent semantic cache hosted for you
|
|
129
|
+
- Works in serverless (Vercel, AWS Lambda, Cloudflare Workers)
|
|
130
|
+
- Get your key at [lemma.dev](https://lemma.dev)
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## API
|
|
135
|
+
|
|
136
|
+
### `Lemma.create(config?)`
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const lemma = await Lemma.create({
|
|
140
|
+
storage: 'memory' | 'chroma' | 'cloud', // default: 'memory'
|
|
141
|
+
threshold: 0.92, // similarity cutoff (0–1)
|
|
142
|
+
apiKey: 'lk_live_...', // required for cloud mode
|
|
143
|
+
debug: false, // log hits/misses
|
|
144
|
+
ttl: 0, // cache TTL in ms (0 = forever)
|
|
145
|
+
maxSize: 10000, // max entries (memory mode)
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### `lemma.wrap(fn)`
|
|
150
|
+
|
|
151
|
+
Wraps any async function. Uses the first argument as the cache key.
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const cached = lemma.wrap(async (input: string, ...rest) => {
|
|
155
|
+
return await someExpensiveCall(input, ...rest);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const result = await cached('my query');
|
|
159
|
+
// result.data — the actual response
|
|
160
|
+
// result.fromCache — true if served from cache
|
|
161
|
+
// result.similarity — how similar to the cached entry (0–1)
|
|
162
|
+
// result.latencyMs — total time including cache lookup
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### `lemma.run(input, fn)`
|
|
166
|
+
|
|
167
|
+
Manual control — check cache first, run function on miss.
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
const result = await lemma.run(
|
|
171
|
+
userMessage,
|
|
172
|
+
() => llm.chat.completions.create({ ... })
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
if (result.fromCache) {
|
|
176
|
+
console.log(`Saved an API call! Similarity: ${result.similarity}`);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### `lemma.get(input)` / `lemma.set(input, data)`
|
|
181
|
+
|
|
182
|
+
Direct cache access.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
const cached = await lemma.get('what is machine learning?');
|
|
186
|
+
if (!cached) {
|
|
187
|
+
const data = await callYourLLM(...);
|
|
188
|
+
await lemma.set('what is machine learning?', data);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### `lemma.getMetrics()`
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
const metrics = lemma.getMetrics();
|
|
196
|
+
// {
|
|
197
|
+
// hits: 847,
|
|
198
|
+
// misses: 153,
|
|
199
|
+
// total: 1000,
|
|
200
|
+
// hitRate: 0.847,
|
|
201
|
+
// avgLatencyMs: 12,
|
|
202
|
+
// cacheSize: 153
|
|
203
|
+
// }
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Who this is for
|
|
209
|
+
|
|
210
|
+
Lemma pays off fast if your app has any of these:
|
|
211
|
+
|
|
212
|
+
- **Repetitive user queries** — support bots, FAQ assistants, recipe/travel/fitness apps. Users ask the same things in different words constantly.
|
|
213
|
+
- **Multiple services calling the same LLM** — if 3 microservices independently ask similar questions, you're paying 3x. Lemma centralizes the cache.
|
|
214
|
+
- **LangChain or CrewAI pipelines** — agents in a pipeline often re-derive the same context. Lemma short-circuits that.
|
|
215
|
+
- **High-volume, cost-sensitive apps** — if your LLM bill is already noticeable, the ROI is immediate.
|
|
216
|
+
|
|
217
|
+
### Real hit rates by app type
|
|
218
|
+
|
|
219
|
+
| App type | Avg hit rate | Savings on 50k req/mo |
|
|
220
|
+
|---|---|---|
|
|
221
|
+
| Customer support chatbot | 85% | ~$340/mo |
|
|
222
|
+
| Recipe / food suggestions | 78% | ~$180/mo |
|
|
223
|
+
| Location / places search | 82% | ~$290/mo |
|
|
224
|
+
| Code assistant | 65% | ~$120/mo |
|
|
225
|
+
|
|
226
|
+
*Based on gpt-4o-mini pricing at $0.002/1k tokens, avg 800 tokens/request.*
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## For teams building multi-agent systems
|
|
231
|
+
|
|
232
|
+
If you're past the single-app use case and building systems where multiple AI agents collaborate, Lemma ships a full orchestration layer on top of the cache.
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
import { SubconsciousHub } from 'lemma';
|
|
236
|
+
|
|
237
|
+
const hub = new SubconsciousHub({ server: { port: 8080 } });
|
|
238
|
+
await hub.start();
|
|
239
|
+
// Agents connect via WebSocket and share a semantic cache
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
What this adds:
|
|
243
|
+
|
|
244
|
+
- **WebSocket server** — persistent agent connections with heartbeat
|
|
245
|
+
- **Agent registry** — dynamic capability discovery and routing
|
|
246
|
+
- **Shared semantic cache** — all agents benefit from each other's work
|
|
247
|
+
- **Consensus engine** — multi-model voting for high-stakes decisions
|
|
248
|
+
- **Speculative execution** — pre-compute likely next requests
|
|
249
|
+
- **Security middleware** — API key auth, rate limiting, message sanitization
|
|
250
|
+
|
|
251
|
+
This layer is designed for teams already running LangChain, CrewAI, or custom agent frameworks who need coordination and shared memory across agents. See [docs/](./docs/) for the full architecture guide.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Self-hosting the cloud server
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# 1. Build
|
|
259
|
+
npm run build
|
|
260
|
+
|
|
261
|
+
# 2. Deploy to any VPS
|
|
262
|
+
./scripts/deploy-cloud.sh YOUR_SERVER_IP
|
|
263
|
+
|
|
264
|
+
# 3. Generate an API key
|
|
265
|
+
curl -X POST http://YOUR_SERVER_IP:3100/admin/keys \
|
|
266
|
+
-H 'X-Admin-Secret: YOUR_ADMIN_SECRET' \
|
|
267
|
+
-H 'Content-Type: application/json' \
|
|
268
|
+
-d '{"tenantId": "user1", "name": "My Project", "plan": "pro"}'
|
|
269
|
+
|
|
270
|
+
# 4. Use it
|
|
271
|
+
const lemma = await Lemma.create({
|
|
272
|
+
storage: 'cloud',
|
|
273
|
+
apiKey: 'lk_live_...',
|
|
274
|
+
cloudUrl: 'http://YOUR_SERVER_IP:3100',
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Requirements: Docker, ChromaDB, Ollama with `nomic-embed-text`.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Pricing
|
|
283
|
+
|
|
284
|
+
| | Free | Pro | Scale |
|
|
285
|
+
|---|---|---|---|
|
|
286
|
+
| Requests/day | 1,000 | 100,000 | Unlimited |
|
|
287
|
+
| Semantic matching | ✅ | ✅ | ✅ |
|
|
288
|
+
| Persistent cache | ✅ | ✅ | ✅ |
|
|
289
|
+
| Savings dashboard | ✅ | ✅ | ✅ |
|
|
290
|
+
| Price | $0 | $29/mo | $99/mo |
|
|
291
|
+
|
|
292
|
+
[Get your API key →](https://lemma.dev)
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Contributing
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
git clone https://github.com/Nxusbets/lemma.git
|
|
300
|
+
cd lemma
|
|
301
|
+
npm install
|
|
302
|
+
npm run build # compile TypeScript
|
|
303
|
+
npm test # run tests
|
|
304
|
+
npm run dev # start the orchestration server
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## License
|
|
310
|
+
|
|
311
|
+
MIT © [Nxus Studio](https://github.com/Nxusbets)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lemma Cloud — API Key Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles key generation, validation, usage tracking, and plan enforcement.
|
|
5
|
+
* Uses a JSON file as storage (swap for Redis/Postgres in production).
|
|
6
|
+
*/
|
|
7
|
+
import { ApiKey } from './types';
|
|
8
|
+
export declare class KeyManager {
|
|
9
|
+
private keys;
|
|
10
|
+
private storePath;
|
|
11
|
+
private saveTimer;
|
|
12
|
+
constructor(storePath?: string);
|
|
13
|
+
generate(tenantId: string, name: string, plan?: ApiKey['plan']): ApiKey;
|
|
14
|
+
validate(keyId: string): {
|
|
15
|
+
valid: boolean;
|
|
16
|
+
key?: ApiKey;
|
|
17
|
+
reason?: string;
|
|
18
|
+
};
|
|
19
|
+
recordRequest(keyId: string): void;
|
|
20
|
+
upgradePlan(keyId: string, plan: ApiKey['plan']): boolean;
|
|
21
|
+
revoke(keyId: string): boolean;
|
|
22
|
+
getByTenant(tenantId: string): ApiKey[];
|
|
23
|
+
get(keyId: string): ApiKey | undefined;
|
|
24
|
+
private maybeResetDaily;
|
|
25
|
+
private scheduleSave;
|
|
26
|
+
private save;
|
|
27
|
+
private load;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=KeyManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeyManager.d.ts","sourceRoot":"","sources":["../../src/cloud/KeyManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,MAAM,EAAe,MAAM,SAAS,CAAC;AAE9C,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAA+B;gBAEpC,SAAS,SAAqB;IAO1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,CAAU,GAAG,MAAM;IAkB/E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IA4B1E,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUlC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO;IAQzD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAQ9B,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAIvC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAMtC,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,IAAI;IAWZ,OAAO,CAAC,IAAI;CAYb"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Lemma Cloud — API Key Manager
|
|
4
|
+
*
|
|
5
|
+
* Handles key generation, validation, usage tracking, and plan enforcement.
|
|
6
|
+
* Uses a JSON file as storage (swap for Redis/Postgres in production).
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.KeyManager = void 0;
|
|
13
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
14
|
+
const fs_1 = __importDefault(require("fs"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const types_1 = require("./types");
|
|
17
|
+
class KeyManager {
|
|
18
|
+
constructor(storePath = './data/keys.json') {
|
|
19
|
+
this.keys = new Map();
|
|
20
|
+
this.saveTimer = null;
|
|
21
|
+
this.storePath = storePath;
|
|
22
|
+
this.load();
|
|
23
|
+
}
|
|
24
|
+
// ─── Key Generation ─────────────────────────────────────────────────────────
|
|
25
|
+
generate(tenantId, name, plan = 'free') {
|
|
26
|
+
const id = `lk_${plan === 'free' ? 'free' : 'live'}_${crypto_1.default.randomBytes(16).toString('hex')}`;
|
|
27
|
+
const key = {
|
|
28
|
+
id,
|
|
29
|
+
tenantId,
|
|
30
|
+
name,
|
|
31
|
+
plan,
|
|
32
|
+
createdAt: Date.now(),
|
|
33
|
+
active: true,
|
|
34
|
+
usage: { today: 0, total: 0, lastReset: Date.now() },
|
|
35
|
+
};
|
|
36
|
+
this.keys.set(id, key);
|
|
37
|
+
this.scheduleSave();
|
|
38
|
+
return key;
|
|
39
|
+
}
|
|
40
|
+
// ─── Validation ─────────────────────────────────────────────────────────────
|
|
41
|
+
validate(keyId) {
|
|
42
|
+
const key = this.keys.get(keyId);
|
|
43
|
+
if (!key)
|
|
44
|
+
return { valid: false, reason: 'Invalid API key' };
|
|
45
|
+
if (!key.active)
|
|
46
|
+
return { valid: false, reason: 'API key is suspended' };
|
|
47
|
+
if (key.expiresAt && Date.now() > key.expiresAt) {
|
|
48
|
+
return { valid: false, reason: 'API key has expired' };
|
|
49
|
+
}
|
|
50
|
+
// Reset daily counter if needed
|
|
51
|
+
this.maybeResetDaily(key);
|
|
52
|
+
// Check plan limits
|
|
53
|
+
const limits = types_1.PLAN_LIMITS[key.plan];
|
|
54
|
+
if (key.usage.today >= limits.dailyRequests) {
|
|
55
|
+
return {
|
|
56
|
+
valid: false,
|
|
57
|
+
reason: key.plan === 'free'
|
|
58
|
+
? 'Free tier limit reached (1,000 req/day). Upgrade at https://lemma.dev'
|
|
59
|
+
: 'Daily request limit reached. Contact support to increase limits.',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { valid: true, key };
|
|
63
|
+
}
|
|
64
|
+
// ─── Usage Tracking ─────────────────────────────────────────────────────────
|
|
65
|
+
recordRequest(keyId) {
|
|
66
|
+
const key = this.keys.get(keyId);
|
|
67
|
+
if (!key)
|
|
68
|
+
return;
|
|
69
|
+
key.usage.today++;
|
|
70
|
+
key.usage.total++;
|
|
71
|
+
this.scheduleSave();
|
|
72
|
+
}
|
|
73
|
+
// ─── Plan Management ────────────────────────────────────────────────────────
|
|
74
|
+
upgradePlan(keyId, plan) {
|
|
75
|
+
const key = this.keys.get(keyId);
|
|
76
|
+
if (!key)
|
|
77
|
+
return false;
|
|
78
|
+
key.plan = plan;
|
|
79
|
+
this.scheduleSave();
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
revoke(keyId) {
|
|
83
|
+
const key = this.keys.get(keyId);
|
|
84
|
+
if (!key)
|
|
85
|
+
return false;
|
|
86
|
+
key.active = false;
|
|
87
|
+
this.scheduleSave();
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
getByTenant(tenantId) {
|
|
91
|
+
return Array.from(this.keys.values()).filter(k => k.tenantId === tenantId);
|
|
92
|
+
}
|
|
93
|
+
get(keyId) {
|
|
94
|
+
return this.keys.get(keyId);
|
|
95
|
+
}
|
|
96
|
+
// ─── Persistence ────────────────────────────────────────────────────────────
|
|
97
|
+
maybeResetDaily(key) {
|
|
98
|
+
const now = Date.now();
|
|
99
|
+
const midnight = new Date();
|
|
100
|
+
midnight.setUTCHours(0, 0, 0, 0);
|
|
101
|
+
if (key.usage.lastReset < midnight.getTime()) {
|
|
102
|
+
key.usage.today = 0;
|
|
103
|
+
key.usage.lastReset = now;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
scheduleSave() {
|
|
107
|
+
if (this.saveTimer)
|
|
108
|
+
return;
|
|
109
|
+
this.saveTimer = setTimeout(() => {
|
|
110
|
+
this.save();
|
|
111
|
+
this.saveTimer = null;
|
|
112
|
+
}, 2000); // debounce writes
|
|
113
|
+
}
|
|
114
|
+
save() {
|
|
115
|
+
try {
|
|
116
|
+
const dir = path_1.default.dirname(this.storePath);
|
|
117
|
+
if (!fs_1.default.existsSync(dir))
|
|
118
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
119
|
+
const data = JSON.stringify(Array.from(this.keys.entries()), null, 2);
|
|
120
|
+
fs_1.default.writeFileSync(this.storePath, data, 'utf-8');
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
console.error('[KeyManager] Failed to save keys:', err);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
load() {
|
|
127
|
+
try {
|
|
128
|
+
if (!fs_1.default.existsSync(this.storePath))
|
|
129
|
+
return;
|
|
130
|
+
const data = JSON.parse(fs_1.default.readFileSync(this.storePath, 'utf-8'));
|
|
131
|
+
for (const [id, key] of data) {
|
|
132
|
+
this.keys.set(id, key);
|
|
133
|
+
}
|
|
134
|
+
console.log(`[KeyManager] Loaded ${this.keys.size} keys`);
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
console.error('[KeyManager] Failed to load keys:', err);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.KeyManager = KeyManager;
|
|
142
|
+
//# sourceMappingURL=KeyManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeyManager.js","sourceRoot":"","sources":["../../src/cloud/KeyManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lemma Cloud — Tenant Cache Manager
|
|
3
|
+
*
|
|
4
|
+
* Each tenant gets an isolated ChromaDB collection + usage stats.
|
|
5
|
+
* Handles semantic search via Ollama embeddings.
|
|
6
|
+
*/
|
|
7
|
+
import { TenantStats } from './types';
|
|
8
|
+
export declare class TenantCache {
|
|
9
|
+
private tenantId;
|
|
10
|
+
private chromaUrl;
|
|
11
|
+
private ollamaUrl;
|
|
12
|
+
private model;
|
|
13
|
+
private collectionName;
|
|
14
|
+
private chromaClient;
|
|
15
|
+
private chromaCollection;
|
|
16
|
+
private embeddingCache;
|
|
17
|
+
private stats;
|
|
18
|
+
constructor(tenantId: string, chromaUrl: string, ollamaUrl: string, model: string);
|
|
19
|
+
initialize(): Promise<void>;
|
|
20
|
+
query(input: string, threshold: number): Promise<{
|
|
21
|
+
hit: boolean;
|
|
22
|
+
data?: any;
|
|
23
|
+
similarity?: number;
|
|
24
|
+
}>;
|
|
25
|
+
store(key: string, input: string, data: any, ttl: number): Promise<void>;
|
|
26
|
+
getStats(): Promise<TenantStats>;
|
|
27
|
+
private embed;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=TenantCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TenantCache.d.ts","sourceRoot":"","sources":["../../src/cloud/TenantCache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,WAAW,EAAuD,MAAM,SAAS,CAAC;AAU3F,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,cAAc,CAA+B;IAErD,OAAO,CAAC,KAAK,CAA0B;gBAE3B,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAS3E,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,KAAK,CACT,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,GAAG,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA0CvD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBxE,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC;YAyBxB,KAAK;CAiBpB"}
|