superbrain-distributed-sdk 0.2.1 β 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -15
- package/lib/libsuperbrain.dylib +0 -0
- package/lib/libsuperbrain.so +0 -0
- package/package.json +6 -1
- package/demo.js +0 -29
- package/demo.ts +0 -37
- package/index.ts +0 -118
- package/tsconfig.json +0 -17
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# π§ superbrain-distributed-sdk v0.2
|
|
1
|
+
# π§ superbrain-distributed-sdk v0.7.2 β TypeScript/Node.js
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/superbrain-distributed-sdk)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -16,17 +16,12 @@ npm install superbrain-distributed-sdk
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
## β¨ New in v0.
|
|
19
|
+
## β¨ New in v0.7.1 β Tiered Architecture & Zero-Copy SHM
|
|
20
|
+
Version 0.7.1 introduces the ability to operate as a microsecond-latency **L1 Shared Memory Tier** for agent architectures.
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- **Auto-Discovery**: Zero-config cluster formation via mDNS
|
|
25
|
-
- **KV Cache Pooling**: Identical prefixes shared across models automatically
|
|
26
|
-
- **Smart Prefetching**: Markov-chain access pattern prediction
|
|
27
|
-
- **Self-Tuning Allocator**: Learns from access history to pre-allocate
|
|
28
|
-
- **Anomaly Detection**: Z-score alerting for unusual access patterns
|
|
29
|
-
- **Live Dashboard**: Real-time metrics at `http://localhost:9090`
|
|
22
|
+
- **Coordinator Bypass**: Metadata is cached locally, eliminating the gRPC hop to the Coordinator for established pointers.
|
|
23
|
+
- **Zero-Copy SHM**: When the SDK detects a co-located Memory Node (`127.0.0.1`), it seamlessly switches from gRPC streaming to direct `/dev/shm` memory-mapped file access.
|
|
24
|
+
- **13.5Β΅s Native Latency**: The Native Go core bypass achieves microsecond speed, bypassing the network entirely for local agents.
|
|
30
25
|
|
|
31
26
|
---
|
|
32
27
|
|
|
@@ -112,6 +107,44 @@ The Coordinator is ONLY in the control path (allocate + free).
|
|
|
112
107
|
|
|
113
108
|
---
|
|
114
109
|
|
|
110
|
+
## π§Ή Memory Management
|
|
111
|
+
|
|
112
|
+
> **The Node.js SDK exposes the raw client layer β `free()` is always required after `allocate()`.**
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// β
Always do this after you are done with a pointer
|
|
116
|
+
const ptr = await client.allocate(100 * 1024 * 1024);
|
|
117
|
+
await client.write(ptr, 0, data);
|
|
118
|
+
const result = await client.read(ptr, 0, 0);
|
|
119
|
+
await client.free(ptr); // β required β leaks memory if skipped
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### π Want Managed Memory? Use the Python SDK
|
|
123
|
+
|
|
124
|
+
The Python SDK (`pip install superbrain-sdk`) provides higher-level APIs where **free() is never needed**:
|
|
125
|
+
|
|
126
|
+
| Python API | Free needed? | What it does |
|
|
127
|
+
|------------|:------------:|--------------|
|
|
128
|
+
| `SharedContext.write("key", data)` | β No | Key-based shared state across agents |
|
|
129
|
+
| `fabric.store_kv_cache(prefix)` | β No | Deduped prompt cache, auto-evicted |
|
|
130
|
+
| `SuperBrainMemory` (LangChain) | β No | Chat history in distributed RAM |
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
# Python β no free() ever needed with high-level APIs
|
|
134
|
+
from superbrain import DistributedContextFabric
|
|
135
|
+
|
|
136
|
+
fabric = DistributedContextFabric(coordinator="localhost:50050")
|
|
137
|
+
ctx = fabric.create_context("session-42")
|
|
138
|
+
|
|
139
|
+
ctx.write("state", {"step": 10}) # written to distributed RAM
|
|
140
|
+
ctx.read("state") # read from any machine
|
|
141
|
+
# No free() β
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
β [Full Memory Management Guide](https://github.com/anispy211/superbrainSdk/blob/main/DOCUMENTATION.md#memory-management--when-to-free)
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
115
148
|
## π Security Features
|
|
116
149
|
|
|
117
150
|
| Feature | Status |
|
|
@@ -131,10 +164,14 @@ The Coordinator is ONLY in the control path (allocate + free).
|
|
|
131
164
|
|---------|-----------|--------|
|
|
132
165
|
| `v0.1.0` | Core Distributed RAM | β
Shipped |
|
|
133
166
|
| `v0.1.1` | Secure Fabric (mTLS + E2EE) | β
Shipped |
|
|
134
|
-
| `v0.2.0` | **Phase 3: Automated AI Memory Controller** | β
|
|
135
|
-
| `v0.3.
|
|
136
|
-
| `v0.4.0` |
|
|
137
|
-
| `v0.5.0` |
|
|
167
|
+
| `v0.2.0` | **Phase 3: Automated AI Memory Controller** | β
Shipped |
|
|
168
|
+
| `v0.3.1` | Semantic Memory (FAISS-Backed Distributed Vectors) | β
Shipped |
|
|
169
|
+
| `v0.4.0` | Gossip & P2P Membership | β
Shipped |
|
|
170
|
+
| `v0.5.0` | High Availability & Partition Tolerance | β
Shipped |
|
|
171
|
+
| `v0.6.0` | Decentralized Observability & Metrics | β
Shipped |
|
|
172
|
+
| `v0.7.1` | **Tiered Architecture & Zero-Copy SHM Bypass** | β
**Current** |
|
|
173
|
+
| `v0.8.0` | Raft Consensus Replication | β
Shipped |
|
|
174
|
+
| `v0.9.0` | NVMe Spilling | β
Shipped |
|
|
138
175
|
|
|
139
176
|
---
|
|
140
177
|
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superbrain-distributed-sdk",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Premium High-Performance Distributed Memory SDK for AI Agents",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
"engines": {
|
|
31
31
|
"node": ">=18.0.0"
|
|
32
32
|
},
|
|
33
|
+
"files": [
|
|
34
|
+
"index.js",
|
|
35
|
+
"index.d.ts",
|
|
36
|
+
"lib/*"
|
|
37
|
+
],
|
|
33
38
|
"dependencies": {
|
|
34
39
|
"koffi": "^2.15.1"
|
|
35
40
|
},
|
package/demo.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const index_1 = require("./index");
|
|
4
|
-
async function main() {
|
|
5
|
-
console.log("π€ Node.js Superbrain Agent Demo");
|
|
6
|
-
try {
|
|
7
|
-
// We will assume the local cluster is running from earlier commands on port 50050
|
|
8
|
-
const client = new index_1.Client('localhost:50050');
|
|
9
|
-
console.log("β
Custom Client initialized");
|
|
10
|
-
client.register("typescript-demo-agent");
|
|
11
|
-
console.log("β
Agent registered to Secure Fabric");
|
|
12
|
-
const dataStr = "Hello from Node.js (TypeScript) via Koffi/gRPC!";
|
|
13
|
-
const dataBytes = Buffer.from(dataStr, 'utf-8');
|
|
14
|
-
const ptr = client.allocate(dataBytes.length + 128);
|
|
15
|
-
console.log(`β
Allocated pointer: ${ptr}`);
|
|
16
|
-
client.write(ptr, 0, dataBytes);
|
|
17
|
-
console.log(`β
Wrote data to pointer`);
|
|
18
|
-
const readBuf = client.read(ptr, 0, dataBytes.length + 128);
|
|
19
|
-
// Remove null padding
|
|
20
|
-
const resultStr = readBuf.toString('utf-8').replace(/\0/g, '');
|
|
21
|
-
console.log(`β
Read verified: ${resultStr}`);
|
|
22
|
-
client.free(ptr);
|
|
23
|
-
console.log("π§Ή Memory freed.");
|
|
24
|
-
}
|
|
25
|
-
catch (err) {
|
|
26
|
-
console.error("Failed to run demo:", err.message);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
main();
|
package/demo.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Client, SuperbrainError } from './index';
|
|
2
|
-
|
|
3
|
-
async function main() {
|
|
4
|
-
console.log("π€ Node.js Superbrain Agent Demo");
|
|
5
|
-
|
|
6
|
-
try {
|
|
7
|
-
// We will assume the local cluster is running from earlier commands on port 50050
|
|
8
|
-
const client = new Client('localhost:50050');
|
|
9
|
-
console.log("β
Custom Client initialized");
|
|
10
|
-
|
|
11
|
-
client.register("typescript-demo-agent");
|
|
12
|
-
console.log("β
Agent registered to Secure Fabric");
|
|
13
|
-
|
|
14
|
-
const dataStr = "Hello from Node.js (TypeScript) via Koffi/gRPC!";
|
|
15
|
-
const dataBytes = Buffer.from(dataStr, 'utf-8');
|
|
16
|
-
|
|
17
|
-
const ptr = client.allocate(dataBytes.length + 128);
|
|
18
|
-
console.log(`β
Allocated pointer: ${ptr}`);
|
|
19
|
-
|
|
20
|
-
client.write(ptr, 0, dataBytes);
|
|
21
|
-
console.log(`β
Wrote data to pointer`);
|
|
22
|
-
|
|
23
|
-
const readBuf = client.read(ptr, 0, dataBytes.length + 128);
|
|
24
|
-
|
|
25
|
-
// Remove null padding
|
|
26
|
-
const resultStr = readBuf.toString('utf-8').replace(/\0/g, '');
|
|
27
|
-
console.log(`β
Read verified: ${resultStr}`);
|
|
28
|
-
|
|
29
|
-
client.free(ptr);
|
|
30
|
-
console.log("π§Ή Memory freed.");
|
|
31
|
-
|
|
32
|
-
} catch (err: any) {
|
|
33
|
-
console.error("Failed to run demo:", err.message);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
main();
|
package/index.ts
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import koffi from 'koffi';
|
|
2
|
-
import * as os from 'os';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
import * as fs from 'fs';
|
|
5
|
-
|
|
6
|
-
export class SuperbrainError extends Error {
|
|
7
|
-
constructor(message: string) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = 'SuperbrainError';
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Locate shared library
|
|
14
|
-
const libName = os.platform() === 'darwin' ? 'libsuperbrain.dylib' : 'libsuperbrain.so';
|
|
15
|
-
|
|
16
|
-
// Try finding it correctly in the package or local structure
|
|
17
|
-
let libPath = path.join(__dirname, '..', '..', 'lib', libName);
|
|
18
|
-
if (!fs.existsSync(libPath)) {
|
|
19
|
-
libPath = path.join(process.cwd(), libName);
|
|
20
|
-
}
|
|
21
|
-
if (!fs.existsSync(libPath)) {
|
|
22
|
-
libPath = path.join(process.cwd(), '..', 'lib', libName);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (!fs.existsSync(libPath)) {
|
|
26
|
-
throw new SuperbrainError(`Shared library ${libName} not found at ${libPath}. Ensure it is built and in the correct path.`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const lib = koffi.load(libPath);
|
|
30
|
-
|
|
31
|
-
// C Bindings
|
|
32
|
-
const SB_NewClient = lib.func('SB_NewClient', 'str', ['str']);
|
|
33
|
-
const SB_NewClientWithEncryption = lib.func('SB_NewClientWithEncryption', 'str', ['str', 'uint8_t*', 'int']);
|
|
34
|
-
const SB_Register = lib.func('SB_Register', 'str', ['str', 'str']);
|
|
35
|
-
const SB_Allocate = lib.func('SB_Allocate', 'str', ['str', 'uint64_t']);
|
|
36
|
-
const SB_Write = lib.func('SB_Write', 'str', ['str', 'str', 'uint64_t', 'uint8_t*', 'uint64_t']);
|
|
37
|
-
const SB_Read = lib.func('SB_Read', 'str', ['str', 'str', 'uint64_t', 'uint64_t', '_Out_ uint8_t**', '_Out_ uint64_t*']);
|
|
38
|
-
const SB_Free = lib.func('SB_Free', 'str', ['str', 'str']);
|
|
39
|
-
|
|
40
|
-
export class Client {
|
|
41
|
-
private clientId: string;
|
|
42
|
-
|
|
43
|
-
constructor(addrs: string, encryptionKey?: Buffer) {
|
|
44
|
-
let res: string;
|
|
45
|
-
if (encryptionKey) {
|
|
46
|
-
if (encryptionKey.length !== 32) {
|
|
47
|
-
throw new SuperbrainError('Encryption key must be exactly 32 bytes for AES-GCM-256');
|
|
48
|
-
}
|
|
49
|
-
res = SB_NewClientWithEncryption(addrs, encryptionKey, encryptionKey.length);
|
|
50
|
-
} else {
|
|
51
|
-
res = SB_NewClient(addrs);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (res && res.startsWith('error:')) {
|
|
55
|
-
throw new SuperbrainError(res);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
this.clientId = res;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public register(agentId: string): void {
|
|
62
|
-
const res = SB_Register(this.clientId, agentId);
|
|
63
|
-
if (res && res.startsWith('error:')) {
|
|
64
|
-
throw new SuperbrainError(res);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
public allocate(size: number): string {
|
|
69
|
-
const res = SB_Allocate(this.clientId, size);
|
|
70
|
-
if (res && res.startsWith('error:')) {
|
|
71
|
-
throw new SuperbrainError(res);
|
|
72
|
-
}
|
|
73
|
-
return res;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
public write(ptrId: string, offset: number, data: Buffer): void {
|
|
77
|
-
const res = SB_Write(this.clientId, ptrId, offset, data, data.length);
|
|
78
|
-
if (res && res.startsWith('error:')) {
|
|
79
|
-
throw new SuperbrainError(res);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public read(ptrId: string, offset: number, length: number): Buffer {
|
|
84
|
-
// Output pointers for koffi
|
|
85
|
-
const outDataPtr = [null];
|
|
86
|
-
const outLenPtr = [0];
|
|
87
|
-
|
|
88
|
-
const res = SB_Read(this.clientId, ptrId, offset, length, outDataPtr, outLenPtr);
|
|
89
|
-
|
|
90
|
-
if (res && res.startsWith('error:')) {
|
|
91
|
-
throw new SuperbrainError(res);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const outBufPtr = outDataPtr[0] as any;
|
|
95
|
-
const outLen = outLenPtr[0] as number;
|
|
96
|
-
|
|
97
|
-
if (!outBufPtr || outLen === 0) {
|
|
98
|
-
return Buffer.alloc(0);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Decode the C string memory pointer into a Buffer
|
|
102
|
-
const decodedBuffer = koffi.decode(outBufPtr, 'uint8_t', outLen);
|
|
103
|
-
const buffer = Buffer.from(decodedBuffer);
|
|
104
|
-
|
|
105
|
-
// Note: C-allocated pointer memory leak if we don't C-free,
|
|
106
|
-
// but for now Superbrain handles general lifecycle cleanup
|
|
107
|
-
// when client exists or pointer freed.
|
|
108
|
-
|
|
109
|
-
return buffer;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
public free(ptrId: string): void {
|
|
113
|
-
const res = SB_Free(this.clientId, ptrId);
|
|
114
|
-
if (res && res.startsWith('error:')) {
|
|
115
|
-
throw new SuperbrainError(res);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2022",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"esModuleInterop": true,
|
|
6
|
-
"forceConsistentCasingInFileNames": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"resolveJsonModule": true,
|
|
10
|
-
"types": [
|
|
11
|
-
"node"
|
|
12
|
-
]
|
|
13
|
-
},
|
|
14
|
-
"ts-node": {
|
|
15
|
-
"esm": true
|
|
16
|
-
}
|
|
17
|
-
}
|