mengram-ai 2.2.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.
Files changed (4) hide show
  1. package/README.md +72 -0
  2. package/index.d.ts +131 -0
  3. package/index.js +430 -0
  4. package/package.json +16 -0
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # mengram-ai
2
+
3
+ JavaScript / TypeScript SDK for [Mengram](https://mengram.io) — AI Memory Layer with Autonomous Agents.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install mengram-ai
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```javascript
14
+ const { MengramClient } = require('mengram-ai');
15
+
16
+ const m = new MengramClient('mg-your-api-key');
17
+
18
+ // Add memories from conversation
19
+ await m.add([
20
+ { role: 'user', content: 'I work at Acme Corp as a senior engineer. I prefer dark mode.' },
21
+ { role: 'assistant', content: 'Noted your preferences!' }
22
+ ], { userId: 'ali' });
23
+
24
+ // Search memories
25
+ const results = await m.search('work preferences', { userId: 'ali' });
26
+ console.log(results);
27
+ // [{ entity: 'User', type: 'person', score: 0.92, facts: ['Works at Acme Corp', 'Prefers dark mode'] }]
28
+
29
+ // Multi-agent memory
30
+ await m.add(messages, {
31
+ userId: 'ali',
32
+ agentId: 'support-bot',
33
+ appId: 'helpdesk'
34
+ });
35
+ ```
36
+
37
+ ## TypeScript
38
+
39
+ ```typescript
40
+ import { MengramClient, SearchResult } from 'mengram-ai';
41
+
42
+ const m = new MengramClient('mg-...');
43
+ const results: SearchResult[] = await m.search('preferences');
44
+ ```
45
+
46
+ ## API
47
+
48
+ | Method | Description |
49
+ |--------|-------------|
50
+ | `add(messages, options?)` | Add memories from conversation |
51
+ | `addText(text, options?)` | Add memories from plain text |
52
+ | `search(query, options?)` | Semantic search |
53
+ | `getAll(options?)` | List all memories |
54
+ | `get(name)` | Get specific entity |
55
+ | `delete(name)` | Delete entity |
56
+ | `stats()` | Usage statistics |
57
+ | `graph()` | Knowledge graph |
58
+ | `runAgents(options?)` | Run memory agents |
59
+ | `insights()` | AI-generated reflections |
60
+ | `createTeam(name)` | Create shared team |
61
+ | `joinTeam(code)` | Join team with invite code |
62
+ | `shareMemory(entity, teamId)` | Share memory with team |
63
+ | `listKeys()` | List API keys |
64
+ | `createKey(name?)` | Create new API key |
65
+
66
+ All methods support `userId`, `agentId`, `runId`, `appId` options for multi-agent systems.
67
+
68
+ ## Links
69
+
70
+ - [Documentation](https://mengram.io/docs)
71
+ - [Python SDK](https://pypi.org/project/mengram-ai/)
72
+ - [GitHub](https://github.com/alibaizhanov/mengram)
package/index.d.ts ADDED
@@ -0,0 +1,131 @@
1
+ export interface MengramOptions {
2
+ baseUrl?: string;
3
+ timeout?: number;
4
+ }
5
+
6
+ export interface Message {
7
+ role: 'user' | 'assistant' | 'system';
8
+ content: string;
9
+ }
10
+
11
+ export interface MemoryOptions {
12
+ userId?: string;
13
+ agentId?: string;
14
+ runId?: string;
15
+ appId?: string;
16
+ }
17
+
18
+ export interface SearchOptions extends MemoryOptions {
19
+ limit?: number;
20
+ }
21
+
22
+ export interface AddResult {
23
+ status: string;
24
+ message?: string;
25
+ job_id?: string;
26
+ }
27
+
28
+ export interface SearchResult {
29
+ entity: string;
30
+ type: string;
31
+ score: number;
32
+ facts: string[];
33
+ knowledge: any[];
34
+ relations: any[];
35
+ }
36
+
37
+ export interface Entity {
38
+ name: string;
39
+ type: string;
40
+ facts: string[];
41
+ knowledge: any[];
42
+ relations: any[];
43
+ created_at: string;
44
+ updated_at: string;
45
+ }
46
+
47
+ export interface Stats {
48
+ entities: number;
49
+ facts: number;
50
+ knowledge: number;
51
+ relations: number;
52
+ embeddings: number;
53
+ by_type: Record<string, number>;
54
+ }
55
+
56
+ export interface ApiKey {
57
+ id: number;
58
+ name: string;
59
+ prefix: string;
60
+ active: boolean;
61
+ created_at: string | null;
62
+ last_used: string | null;
63
+ }
64
+
65
+ export interface JobStatus {
66
+ status: 'pending' | 'processing' | 'completed' | 'failed';
67
+ result?: any;
68
+ error?: string;
69
+ }
70
+
71
+ export interface Webhook {
72
+ id: number;
73
+ url: string;
74
+ name: string;
75
+ event_types: string[];
76
+ active: boolean;
77
+ trigger_count: number;
78
+ last_triggered: string | null;
79
+ last_error: string | null;
80
+ }
81
+
82
+ export declare class MengramError extends Error {
83
+ statusCode: number;
84
+ constructor(message: string, statusCode: number);
85
+ }
86
+
87
+ export declare class MengramClient {
88
+ constructor(apiKey: string, options?: MengramOptions);
89
+
90
+ // Memory
91
+ add(messages: Message[], options?: MemoryOptions): Promise<AddResult>;
92
+ addText(text: string, options?: MemoryOptions): Promise<AddResult>;
93
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
94
+ getAll(options?: MemoryOptions): Promise<Entity[]>;
95
+ getAllFull(): Promise<Entity[]>;
96
+ get(name: string): Promise<Entity | null>;
97
+ delete(name: string): Promise<boolean>;
98
+ stats(): Promise<Stats>;
99
+ graph(): Promise<{ nodes: any[]; edges: any[] }>;
100
+ timeline(options?: { after?: string; before?: string; limit?: number }): Promise<any[]>;
101
+
102
+ // Agents
103
+ runAgents(options?: { agent?: string; autoFix?: boolean }): Promise<any>;
104
+ agentHistory(options?: { agent?: string; limit?: number }): Promise<any[]>;
105
+
106
+ // Insights
107
+ insights(): Promise<any>;
108
+ reflect(): Promise<any>;
109
+
110
+ // Webhooks
111
+ listWebhooks(): Promise<Webhook[]>;
112
+ createWebhook(webhook: { url: string; eventTypes: string[]; name?: string; secret?: string }): Promise<any>;
113
+ deleteWebhook(webhookId: number): Promise<boolean>;
114
+
115
+ // Teams
116
+ createTeam(name: string, description?: string): Promise<any>;
117
+ joinTeam(inviteCode: string): Promise<any>;
118
+ listTeams(): Promise<any[]>;
119
+ shareMemory(entityName: string, teamId: number): Promise<any>;
120
+
121
+ // API Keys
122
+ listKeys(): Promise<ApiKey[]>;
123
+ createKey(name?: string): Promise<{ key: string; name: string }>;
124
+ revokeKey(keyId: number): Promise<any>;
125
+
126
+ // Jobs
127
+ jobStatus(jobId: string): Promise<JobStatus>;
128
+ waitForJob(jobId: string, options?: { pollInterval?: number; maxWait?: number }): Promise<any>;
129
+ }
130
+
131
+ export default MengramClient;
package/index.js ADDED
@@ -0,0 +1,430 @@
1
+ /**
2
+ * Mengram Cloud SDK for JavaScript / TypeScript
3
+ *
4
+ * Usage:
5
+ * const { MengramClient } = require('mengram-ai');
6
+ * // or: import { MengramClient } from 'mengram-ai';
7
+ *
8
+ * const m = new MengramClient('mg-...');
9
+ *
10
+ * await m.add([
11
+ * { role: 'user', content: 'I prefer dark mode and use Vim.' },
12
+ * { role: 'assistant', content: 'Noted!' }
13
+ * ], { userId: 'ali' });
14
+ *
15
+ * const results = await m.search('editor preferences', { userId: 'ali' });
16
+ */
17
+
18
+ class MengramClient {
19
+ /**
20
+ * @param {string} apiKey - Your Mengram API key (mg-...)
21
+ * @param {object} [options]
22
+ * @param {string} [options.baseUrl] - API base URL (default: https://mengram.io)
23
+ * @param {number} [options.timeout] - Request timeout in ms (default: 30000)
24
+ */
25
+ constructor(apiKey, options = {}) {
26
+ if (!apiKey) throw new Error('API key is required');
27
+ this.apiKey = apiKey;
28
+ this.baseUrl = (options.baseUrl || 'https://mengram.io').replace(/\/$/, '');
29
+ this.timeout = options.timeout || 30000;
30
+ }
31
+
32
+ async _request(method, path, body = null, params = null) {
33
+ let url = `${this.baseUrl}${path}`;
34
+
35
+ if (params) {
36
+ const qs = Object.entries(params)
37
+ .filter(([, v]) => v !== undefined && v !== null)
38
+ .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
39
+ .join('&');
40
+ if (qs) url += `?${qs}`;
41
+ }
42
+
43
+ const headers = {
44
+ 'Authorization': `Bearer ${this.apiKey}`,
45
+ 'Content-Type': 'application/json',
46
+ };
47
+
48
+ const controller = new AbortController();
49
+ const timer = setTimeout(() => controller.abort(), this.timeout);
50
+
51
+ try {
52
+ const res = await fetch(url, {
53
+ method,
54
+ headers,
55
+ body: body ? JSON.stringify(body) : undefined,
56
+ signal: controller.signal,
57
+ });
58
+
59
+ const data = await res.json();
60
+ if (!res.ok) {
61
+ throw new MengramError(data.detail || `HTTP ${res.status}`, res.status);
62
+ }
63
+ return data;
64
+ } catch (err) {
65
+ if (err instanceof MengramError) throw err;
66
+ if (err.name === 'AbortError') {
67
+ throw new MengramError(`Request timeout after ${this.timeout}ms`, 408);
68
+ }
69
+ throw new MengramError(err.message, 0);
70
+ } finally {
71
+ clearTimeout(timer);
72
+ }
73
+ }
74
+
75
+ // ---- Memory ----
76
+
77
+ /**
78
+ * Add memories from conversation.
79
+ * @param {Array<{role: string, content: string}>} messages
80
+ * @param {object} [options]
81
+ * @param {string} [options.userId] - User ID (default: 'default')
82
+ * @param {string} [options.agentId] - Agent ID for multi-agent systems
83
+ * @param {string} [options.runId] - Run/session ID
84
+ * @param {string} [options.appId] - Application ID
85
+ * @returns {Promise<{status: string, job_id?: string}>}
86
+ */
87
+ async add(messages, options = {}) {
88
+ return this._request('POST', '/v1/add', {
89
+ messages,
90
+ user_id: options.userId || 'default',
91
+ agent_id: options.agentId || null,
92
+ run_id: options.runId || null,
93
+ app_id: options.appId || null,
94
+ });
95
+ }
96
+
97
+ /**
98
+ * Add memory from plain text.
99
+ * @param {string} text
100
+ * @param {object} [options]
101
+ * @param {string} [options.userId]
102
+ * @param {string} [options.agentId]
103
+ * @param {string} [options.runId]
104
+ * @param {string} [options.appId]
105
+ * @returns {Promise<{status: string}>}
106
+ */
107
+ async addText(text, options = {}) {
108
+ return this._request('POST', '/v1/add_text', {
109
+ text,
110
+ user_id: options.userId || 'default',
111
+ agent_id: options.agentId || null,
112
+ run_id: options.runId || null,
113
+ app_id: options.appId || null,
114
+ });
115
+ }
116
+
117
+ /**
118
+ * Semantic search across memories.
119
+ * @param {string} query
120
+ * @param {object} [options]
121
+ * @param {string} [options.userId]
122
+ * @param {string} [options.agentId]
123
+ * @param {string} [options.runId]
124
+ * @param {string} [options.appId]
125
+ * @param {number} [options.limit] - Max results (default: 5)
126
+ * @returns {Promise<Array>}
127
+ */
128
+ async search(query, options = {}) {
129
+ const data = await this._request('POST', '/v1/search', {
130
+ query,
131
+ user_id: options.userId || 'default',
132
+ agent_id: options.agentId || null,
133
+ run_id: options.runId || null,
134
+ app_id: options.appId || null,
135
+ limit: options.limit || 5,
136
+ });
137
+ return data.results || [];
138
+ }
139
+
140
+ /**
141
+ * Get all memories.
142
+ * @param {object} [options]
143
+ * @param {string} [options.userId]
144
+ * @param {string} [options.agentId]
145
+ * @param {string} [options.appId]
146
+ * @returns {Promise<Array>}
147
+ */
148
+ async getAll(options = {}) {
149
+ const params = {};
150
+ if (options.userId) params.user_id_param = options.userId;
151
+ if (options.agentId) params.agent_id = options.agentId;
152
+ if (options.appId) params.app_id = options.appId;
153
+ const data = await this._request('GET', '/v1/memories', null, params);
154
+ return data.memories || [];
155
+ }
156
+
157
+ /**
158
+ * Get all memories with full details.
159
+ * @returns {Promise<Array>}
160
+ */
161
+ async getAllFull() {
162
+ const data = await this._request('GET', '/v1/memories/full');
163
+ return data.memories || [];
164
+ }
165
+
166
+ /**
167
+ * Get specific entity.
168
+ * @param {string} name - Entity name
169
+ * @returns {Promise<object|null>}
170
+ */
171
+ async get(name) {
172
+ try {
173
+ return await this._request('GET', `/v1/memory/${encodeURIComponent(name)}`);
174
+ } catch {
175
+ return null;
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Delete a memory entity.
181
+ * @param {string} name
182
+ * @returns {Promise<boolean>}
183
+ */
184
+ async delete(name) {
185
+ try {
186
+ await this._request('DELETE', `/v1/entity/${encodeURIComponent(name)}`);
187
+ return true;
188
+ } catch {
189
+ return false;
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Get usage statistics.
195
+ * @returns {Promise<object>}
196
+ */
197
+ async stats() {
198
+ return this._request('GET', '/v1/stats');
199
+ }
200
+
201
+ /**
202
+ * Get knowledge graph.
203
+ * @returns {Promise<{nodes: Array, edges: Array}>}
204
+ */
205
+ async graph() {
206
+ return this._request('GET', '/v1/graph');
207
+ }
208
+
209
+ /**
210
+ * Timeline search.
211
+ * @param {object} [options]
212
+ * @param {string} [options.after] - ISO date
213
+ * @param {string} [options.before] - ISO date
214
+ * @param {number} [options.limit]
215
+ * @returns {Promise<Array>}
216
+ */
217
+ async timeline(options = {}) {
218
+ const params = { limit: options.limit || 20 };
219
+ if (options.after) params.after = options.after;
220
+ if (options.before) params.before = options.before;
221
+ const data = await this._request('GET', '/v1/timeline', null, params);
222
+ return data.results || [];
223
+ }
224
+
225
+ // ---- Agents ----
226
+
227
+ /**
228
+ * Run memory agents.
229
+ * @param {object} [options]
230
+ * @param {string} [options.agent] - 'curator', 'connector', 'digest', or 'all'
231
+ * @param {boolean} [options.autoFix] - Auto-archive bad facts
232
+ * @returns {Promise<object>}
233
+ */
234
+ async runAgents(options = {}) {
235
+ return this._request('POST', '/v1/agents/run', null, {
236
+ agent: options.agent || 'all',
237
+ auto_fix: options.autoFix ? 'true' : 'false',
238
+ });
239
+ }
240
+
241
+ /**
242
+ * Get agent run history.
243
+ * @param {object} [options]
244
+ * @param {string} [options.agent]
245
+ * @param {number} [options.limit]
246
+ * @returns {Promise<Array>}
247
+ */
248
+ async agentHistory(options = {}) {
249
+ const params = { limit: options.limit || 10 };
250
+ if (options.agent) params.agent = options.agent;
251
+ const data = await this._request('GET', '/v1/agents/history', null, params);
252
+ return data.runs || [];
253
+ }
254
+
255
+ // ---- Insights ----
256
+
257
+ /**
258
+ * Get AI insights and reflections.
259
+ * @returns {Promise<object>}
260
+ */
261
+ async insights() {
262
+ return this._request('GET', '/v1/insights');
263
+ }
264
+
265
+ /**
266
+ * Trigger reflection generation.
267
+ * @returns {Promise<object>}
268
+ */
269
+ async reflect() {
270
+ return this._request('POST', '/v1/reflect');
271
+ }
272
+
273
+ // ---- Webhooks ----
274
+
275
+ /**
276
+ * List webhooks.
277
+ * @returns {Promise<Array>}
278
+ */
279
+ async listWebhooks() {
280
+ const data = await this._request('GET', '/v1/webhooks');
281
+ return data.webhooks || [];
282
+ }
283
+
284
+ /**
285
+ * Create webhook.
286
+ * @param {object} webhook
287
+ * @param {string} webhook.url
288
+ * @param {string[]} webhook.eventTypes
289
+ * @param {string} [webhook.name]
290
+ * @param {string} [webhook.secret]
291
+ * @returns {Promise<object>}
292
+ */
293
+ async createWebhook(webhook) {
294
+ return this._request('POST', '/v1/webhooks', {
295
+ url: webhook.url,
296
+ event_types: webhook.eventTypes,
297
+ name: webhook.name || '',
298
+ secret: webhook.secret || '',
299
+ });
300
+ }
301
+
302
+ /**
303
+ * Delete webhook.
304
+ * @param {number} webhookId
305
+ * @returns {Promise<boolean>}
306
+ */
307
+ async deleteWebhook(webhookId) {
308
+ try {
309
+ await this._request('DELETE', `/v1/webhooks/${webhookId}`);
310
+ return true;
311
+ } catch {
312
+ return false;
313
+ }
314
+ }
315
+
316
+ // ---- Teams ----
317
+
318
+ /**
319
+ * Create a team.
320
+ * @param {string} name
321
+ * @param {string} [description]
322
+ * @returns {Promise<object>}
323
+ */
324
+ async createTeam(name, description = '') {
325
+ return this._request('POST', '/v1/teams', { name, description });
326
+ }
327
+
328
+ /**
329
+ * Join a team with invite code.
330
+ * @param {string} inviteCode
331
+ * @returns {Promise<object>}
332
+ */
333
+ async joinTeam(inviteCode) {
334
+ return this._request('POST', '/v1/teams/join', { invite_code: inviteCode });
335
+ }
336
+
337
+ /**
338
+ * List your teams.
339
+ * @returns {Promise<Array>}
340
+ */
341
+ async listTeams() {
342
+ const data = await this._request('GET', '/v1/teams');
343
+ return data.teams || [];
344
+ }
345
+
346
+ /**
347
+ * Share memory with a team.
348
+ * @param {string} entityName
349
+ * @param {number} teamId
350
+ * @returns {Promise<object>}
351
+ */
352
+ async shareMemory(entityName, teamId) {
353
+ return this._request('POST', `/v1/teams/${teamId}/share`, { entity: entityName });
354
+ }
355
+
356
+ // ---- API Keys ----
357
+
358
+ /**
359
+ * List API keys.
360
+ * @returns {Promise<Array>}
361
+ */
362
+ async listKeys() {
363
+ const data = await this._request('GET', '/v1/keys');
364
+ return data.keys || [];
365
+ }
366
+
367
+ /**
368
+ * Create a new API key.
369
+ * @param {string} [name] - Key name
370
+ * @returns {Promise<{key: string, name: string}>}
371
+ */
372
+ async createKey(name = 'default') {
373
+ return this._request('POST', '/v1/keys', { name });
374
+ }
375
+
376
+ /**
377
+ * Revoke an API key.
378
+ * @param {number} keyId
379
+ * @returns {Promise<object>}
380
+ */
381
+ async revokeKey(keyId) {
382
+ return this._request('DELETE', `/v1/keys/${keyId}`);
383
+ }
384
+
385
+ // ---- Jobs (Async) ----
386
+
387
+ /**
388
+ * Check status of a background job.
389
+ * @param {string} jobId
390
+ * @returns {Promise<{status: string, result?: object}>}
391
+ */
392
+ async jobStatus(jobId) {
393
+ return this._request('GET', `/v1/jobs/${jobId}`);
394
+ }
395
+
396
+ /**
397
+ * Wait for a job to complete.
398
+ * @param {string} jobId
399
+ * @param {object} [options]
400
+ * @param {number} [options.pollInterval] - ms between polls (default: 1000)
401
+ * @param {number} [options.maxWait] - max ms to wait (default: 60000)
402
+ * @returns {Promise<object>}
403
+ */
404
+ async waitForJob(jobId, options = {}) {
405
+ const interval = options.pollInterval || 1000;
406
+ const maxWait = options.maxWait || 60000;
407
+ const start = Date.now();
408
+
409
+ while (Date.now() - start < maxWait) {
410
+ const job = await this.jobStatus(jobId);
411
+ if (job.status === 'completed' || job.status === 'failed') {
412
+ return job;
413
+ }
414
+ await new Promise(r => setTimeout(r, interval));
415
+ }
416
+ throw new MengramError('Job timed out', 408);
417
+ }
418
+ }
419
+
420
+ class MengramError extends Error {
421
+ constructor(message, statusCode) {
422
+ super(message);
423
+ this.name = 'MengramError';
424
+ this.statusCode = statusCode;
425
+ }
426
+ }
427
+
428
+ // Export for both CommonJS and ESM
429
+ module.exports = { MengramClient, MengramError };
430
+ module.exports.default = MengramClient;
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "mengram-ai",
3
+ "version": "2.2.0",
4
+ "description": "AI Memory Layer with Autonomous Agents — JavaScript SDK",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "license": "Apache-2.0",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/alibaizhanov/mengram"
11
+ },
12
+ "homepage": "https://mengram.io",
13
+ "keywords": ["ai", "memory", "llm", "agents", "knowledge-graph", "mcp", "mengram"],
14
+ "author": "Ali Baizhanov",
15
+ "files": ["index.js", "index.d.ts", "README.md"]
16
+ }