@becomerpackage/sdk 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/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # becomer — JavaScript / Node.js SDK
2
+
3
+ [![npm](https://img.shields.io/npm/v/becomer)](https://www.npmjs.com/package/becomer)
4
+ [![LongMemEval](https://img.shields.io/badge/LongMemEval-94.4%25-brightgreen)](https://becomer.net/#benchmarks)
5
+
6
+ **Persistent memory API for AI apps. Zero dependencies. Node 18+.**
7
+
8
+ ```js
9
+ const { Client } = require('becomer');
10
+
11
+ const mem = new Client('bcm_your-api-key');
12
+ await mem.store('User prefers dark mode and speaks French');
13
+ const memories = await mem.recall('user preferences');
14
+ // → ['User prefers dark mode and speaks French']
15
+ ```
16
+
17
+ → [Get your free API key](https://becomer.net/signup.html) · [Docs](https://becomer.net/docs.html) · [Benchmarks](https://becomer.net/#benchmarks)
18
+
19
+ ---
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ npm install @becomerpackage/sdk
25
+ ```
26
+
27
+ Zero dependencies. Uses Node's built-in `fetch` (Node 18+).
28
+
29
+ ---
30
+
31
+ ## Quick start
32
+
33
+ ```js
34
+ const { Client } = require('becomer');
35
+ // ESM: import { Client } from 'becomer';
36
+
37
+ const mem = new Client('bcm_your-api-key');
38
+
39
+ await mem.store('User is Sarah, senior engineer at Stripe');
40
+ await mem.store('User prefers TypeScript and dark mode');
41
+
42
+ const context = await mem.recall('what do I know about the user?');
43
+ // → ['User is Sarah, senior engineer at Stripe', ...]
44
+
45
+ // Inject into your LLM call
46
+ const system = 'You are a helpful assistant.\n\nContext:\n' + context.join('\n');
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Multi-tenant (one key, many users)
52
+
53
+ Pass `userId` to isolate memories per end-user under one master key.
54
+
55
+ ```js
56
+ // Constructor-level (all calls scoped to alice)
57
+ const memAlice = new Client('bcm_your-api-key', { userId: 'alice-123' });
58
+ await memAlice.store('Alice prefers TypeScript');
59
+
60
+ // Different user — completely isolated
61
+ const memBob = new Client('bcm_your-api-key', { userId: 'bob-456' });
62
+ await memBob.recall('preferences'); // → [] (cannot see Alice's memories)
63
+
64
+ // Or override per-call
65
+ const mem = new Client('bcm_your-api-key');
66
+ await mem.store('Charlie loves Rust', { userId: 'charlie-789' });
67
+ await mem.recall('languages', { userId: 'charlie-789' });
68
+ ```
69
+
70
+ Billing counts against the master key. Browse per-user memories in your [dashboard](https://becomer.net/dashboard.html).
71
+
72
+ ---
73
+
74
+ ## OpenAI
75
+
76
+ ```js
77
+ const OpenAI = require('openai');
78
+ const { Client } = require('becomer');
79
+
80
+ const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
81
+ const mem = new Client(process.env.BECOMER_API_KEY);
82
+
83
+ async function chat(message, userId) {
84
+ const context = await mem.recall(message, { userId });
85
+ const system = context.length
86
+ ? 'You are helpful.\n\nContext:\n' + context.join('\n')
87
+ : 'You are helpful.';
88
+
89
+ const res = await openai.chat.completions.create({
90
+ model: 'gpt-4o',
91
+ messages: [{ role: 'system', content: system }, { role: 'user', content: message }],
92
+ });
93
+ const reply = res.choices[0].message.content;
94
+
95
+ await mem.store(`User: ${message}`, { userId });
96
+ await mem.store(`Assistant: ${reply}`, { userId });
97
+ return reply;
98
+ }
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Anthropic
104
+
105
+ ```js
106
+ const Anthropic = require('@anthropic-ai/sdk');
107
+ const { Client } = require('becomer');
108
+
109
+ const claude = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
110
+ const mem = new Client(process.env.BECOMER_API_KEY);
111
+
112
+ async function chat(message, userId) {
113
+ const context = await mem.recall(message, { userId });
114
+ const system = context.length
115
+ ? 'You are helpful.\n\nContext:\n' + context.join('\n')
116
+ : 'You are helpful.';
117
+
118
+ const res = await claude.messages.create({
119
+ model: 'claude-opus-4-8',
120
+ max_tokens: 1024,
121
+ system,
122
+ messages: [{ role: 'user', content: message }],
123
+ });
124
+ const reply = res.content[0].text;
125
+
126
+ await mem.store(`User: ${message}`, { userId });
127
+ await mem.store(`Assistant: ${reply}`, { userId });
128
+ return reply;
129
+ }
130
+ ```
131
+
132
+ ---
133
+
134
+ ## API reference
135
+
136
+ ### `new Client(apiKey, options?)`
137
+
138
+ | Option | Type | Description |
139
+ |--------|------|-------------|
140
+ | `userId` | string | Default sub-user ID applied to all calls |
141
+ | `baseUrl` | string | Override API base URL |
142
+
143
+ ### Methods
144
+
145
+ | Method | Returns | Description |
146
+ |--------|---------|-------------|
147
+ | `store(content, opts?)` | `Promise<{ok}>` | Store a memory |
148
+ | `recall(query, opts?)` | `Promise<string[]>` | Retrieve top-k relevant memories |
149
+ | `forget(opts?)` | `Promise<{ok}>` | Delete all memories (or sub-user's) |
150
+ | `sync(opts?)` | `Promise<{ok}>` | Consolidate working memory |
151
+
152
+ All methods accept `opts.userId` to override the sub-user for that call.
153
+ `recall` also accepts `opts.topK` (default: 5).
154
+
155
+ ---
156
+
157
+ ## Examples
158
+
159
+ | File | Framework |
160
+ |------|-----------|
161
+ | [quickstart.js](examples/quickstart.js) | Plain Node.js |
162
+ | [openai.js](examples/openai.js) | OpenAI SDK |
163
+ | [anthropic.js](examples/anthropic.js) | Anthropic SDK |
164
+ | [langchain.js](examples/langchain.js) | LangChain.js |
165
+
166
+ ---
167
+
168
+ ## Requirements
169
+
170
+ - Node.js 18+ (uses built-in `fetch`)
171
+ - Zero npm dependencies
172
+
173
+ ---
174
+
175
+ ## Built by
176
+
177
+ [Obsidex Pvt Limited](https://www.linkedin.com/company/115424394/) · [Aravind Balaji](https://www.linkedin.com/in/aravind-balaji-2k1/), Founder · [hello@becomer.net](mailto:hello@becomer.net)
@@ -0,0 +1,44 @@
1
+ // Anthropic Claude + BECOMER — persistent memory across conversations
2
+ // npm install @anthropic-ai/sdk becomer
3
+ const Anthropic = require('@anthropic-ai/sdk');
4
+ const { Client } = require('becomer');
5
+
6
+ const claude = new Anthropic({ apiKey: 'sk-ant-your-key' });
7
+
8
+ async function chat(message, mem) {
9
+ const context = await mem.recall(message);
10
+
11
+ let system = 'You are a helpful assistant.';
12
+ if (context.length) {
13
+ system += '\n\nWhat you remember about this user:\n' + context.map(m => `- ${m}`).join('\n');
14
+ }
15
+
16
+ const response = await claude.messages.create({
17
+ model: 'claude-opus-4-8',
18
+ max_tokens: 1024,
19
+ system,
20
+ messages: [{ role: 'user', content: message }],
21
+ });
22
+ const reply = response.content[0].text;
23
+
24
+ await mem.store(`User: ${message}`);
25
+ await mem.store(`Assistant: ${reply}`);
26
+
27
+ return reply;
28
+ }
29
+
30
+ async function main() {
31
+ // ── Single user ─────────────────────────────────────────────────────────────
32
+ const mem = new Client('bcm_your-api-key');
33
+ console.log(await chat("I'm Aravind, I'm building an AI memory product", mem));
34
+ console.log(await chat('What should I focus on for launch?', mem));
35
+
36
+ // ── Multi-tenant ────────────────────────────────────────────────────────────
37
+ const memAlice = new Client('bcm_your-api-key', { userId: 'alice-123' });
38
+ const memBob = new Client('bcm_your-api-key', { userId: 'bob-456' });
39
+
40
+ console.log(await chat('I love Rust and systems programming', memAlice));
41
+ console.log(await chat("I'm a data scientist, I use Python daily", memBob));
42
+ }
43
+
44
+ main().catch(console.error);
@@ -0,0 +1,58 @@
1
+ // LangChain.js + BECOMER — persistent memory adapter
2
+ // npm install langchain @langchain/openai becomer
3
+ const { BaseMemory } = require('langchain/memory');
4
+ const { ConversationChain } = require('langchain/chains');
5
+ const { ChatOpenAI } = require('@langchain/openai');
6
+ const { Client } = require('becomer');
7
+
8
+ class BecomerMemory extends BaseMemory {
9
+ constructor(apiKey, options = {}) {
10
+ super();
11
+ this.mem = new Client(apiKey, { userId: options.userId });
12
+ this.memoryKey = options.memoryKey || 'history';
13
+ }
14
+
15
+ get memoryVariables() {
16
+ return [this.memoryKey];
17
+ }
18
+
19
+ async loadMemoryVariables(inputs) {
20
+ const query = inputs.input || '';
21
+ const memories = await this.mem.recall(query);
22
+ return { [this.memoryKey]: memories.join('\n') };
23
+ }
24
+
25
+ async saveContext(inputs, outputs) {
26
+ await this.mem.store(`User: ${inputs.input || ''}`);
27
+ await this.mem.store(`Assistant: ${outputs.response || outputs.output || ''}`);
28
+ }
29
+
30
+ async clear() {
31
+ await this.mem.forget();
32
+ }
33
+ }
34
+
35
+ async function main() {
36
+ // ── Single user ─────────────────────────────────────────────────────────────
37
+ const chain = new ConversationChain({
38
+ llm: new ChatOpenAI({ model: 'gpt-4o', apiKey: 'sk-your-openai-key' }),
39
+ memory: new BecomerMemory('bcm_your-api-key'),
40
+ });
41
+
42
+ console.log(await chain.call({ input: 'My name is Sarah and I work at Stripe' }));
43
+ console.log(await chain.call({ input: 'What do you know about me?' }));
44
+
45
+ // ── Multi-tenant: per-user isolated memory ──────────────────────────────────
46
+ const chainAlice = new ConversationChain({
47
+ llm: new ChatOpenAI({ model: 'gpt-4o', apiKey: 'sk-your-openai-key' }),
48
+ memory: new BecomerMemory('bcm_your-api-key', { userId: 'alice-123' }),
49
+ });
50
+ const chainBob = new ConversationChain({
51
+ llm: new ChatOpenAI({ model: 'gpt-4o', apiKey: 'sk-your-openai-key' }),
52
+ memory: new BecomerMemory('bcm_your-api-key', { userId: 'bob-456' }),
53
+ });
54
+ // Alice and Bob have completely separate memory stores.
55
+ }
56
+
57
+ module.exports = { BecomerMemory };
58
+ main().catch(console.error);
@@ -0,0 +1,46 @@
1
+ // OpenAI + BECOMER — persistent memory across conversations
2
+ // npm install openai becomer
3
+ const OpenAI = require('openai');
4
+ const { Client } = require('becomer');
5
+
6
+ const openai = new OpenAI({ apiKey: 'sk-your-openai-key' });
7
+
8
+ async function chat(message, mem) {
9
+ const context = await mem.recall(message);
10
+
11
+ let system = 'You are a helpful assistant.';
12
+ if (context.length) {
13
+ system += '\n\nWhat you remember about this user:\n' + context.map(m => `- ${m}`).join('\n');
14
+ }
15
+
16
+ const response = await openai.chat.completions.create({
17
+ model: 'gpt-4o',
18
+ messages: [
19
+ { role: 'system', content: system },
20
+ { role: 'user', content: message },
21
+ ],
22
+ });
23
+ const reply = response.choices[0].message.content;
24
+
25
+ await mem.store(`User: ${message}`);
26
+ await mem.store(`Assistant: ${reply}`);
27
+
28
+ return reply;
29
+ }
30
+
31
+ async function main() {
32
+ // ── Single user ─────────────────────────────────────────────────────────────
33
+ const mem = new Client('bcm_your-api-key');
34
+ console.log(await chat("My name is Sarah and I'm building a payments dashboard", mem));
35
+ console.log(await chat('What stack should I use?', mem));
36
+
37
+ // ── Multi-tenant ────────────────────────────────────────────────────────────
38
+ const memAlice = new Client('bcm_your-api-key', { userId: 'alice-123' });
39
+ const memBob = new Client('bcm_your-api-key', { userId: 'bob-456' });
40
+
41
+ console.log(await chat('I prefer functional programming', memAlice));
42
+ console.log(await chat('I prefer OOP and Java', memBob));
43
+ // Alice and Bob have completely separate memory stores.
44
+ }
45
+
46
+ main().catch(console.error);
@@ -0,0 +1,32 @@
1
+ // Quickstart — store and recall memories
2
+ // Get your free API key at https://becomer.net
3
+ const { Client } = require('becomer');
4
+
5
+ async function main() {
6
+ // ── Single user ─────────────────────────────────────────────────────────────
7
+ const mem = new Client('bcm_your-api-key');
8
+
9
+ await mem.store('My name is Sarah and I work at Stripe');
10
+ await mem.store('I prefer concise answers and I use Node.js 20');
11
+
12
+ const results = await mem.recall('who is the user?');
13
+ console.log(results);
14
+ // → ['My name is Sarah and I work at Stripe', ...]
15
+
16
+ // ── Multi-tenant: one key, many users ───────────────────────────────────────
17
+ const memAlice = new Client('bcm_your-api-key', { userId: 'alice-123' });
18
+ const memBob = new Client('bcm_your-api-key', { userId: 'bob-456' });
19
+
20
+ await memAlice.store('Alice prefers TypeScript');
21
+ await memBob.store('Bob prefers Python');
22
+
23
+ console.log(await memAlice.recall('language preference')); // → Alice's only
24
+ console.log(await memBob.recall('language preference')); // → Bob's only
25
+
26
+ // Or override per-call:
27
+ const mem2 = new Client('bcm_your-api-key');
28
+ await mem2.store('Charlie loves Rust', { userId: 'charlie-789' });
29
+ console.log(await mem2.recall('languages', { userId: 'charlie-789' }));
30
+ }
31
+
32
+ main().catch(console.error);
package/index.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ export interface ClientOptions {
2
+ /** Default sub-user ID for multi-tenant apps. Applied to all calls unless overridden. */
3
+ userId?: string;
4
+ /** Override the API base URL. Defaults to https://becomer.net */
5
+ baseUrl?: string;
6
+ }
7
+
8
+ export interface CallOptions {
9
+ /** Sub-user ID for this call only. Overrides the constructor-level userId. */
10
+ userId?: string;
11
+ }
12
+
13
+ export interface RecallOptions extends CallOptions {
14
+ /** Number of memories to return. Default: 5 */
15
+ topK?: number;
16
+ }
17
+
18
+ export declare class BecomerError extends Error {
19
+ status?: number;
20
+ }
21
+
22
+ export declare class Client {
23
+ constructor(apiKey: string, options?: ClientOptions);
24
+
25
+ /** Store a memory. */
26
+ store(content: string, opts?: CallOptions): Promise<{ ok: boolean }>;
27
+
28
+ /** Recall relevant memories for a query. */
29
+ recall(query: string, opts?: RecallOptions): Promise<string[]>;
30
+
31
+ /** Delete all memories (or a sub-user's memories if userId is set). */
32
+ forget(opts?: CallOptions): Promise<{ ok: boolean }>;
33
+
34
+ /** Consolidate working memory into long-term storage. */
35
+ sync(opts?: CallOptions): Promise<{ ok: boolean }>;
36
+ }
package/index.js ADDED
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+
3
+ const BASE_URL = 'https://becomer.net';
4
+
5
+ class BecomerError extends Error {
6
+ constructor(message, status) {
7
+ super(message);
8
+ this.name = 'BecomerError';
9
+ this.status = status;
10
+ }
11
+ }
12
+
13
+ class Client {
14
+ /**
15
+ * @param {string} apiKey - Your BECOMER API key (starts with bcm_)
16
+ * @param {object} [options]
17
+ * @param {string} [options.userId] - Default sub-user ID for multi-tenant apps
18
+ * @param {string} [options.baseUrl] - Override API base URL
19
+ */
20
+ constructor(apiKey, options = {}) {
21
+ if (!apiKey) throw new BecomerError('apiKey is required');
22
+ this._key = apiKey;
23
+ this._userId = options.userId || null;
24
+ this._base = (options.baseUrl || BASE_URL).replace(/\/$/, '');
25
+ }
26
+
27
+ _body(base, opts = {}) {
28
+ const uid = opts.userId !== undefined ? opts.userId : this._userId;
29
+ if (uid) return { ...base, user_id: uid };
30
+ return base;
31
+ }
32
+
33
+ async _request(method, path, body) {
34
+ const url = this._base + path;
35
+ const res = await fetch(url, {
36
+ method,
37
+ headers: {
38
+ Authorization: `Bearer ${this._key}`,
39
+ 'Content-Type': 'application/json',
40
+ },
41
+ body: body !== undefined ? JSON.stringify(body) : undefined,
42
+ });
43
+ if (!res.ok) {
44
+ const text = await res.text().catch(() => '');
45
+ throw new BecomerError(`HTTP ${res.status}: ${text}`, res.status);
46
+ }
47
+ return res.json();
48
+ }
49
+
50
+ /**
51
+ * Store a memory.
52
+ * @param {string} content
53
+ * @param {object} [opts]
54
+ * @param {string} [opts.userId] - Override sub-user for this call
55
+ */
56
+ async store(content, opts = {}) {
57
+ return this._request('POST', '/v1/store', this._body({ content }, opts));
58
+ }
59
+
60
+ /**
61
+ * Recall relevant memories for a query.
62
+ * @param {string} query
63
+ * @param {object} [opts]
64
+ * @param {number} [opts.topK=5]
65
+ * @param {string} [opts.userId]
66
+ * @returns {Promise<string[]>}
67
+ */
68
+ async recall(query, opts = {}) {
69
+ const { topK = 5, userId } = opts;
70
+ const result = await this._request(
71
+ 'POST', '/v1/recall',
72
+ this._body({ query, top_k: topK }, { userId })
73
+ );
74
+ return result.memories || [];
75
+ }
76
+
77
+ /**
78
+ * Delete all memories (or a sub-user's memories if userId is set).
79
+ * @param {object} [opts]
80
+ * @param {string} [opts.userId]
81
+ */
82
+ async forget(opts = {}) {
83
+ return this._request('POST', '/v1/forget', this._body({ forget_all: true }, opts));
84
+ }
85
+
86
+ /**
87
+ * Consolidate working memory into long-term storage.
88
+ * @param {object} [opts]
89
+ * @param {string} [opts.userId]
90
+ */
91
+ async sync(opts = {}) {
92
+ return this._request('POST', '/v1/sync', this._body({}, opts));
93
+ }
94
+ }
95
+
96
+ module.exports = { Client, BecomerError };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@becomerpackage/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Persistent memory API for AI applications — 94.4% LongMemEval, zero tokens per recall",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "require": "./index.js",
10
+ "import": "./index.js",
11
+ "types": "./index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "test": "node examples/quickstart.js"
16
+ },
17
+ "keywords": [
18
+ "memory", "llm", "ai", "mcp", "claude", "gpt", "openai", "anthropic",
19
+ "langchain", "persistent-memory", "vector-store", "rag"
20
+ ],
21
+ "author": "Obsidex Pvt Limited <hello@becomer.net>",
22
+ "license": "MIT",
23
+ "homepage": "https://becomer.net",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/Aravind-Becomer-net/Becomer.net"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/Aravind-Becomer-net/Becomer.net/issues",
30
+ "email": "hello@becomer.net"
31
+ },
32
+ "engines": {
33
+ "node": ">=18.0.0"
34
+ },
35
+ "dependencies": {}
36
+ }