kenun-sdk
v1.0.0
Published
Toolkit to prototype neural signal apps: mock Bluetooth capture, one-step calibration, realtime streaming, Brainlink integration.
Maintainers
Readme
kenun-sdk
🔍 Table of Contents
- Why Use It
- Installation
- Start in 60s
- Calibration Flow
- Sending Signals
- Brainlink Integration
- Essential API
- Core Types
- Quick FAQ
- Scripts / Dev
- Roadmap
- License
- Full Documentation
🤔 Why Use It
| Need | How the SDK helps |
| ------------------------ | -------------------------------------------------------------------------------- |
| Rapid prototyping | Ready mock Bluetooth + realtime sending |
| Simple model calibration | Single calibration.submit method (labeled dataset) |
| Token auto-applied | Default autoSetToken injects into every WebSocket signal |
| Try Brainlink quickly | Built-in ThinkGear parser + cognitive state events |
| Extend later | Modular architecture (bluetooth / calibration / signals / websocket / brainlink) |
This README is intentionally minimal. For internal details open
WIKI.md.
🧪 Installation
npm install kenun-sdkPrerequisite: Node >= 20.
⚡ Start in 60s
import { KenunSDK, CalibrationPayload } from 'kenun-sdk';
const sdk = new KenunSDK({ apiKey: 'MY_KEY' });
await sdk.websocket.connect();
const devices = await sdk.bluetooth.listDevices();
await sdk.bluetooth.connect(devices[0].id);
sdk.bluetooth.onSignalReceived(s => console.log('amp', s.amplitude));
sdk.bluetooth.startCapture({ intervalMs: 200, channels: 4 });
const sample = (): any => ({
timestamp: Date.now(),
channels: [Math.random(), Math.random()],
frequency: 256,
amplitude: Math.random() * 40,
});
const dataset: CalibrationPayload = [
{ signal: 0, samples: [sample(), sample()] },
{ signal: 1, samples: [sample(), sample()] },
];
await sdk.calibration.submit(devices[0].id, dataset); // internal token
sdk.signals.sendRealtime({
sensorId: devices[0].id,
signal: dataset[0].samples[0],
timestamp: Date.now(),
});🎯 Calibration Flow
Single method: calibration.submit(sensorId, dataset, options?)
Dataset (grouped by class):
interface CalibrationSampleGroup {
signal: number; // class (0,1,2,...)
samples: NeuralSignal[]; // >=1
}Options:
interface SubmitDatasetOptions {
autoSetToken?: boolean; // default true (apply on SDK)
tokenOverride?: string; // bypass HTTP response and use a manual token
}Common scenarios:
// Default
await sdk.calibration.submit(id, dataset);
// Manual (don't auto-apply)
const { token } = await sdk.calibration.submit(id, dataset, {
autoSetToken: false,
});
sdk.setCalibrationToken(token);
// Force custom token
await sdk.calibration.submit(id, dataset, { tokenOverride: 'my-token' });Minimal validation: non-empty dataset; each group has signal and samples.length > 0.
📡 Sending Signals
Batch (HTTP):
await sdk.signals.send({
sensorId,
signals: batchSignals,
timestamp: Date.now(),
});Realtime (WebSocket):
sdk.signals.sendRealtime({ sensorId, signal, timestamp: Date.now() });Active calibration token is attached automatically.
🧠 Brainlink Integration
import { SensorModel } from 'kenun-sdk';
await sdk.connectSensor('brainlink-1', { model: SensorModel.BRAINLINK });
sdk.onBrainData(d => console.log('attention', d.attention));
sdk.onCognitiveState(e => console.log('state', e.state));
sdk.feedBytes(rawUint8Array); // raw bytes from device
sdk.sendCurrentBrainDataAsSignal('brainlink-1');Channel mapping -> NeuralSignal.channels:
[delta, theta, lowAlpha, highAlpha, lowBeta, highBeta, lowGamma, midGamma]
amplitude = attention, frequency = 256.
🧩 Essential API
new KenunSDK({ apiKey, timeout? });
// Calibration
await calibration.submit(sensorId, dataset, options?);
getCalibrationToken();
setCalibrationToken(token);
// Bluetooth (mock)
bluetooth.listDevices();
bluetooth.connect(id);
bluetooth.disconnect();
bluetooth.startCapture({ intervalMs?, channels? });
bluetooth.stopCapture();
bluetooth.onSignalReceived(cb);
// Signals
aggregateSignals(signals);
signals.send(batch);
signals.sendRealtime({ sensorId, signal, timestamp });
// WebSocket
websocket.connect();
websocket.disconnect();
websocket.onMessage(cb);
websocket.onError(cb);
websocket.send(obj);
// Brainlink
connectSensor(sensorId, { model: SensorModel.BRAINLINK });
feedBytes(bytes);
onBrainData(cb);
onCognitiveState(cb);
sendCurrentBrainDataAsSignal(sensorId);🧾 Core Types
interface NeuralSignal {
timestamp: number;
channels: number[];
frequency: number;
amplitude: number;
}
interface CalibrationResult {
token: string;
modelVersion?: string;
}
interface AIResponse {
type: 'prediction' | 'analysis' | 'error';
data: any;
timestamp: number;
}Cognitive states: focus | verbal_imagery | rest | blink.
Full list in
src/types/index.ts.
❓ Quick FAQ
Do I need real hardware? No. Everything works in mock mode for ideation.
Can I swap the token without recalibration? Yes: sdk.setCalibrationToken(newToken).
Does the WebSocket auto-reconnect? Not yet (see roadmap).
Do mock signals follow biological patterns? No – they're controlled randomness (prototyping).
Does Brainlink change the base API? No. It only adds callbacks and conversion to NeuralSignal.
🛠 Scripts / Dev
npm run build # compile to lib/
npm test # jest + coverage
npm run lint # eslint + prettier
npm run typecheck # TS type checking🗺 Roadmap
- Bluetooth auto-reconnect
- Offline buffer
- Optional encryption
- Metrics / latency
- WebSocket auto-reconnect
- Payload compression strategies
Contributions via PR / issue are welcome.
📄 License
MIT
📘 Full Documentation
Open WIKI.md for advanced details (protocols, extension, internal architecture).
