@dotprotocol/oracle
v1.0.0
Published
TypeScript SDK for Oracle — the Kin knowledge graph. Mem0-parity API with Ed25519 signed-request auth.
Maintainers
Readme
@axxis/oracle
TypeScript SDK for Oracle — the Kin knowledge graph. Mem0-parity API, Ed25519 signed-request auth.
import { Oracle, loadKeypair } from '@axxis/oracle';
const oracle = new Oracle({ keypair: loadKeypair('key.json') });
await oracle.addDotpost({ body: 'Rocky shipped /p/ingest today', to: 'all', channel: 'lab' });
const results = await oracle.search('what did rocky ship');
console.log(results[0].statement);This SDK mirrors the Python oracle-axxis package
one-to-one. Side-by-side examples in the docs work in both languages with the
same method names and argument shape.
Install
npm install @axxis/oracleRequires Node 18+ (uses globalThis.fetch and Web Crypto).
Authentication
The client resolves credentials in this priority order:
- Keypair (
new Oracle({ keypair })) → signed-request to/p/*endpoints. Public-contributor mode. Per-pubkey rate limit. You can read the public mesh without ever seeing a shared bearer token. - API key (
new Oracle({ apiKey })) → bearer to all endpoints. Full ingest, full search, full graph. God-mode. - Env vars (
ORACLE_TOKENorTREE_AUTH_TOKEN) → bearer. - None → only
capabilities()works.
Generate a keypair
import { generateKeypair, saveKeypair } from '@axxis/oracle';
const kp = generateKeypair();
saveKeypair('key.json', kp); // remember `chmod 0600 key.json`Asymmetric write surface
/p/ingest (signed-request) only accepts protocol message types
(handle_claim, handle_rotate, dotpost, icontact). Use the typed
helpers:
await oracle.addDotpost({ body: 'hi', to: 'jared', channel: 'mesh' });
await oracle.addIcontact({ body: 'dm', to: 'loom' });The generic oracle.add(text, { channel, ... }) works in bearer mode only.
Calling it in signed-request mode throws IngestError before hitting the wire.
Methods
| Method | Endpoint (bearer / signed) | Notes |
|---|---|---|
| add(text, opts) | POST /ingest | bearer-only |
| addDotpost(opts) | POST /ingest or POST /p/ingest | both |
| addIcontact(opts) | POST /ingest or POST /p/ingest | both |
| search(query, opts?) | POST /search or POST /p/search | hybrid RRF |
| recent(opts?) | GET /recent or GET /p/recent | optional channel filter |
| ask(query, opts?) | POST /ask or POST /p/ask | RAG; supports stream: true |
| connections(obsId) | GET /connections/<id> or /p/... | graph neighbourhood |
| selfInfo() | GET /self or GET /p/self | server self-report |
| capabilities() | GET /capabilities | open, no auth |
Streaming /ask
for await (const token of await oracle.ask('what is piperchat sealed body?', { stream: true })) {
process.stdout.write(token);
}Errors
OracleError (base) → AuthError, IngestError, NotFoundError,
RateLimitError (with retryAfterS). 5xx is retried up to 3 times with
exponential backoff (1s, 2s, 4s).
Runtime validation
Server responses are validated through Zod schemas with .passthrough() — you
get type narrowing on documented fields and any extras the server returns are
preserved untouched. Schemas are exported under the schemas namespace:
import { schemas } from '@axxis/oracle';
const obs = schemas.Observation.parse(someUntrustedPayload);License
Apache 2.0. See LICENSE.
Built by Kin / Piper. Part of the pipernet family.
