mneme-sdk 0.0.1
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 +89 -0
- package/dist/index.cjs +201 -0
- package/dist/index.d.cts +169 -0
- package/dist/index.d.ts +169 -0
- package/dist/index.js +168 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# mneme-sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for **Mneme** — agent-native data layer on Base. Wallet-signed
|
|
4
|
+
requests, opinionated tables built for agents (`memories`, `documents`,
|
|
5
|
+
`events`, `kvs`), pgvector KNN out of the box.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add mneme-sdk viem
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quickstart
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
15
|
+
import { Mneme } from "mneme-sdk";
|
|
16
|
+
|
|
17
|
+
const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
|
|
18
|
+
|
|
19
|
+
const m = new Mneme({
|
|
20
|
+
account,
|
|
21
|
+
gatewayUrl: "https://gateway.mnemedb.dev",
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Remember
|
|
25
|
+
await m.memories.insert({
|
|
26
|
+
text: "User prefers dark mode and Turkish",
|
|
27
|
+
embedding: embed("...") // 1536-dim, your embedder of choice
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Recall by recency
|
|
31
|
+
const { rows } = await m.memories.list({ limit: 20 });
|
|
32
|
+
|
|
33
|
+
// Recall by meaning (pgvector KNN)
|
|
34
|
+
const { matches } = await m.vectorSearch({
|
|
35
|
+
table: "memories",
|
|
36
|
+
embedding: queryVec,
|
|
37
|
+
k: 5,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Key-value store
|
|
41
|
+
await m.kvs.insert({ key: "last_login", value: { at: Date.now() } });
|
|
42
|
+
|
|
43
|
+
// Append-only event log
|
|
44
|
+
await m.events.insert({ kind: "tool.call", payload: { tool: "search" } });
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Auth
|
|
48
|
+
|
|
49
|
+
No API keys. Every request is signed by the agent's wallet via EIP-712 typed
|
|
50
|
+
data. The gateway verifies the signature, mints a short-lived Supabase JWT
|
|
51
|
+
with the wallet as `agent_id`, and PostgREST + RLS enforces isolation — every
|
|
52
|
+
agent only sees its own rows.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// What gets signed (MnemeRequest typed-data):
|
|
56
|
+
{
|
|
57
|
+
method: "POST",
|
|
58
|
+
path: "/v1/rows/memories",
|
|
59
|
+
bodyHash: keccak256(utf8(requestBody)),
|
|
60
|
+
timestamp: <unix seconds>,
|
|
61
|
+
nonce: <16 random bytes hex>,
|
|
62
|
+
}
|
|
63
|
+
// Domain: { name: "Mneme", version: "1", chainId: 8453 }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Errors
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { MnemeError } from "mneme-sdk";
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await m.memories.insert({ text: "hi" });
|
|
73
|
+
} catch (e) {
|
|
74
|
+
if (e instanceof MnemeError) console.error(e.status, e.message);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Collections
|
|
79
|
+
|
|
80
|
+
| Collection | Row shape |
|
|
81
|
+
|-----------------|------------------------------------------------------------|
|
|
82
|
+
| `m.memories` | `{ text, embedding?, metadata? }` |
|
|
83
|
+
| `m.documents` | `{ title?, body, embedding?, metadata? }` |
|
|
84
|
+
| `m.events` | `{ kind, payload? }` |
|
|
85
|
+
| `m.kvs` | `{ key, value }` |
|
|
86
|
+
|
|
87
|
+
Need a custom table? Edit `gateway/supabase-setup.sql` in the Mneme repo +
|
|
88
|
+
add the table name to `ALLOWED_TABLES` in `gateway/src/db.ts`. Schemas are
|
|
89
|
+
managed at deploy time, not at runtime.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
COLUMN_TYPES: () => COLUMN_TYPES,
|
|
24
|
+
Collection: () => Collection,
|
|
25
|
+
DEFAULT_TABLES: () => DEFAULT_TABLES,
|
|
26
|
+
MNEME_TYPES: () => MNEME_TYPES,
|
|
27
|
+
Mneme: () => Mneme,
|
|
28
|
+
MnemeError: () => MnemeError,
|
|
29
|
+
signRequest: () => signRequest
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(index_exports);
|
|
32
|
+
|
|
33
|
+
// src/sign.ts
|
|
34
|
+
var import_viem = require("viem");
|
|
35
|
+
var MNEME_TYPES = {
|
|
36
|
+
MnemeRequest: [
|
|
37
|
+
{ name: "method", type: "string" },
|
|
38
|
+
{ name: "path", type: "string" },
|
|
39
|
+
{ name: "bodyHash", type: "bytes32" },
|
|
40
|
+
{ name: "timestamp", type: "uint256" },
|
|
41
|
+
{ name: "nonce", type: "string" }
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
async function signRequest(p) {
|
|
45
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
46
|
+
const nonce = randomNonce();
|
|
47
|
+
const bodyHash = (0, import_viem.keccak256)((0, import_viem.toBytes)(p.body));
|
|
48
|
+
if (!p.account.signTypedData) {
|
|
49
|
+
throw new Error("Account must support signTypedData (use privateKeyToAccount or a viem LocalAccount)");
|
|
50
|
+
}
|
|
51
|
+
const signature = await p.account.signTypedData({
|
|
52
|
+
domain: { name: p.domainName, version: p.domainVersion, chainId: p.chainId },
|
|
53
|
+
types: MNEME_TYPES,
|
|
54
|
+
primaryType: "MnemeRequest",
|
|
55
|
+
message: {
|
|
56
|
+
method: p.method,
|
|
57
|
+
path: p.path,
|
|
58
|
+
bodyHash,
|
|
59
|
+
timestamp: BigInt(timestamp),
|
|
60
|
+
nonce
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
"X-Mneme-Wallet": p.account.address,
|
|
65
|
+
"X-Mneme-Timestamp": String(timestamp),
|
|
66
|
+
"X-Mneme-Nonce": nonce,
|
|
67
|
+
"Authorization": `Mneme ${signature}`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function randomNonce() {
|
|
71
|
+
const bytes = new Uint8Array(16);
|
|
72
|
+
crypto.getRandomValues(bytes);
|
|
73
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/client.ts
|
|
77
|
+
var MnemeError = class extends Error {
|
|
78
|
+
constructor(status, message) {
|
|
79
|
+
super(message);
|
|
80
|
+
this.status = status;
|
|
81
|
+
this.name = "MnemeError";
|
|
82
|
+
}
|
|
83
|
+
status;
|
|
84
|
+
};
|
|
85
|
+
var Mneme = class {
|
|
86
|
+
auth;
|
|
87
|
+
gatewayUrl;
|
|
88
|
+
chainId;
|
|
89
|
+
domainName;
|
|
90
|
+
domainVersion;
|
|
91
|
+
/** Convenience accessors for the four always-on default tables. */
|
|
92
|
+
memories;
|
|
93
|
+
documents;
|
|
94
|
+
events;
|
|
95
|
+
kvs;
|
|
96
|
+
constructor(opts) {
|
|
97
|
+
this.auth = "accessToken" in opts && opts.accessToken ? { accessToken: opts.accessToken } : { account: opts.account };
|
|
98
|
+
this.gatewayUrl = opts.gatewayUrl.replace(/\/$/, "");
|
|
99
|
+
this.chainId = opts.chainId ?? 8453;
|
|
100
|
+
this.domainName = opts.domainName ?? "Mneme";
|
|
101
|
+
this.domainVersion = opts.domainVersion ?? "1";
|
|
102
|
+
this.memories = new Collection(this, "memories");
|
|
103
|
+
this.documents = new Collection(this, "documents");
|
|
104
|
+
this.events = new Collection(this, "events");
|
|
105
|
+
this.kvs = new Collection(this, "kvs");
|
|
106
|
+
}
|
|
107
|
+
// ─── DDL ──────────────────────────────────────────────────────────────────
|
|
108
|
+
createTable(args) {
|
|
109
|
+
return this.request("POST", "/v1/tables", args);
|
|
110
|
+
}
|
|
111
|
+
listTables() {
|
|
112
|
+
return this.request("GET", "/v1/tables");
|
|
113
|
+
}
|
|
114
|
+
// ─── Vector & stats ───────────────────────────────────────────────────────
|
|
115
|
+
vectorSearch(args) {
|
|
116
|
+
return this.request("POST", "/v1/vector/search", args);
|
|
117
|
+
}
|
|
118
|
+
stats() {
|
|
119
|
+
return this.request("GET", "/v1/stats");
|
|
120
|
+
}
|
|
121
|
+
// ─── Generic CRUD against any table the agent owns ───────────────────────
|
|
122
|
+
from(table) {
|
|
123
|
+
return new Collection(this, table);
|
|
124
|
+
}
|
|
125
|
+
async request(method, path, body) {
|
|
126
|
+
const bodyText = body === void 0 ? "" : JSON.stringify(body);
|
|
127
|
+
const headers = { "Content-Type": "application/json" };
|
|
128
|
+
if ("accessToken" in this.auth && this.auth.accessToken) {
|
|
129
|
+
headers["Authorization"] = `Bearer ${this.auth.accessToken}`;
|
|
130
|
+
} else if ("account" in this.auth && this.auth.account) {
|
|
131
|
+
const signed = await signRequest({
|
|
132
|
+
account: this.auth.account,
|
|
133
|
+
chainId: this.chainId,
|
|
134
|
+
domainName: this.domainName,
|
|
135
|
+
domainVersion: this.domainVersion,
|
|
136
|
+
method,
|
|
137
|
+
path,
|
|
138
|
+
body: bodyText
|
|
139
|
+
});
|
|
140
|
+
Object.assign(headers, signed);
|
|
141
|
+
} else {
|
|
142
|
+
throw new Error("Mneme: either { account } or { accessToken } is required");
|
|
143
|
+
}
|
|
144
|
+
const res = await fetch(`${this.gatewayUrl}${path}`, {
|
|
145
|
+
method,
|
|
146
|
+
headers,
|
|
147
|
+
body: method === "GET" ? void 0 : bodyText
|
|
148
|
+
});
|
|
149
|
+
const json = await res.json().catch(() => ({}));
|
|
150
|
+
if (!res.ok) throw new MnemeError(res.status, json.error ?? "request failed");
|
|
151
|
+
return json;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
var Collection = class {
|
|
155
|
+
constructor(mneme, table) {
|
|
156
|
+
this.mneme = mneme;
|
|
157
|
+
this.table = table;
|
|
158
|
+
}
|
|
159
|
+
mneme;
|
|
160
|
+
table;
|
|
161
|
+
insert(rows) {
|
|
162
|
+
return this.mneme.request(
|
|
163
|
+
"POST",
|
|
164
|
+
`/v1/rows/${this.table}`,
|
|
165
|
+
rows
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
list(opts) {
|
|
169
|
+
const q = new URLSearchParams();
|
|
170
|
+
if (opts?.limit != null) q.set("limit", String(opts.limit));
|
|
171
|
+
if (opts?.offset != null) q.set("offset", String(opts.offset));
|
|
172
|
+
if (opts?.order) q.set("order", opts.order);
|
|
173
|
+
const qs = q.toString() ? `?${q}` : "";
|
|
174
|
+
return this.mneme.request("GET", `/v1/rows/${this.table}${qs}`);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/types.ts
|
|
179
|
+
var COLUMN_TYPES = [
|
|
180
|
+
"text",
|
|
181
|
+
"int",
|
|
182
|
+
"bigint",
|
|
183
|
+
"bool",
|
|
184
|
+
"jsonb",
|
|
185
|
+
"timestamptz",
|
|
186
|
+
"vector",
|
|
187
|
+
"numeric",
|
|
188
|
+
"uuid",
|
|
189
|
+
"date"
|
|
190
|
+
];
|
|
191
|
+
var DEFAULT_TABLES = ["memories", "documents", "events", "kvs"];
|
|
192
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
193
|
+
0 && (module.exports = {
|
|
194
|
+
COLUMN_TYPES,
|
|
195
|
+
Collection,
|
|
196
|
+
DEFAULT_TABLES,
|
|
197
|
+
MNEME_TYPES,
|
|
198
|
+
Mneme,
|
|
199
|
+
MnemeError,
|
|
200
|
+
signRequest
|
|
201
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { Account } from 'viem';
|
|
2
|
+
|
|
3
|
+
declare const COLUMN_TYPES: readonly ["text", "int", "bigint", "bool", "jsonb", "timestamptz", "vector", "numeric", "uuid", "date"];
|
|
4
|
+
type ColumnType = (typeof COLUMN_TYPES)[number];
|
|
5
|
+
interface ColumnDef {
|
|
6
|
+
name: string;
|
|
7
|
+
type: ColumnType;
|
|
8
|
+
/** Required when `type === "vector"`. 1–4096. */
|
|
9
|
+
dim?: number;
|
|
10
|
+
nullable?: boolean;
|
|
11
|
+
unique?: boolean;
|
|
12
|
+
primaryKey?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface CreateTableArgs {
|
|
15
|
+
name: string;
|
|
16
|
+
columns: ColumnDef[];
|
|
17
|
+
}
|
|
18
|
+
interface ColumnInfo {
|
|
19
|
+
name: string;
|
|
20
|
+
type: string;
|
|
21
|
+
nullable: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface TableInfo {
|
|
24
|
+
name: string;
|
|
25
|
+
isDefault: boolean;
|
|
26
|
+
rowCount: number;
|
|
27
|
+
columns: ColumnInfo[];
|
|
28
|
+
}
|
|
29
|
+
interface VectorSearchArgs {
|
|
30
|
+
table: string;
|
|
31
|
+
column: string;
|
|
32
|
+
embedding: number[];
|
|
33
|
+
k?: number;
|
|
34
|
+
}
|
|
35
|
+
declare const DEFAULT_TABLES: readonly ["memories", "documents", "events", "kvs"];
|
|
36
|
+
type DefaultTable = (typeof DEFAULT_TABLES)[number];
|
|
37
|
+
interface MemoryRow {
|
|
38
|
+
id?: number;
|
|
39
|
+
text: string;
|
|
40
|
+
embedding?: number[];
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
created_at?: string;
|
|
43
|
+
}
|
|
44
|
+
interface DocumentRow {
|
|
45
|
+
id?: number;
|
|
46
|
+
title?: string;
|
|
47
|
+
body: string;
|
|
48
|
+
embedding?: number[];
|
|
49
|
+
metadata?: Record<string, unknown>;
|
|
50
|
+
created_at?: string;
|
|
51
|
+
}
|
|
52
|
+
interface EventRow {
|
|
53
|
+
id?: number;
|
|
54
|
+
kind: string;
|
|
55
|
+
payload?: Record<string, unknown>;
|
|
56
|
+
created_at?: string;
|
|
57
|
+
}
|
|
58
|
+
interface KvRow {
|
|
59
|
+
key: string;
|
|
60
|
+
value: unknown;
|
|
61
|
+
updated_at?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
type MnemeAuth = {
|
|
65
|
+
account: Account;
|
|
66
|
+
accessToken?: never;
|
|
67
|
+
} | {
|
|
68
|
+
accessToken: string;
|
|
69
|
+
account?: never;
|
|
70
|
+
};
|
|
71
|
+
type MnemeOptions = MnemeAuth & {
|
|
72
|
+
gatewayUrl: string;
|
|
73
|
+
chainId?: number;
|
|
74
|
+
domainName?: string;
|
|
75
|
+
domainVersion?: string;
|
|
76
|
+
};
|
|
77
|
+
interface StatsResponse {
|
|
78
|
+
tables: Record<string, number>;
|
|
79
|
+
totals: {
|
|
80
|
+
rows: number;
|
|
81
|
+
default_tables: number;
|
|
82
|
+
custom_tables: number;
|
|
83
|
+
vector_searches_today: number;
|
|
84
|
+
mneme_burned_total: number;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
declare class MnemeError extends Error {
|
|
88
|
+
status: number;
|
|
89
|
+
constructor(status: number, message: string);
|
|
90
|
+
}
|
|
91
|
+
declare class Mneme {
|
|
92
|
+
private auth;
|
|
93
|
+
private gatewayUrl;
|
|
94
|
+
private chainId;
|
|
95
|
+
private domainName;
|
|
96
|
+
private domainVersion;
|
|
97
|
+
/** Convenience accessors for the four always-on default tables. */
|
|
98
|
+
readonly memories: Collection<MemoryRow>;
|
|
99
|
+
readonly documents: Collection<DocumentRow>;
|
|
100
|
+
readonly events: Collection<EventRow>;
|
|
101
|
+
readonly kvs: Collection<KvRow>;
|
|
102
|
+
constructor(opts: MnemeOptions);
|
|
103
|
+
createTable(args: CreateTableArgs): Promise<{
|
|
104
|
+
ok: true;
|
|
105
|
+
table: string;
|
|
106
|
+
}>;
|
|
107
|
+
listTables(): Promise<{
|
|
108
|
+
tables: TableInfo[];
|
|
109
|
+
}>;
|
|
110
|
+
vectorSearch(args: VectorSearchArgs): Promise<{
|
|
111
|
+
matches: unknown[];
|
|
112
|
+
}>;
|
|
113
|
+
stats(): Promise<StatsResponse>;
|
|
114
|
+
from<T = unknown>(table: string): Collection<T>;
|
|
115
|
+
request<T = unknown>(method: string, path: string, body?: unknown): Promise<T>;
|
|
116
|
+
}
|
|
117
|
+
declare class Collection<T = unknown> {
|
|
118
|
+
private mneme;
|
|
119
|
+
readonly table: string;
|
|
120
|
+
constructor(mneme: Mneme, table: string);
|
|
121
|
+
insert(rows: T | T[]): Promise<{
|
|
122
|
+
inserted: number;
|
|
123
|
+
rows: T[];
|
|
124
|
+
}>;
|
|
125
|
+
list(opts?: {
|
|
126
|
+
limit?: number;
|
|
127
|
+
offset?: number;
|
|
128
|
+
order?: string;
|
|
129
|
+
}): Promise<{
|
|
130
|
+
rows: T[];
|
|
131
|
+
}>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
declare const MNEME_TYPES: {
|
|
135
|
+
readonly MnemeRequest: readonly [{
|
|
136
|
+
readonly name: "method";
|
|
137
|
+
readonly type: "string";
|
|
138
|
+
}, {
|
|
139
|
+
readonly name: "path";
|
|
140
|
+
readonly type: "string";
|
|
141
|
+
}, {
|
|
142
|
+
readonly name: "bodyHash";
|
|
143
|
+
readonly type: "bytes32";
|
|
144
|
+
}, {
|
|
145
|
+
readonly name: "timestamp";
|
|
146
|
+
readonly type: "uint256";
|
|
147
|
+
}, {
|
|
148
|
+
readonly name: "nonce";
|
|
149
|
+
readonly type: "string";
|
|
150
|
+
}];
|
|
151
|
+
};
|
|
152
|
+
interface SignRequestParams {
|
|
153
|
+
account: Account;
|
|
154
|
+
chainId: number;
|
|
155
|
+
domainName: string;
|
|
156
|
+
domainVersion: string;
|
|
157
|
+
method: string;
|
|
158
|
+
path: string;
|
|
159
|
+
body: string;
|
|
160
|
+
}
|
|
161
|
+
interface SignedHeaders {
|
|
162
|
+
"X-Mneme-Wallet": string;
|
|
163
|
+
"X-Mneme-Timestamp": string;
|
|
164
|
+
"X-Mneme-Nonce": string;
|
|
165
|
+
"Authorization": string;
|
|
166
|
+
}
|
|
167
|
+
declare function signRequest(p: SignRequestParams): Promise<SignedHeaders>;
|
|
168
|
+
|
|
169
|
+
export { COLUMN_TYPES, Collection, type ColumnDef, type ColumnInfo, type ColumnType, type CreateTableArgs, DEFAULT_TABLES, type DefaultTable, type DocumentRow, type EventRow, type KvRow, MNEME_TYPES, type MemoryRow, Mneme, type MnemeAuth, MnemeError, type MnemeOptions, type SignRequestParams, type SignedHeaders, type StatsResponse, type TableInfo, type VectorSearchArgs, signRequest };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { Account } from 'viem';
|
|
2
|
+
|
|
3
|
+
declare const COLUMN_TYPES: readonly ["text", "int", "bigint", "bool", "jsonb", "timestamptz", "vector", "numeric", "uuid", "date"];
|
|
4
|
+
type ColumnType = (typeof COLUMN_TYPES)[number];
|
|
5
|
+
interface ColumnDef {
|
|
6
|
+
name: string;
|
|
7
|
+
type: ColumnType;
|
|
8
|
+
/** Required when `type === "vector"`. 1–4096. */
|
|
9
|
+
dim?: number;
|
|
10
|
+
nullable?: boolean;
|
|
11
|
+
unique?: boolean;
|
|
12
|
+
primaryKey?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface CreateTableArgs {
|
|
15
|
+
name: string;
|
|
16
|
+
columns: ColumnDef[];
|
|
17
|
+
}
|
|
18
|
+
interface ColumnInfo {
|
|
19
|
+
name: string;
|
|
20
|
+
type: string;
|
|
21
|
+
nullable: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface TableInfo {
|
|
24
|
+
name: string;
|
|
25
|
+
isDefault: boolean;
|
|
26
|
+
rowCount: number;
|
|
27
|
+
columns: ColumnInfo[];
|
|
28
|
+
}
|
|
29
|
+
interface VectorSearchArgs {
|
|
30
|
+
table: string;
|
|
31
|
+
column: string;
|
|
32
|
+
embedding: number[];
|
|
33
|
+
k?: number;
|
|
34
|
+
}
|
|
35
|
+
declare const DEFAULT_TABLES: readonly ["memories", "documents", "events", "kvs"];
|
|
36
|
+
type DefaultTable = (typeof DEFAULT_TABLES)[number];
|
|
37
|
+
interface MemoryRow {
|
|
38
|
+
id?: number;
|
|
39
|
+
text: string;
|
|
40
|
+
embedding?: number[];
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
created_at?: string;
|
|
43
|
+
}
|
|
44
|
+
interface DocumentRow {
|
|
45
|
+
id?: number;
|
|
46
|
+
title?: string;
|
|
47
|
+
body: string;
|
|
48
|
+
embedding?: number[];
|
|
49
|
+
metadata?: Record<string, unknown>;
|
|
50
|
+
created_at?: string;
|
|
51
|
+
}
|
|
52
|
+
interface EventRow {
|
|
53
|
+
id?: number;
|
|
54
|
+
kind: string;
|
|
55
|
+
payload?: Record<string, unknown>;
|
|
56
|
+
created_at?: string;
|
|
57
|
+
}
|
|
58
|
+
interface KvRow {
|
|
59
|
+
key: string;
|
|
60
|
+
value: unknown;
|
|
61
|
+
updated_at?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
type MnemeAuth = {
|
|
65
|
+
account: Account;
|
|
66
|
+
accessToken?: never;
|
|
67
|
+
} | {
|
|
68
|
+
accessToken: string;
|
|
69
|
+
account?: never;
|
|
70
|
+
};
|
|
71
|
+
type MnemeOptions = MnemeAuth & {
|
|
72
|
+
gatewayUrl: string;
|
|
73
|
+
chainId?: number;
|
|
74
|
+
domainName?: string;
|
|
75
|
+
domainVersion?: string;
|
|
76
|
+
};
|
|
77
|
+
interface StatsResponse {
|
|
78
|
+
tables: Record<string, number>;
|
|
79
|
+
totals: {
|
|
80
|
+
rows: number;
|
|
81
|
+
default_tables: number;
|
|
82
|
+
custom_tables: number;
|
|
83
|
+
vector_searches_today: number;
|
|
84
|
+
mneme_burned_total: number;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
declare class MnemeError extends Error {
|
|
88
|
+
status: number;
|
|
89
|
+
constructor(status: number, message: string);
|
|
90
|
+
}
|
|
91
|
+
declare class Mneme {
|
|
92
|
+
private auth;
|
|
93
|
+
private gatewayUrl;
|
|
94
|
+
private chainId;
|
|
95
|
+
private domainName;
|
|
96
|
+
private domainVersion;
|
|
97
|
+
/** Convenience accessors for the four always-on default tables. */
|
|
98
|
+
readonly memories: Collection<MemoryRow>;
|
|
99
|
+
readonly documents: Collection<DocumentRow>;
|
|
100
|
+
readonly events: Collection<EventRow>;
|
|
101
|
+
readonly kvs: Collection<KvRow>;
|
|
102
|
+
constructor(opts: MnemeOptions);
|
|
103
|
+
createTable(args: CreateTableArgs): Promise<{
|
|
104
|
+
ok: true;
|
|
105
|
+
table: string;
|
|
106
|
+
}>;
|
|
107
|
+
listTables(): Promise<{
|
|
108
|
+
tables: TableInfo[];
|
|
109
|
+
}>;
|
|
110
|
+
vectorSearch(args: VectorSearchArgs): Promise<{
|
|
111
|
+
matches: unknown[];
|
|
112
|
+
}>;
|
|
113
|
+
stats(): Promise<StatsResponse>;
|
|
114
|
+
from<T = unknown>(table: string): Collection<T>;
|
|
115
|
+
request<T = unknown>(method: string, path: string, body?: unknown): Promise<T>;
|
|
116
|
+
}
|
|
117
|
+
declare class Collection<T = unknown> {
|
|
118
|
+
private mneme;
|
|
119
|
+
readonly table: string;
|
|
120
|
+
constructor(mneme: Mneme, table: string);
|
|
121
|
+
insert(rows: T | T[]): Promise<{
|
|
122
|
+
inserted: number;
|
|
123
|
+
rows: T[];
|
|
124
|
+
}>;
|
|
125
|
+
list(opts?: {
|
|
126
|
+
limit?: number;
|
|
127
|
+
offset?: number;
|
|
128
|
+
order?: string;
|
|
129
|
+
}): Promise<{
|
|
130
|
+
rows: T[];
|
|
131
|
+
}>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
declare const MNEME_TYPES: {
|
|
135
|
+
readonly MnemeRequest: readonly [{
|
|
136
|
+
readonly name: "method";
|
|
137
|
+
readonly type: "string";
|
|
138
|
+
}, {
|
|
139
|
+
readonly name: "path";
|
|
140
|
+
readonly type: "string";
|
|
141
|
+
}, {
|
|
142
|
+
readonly name: "bodyHash";
|
|
143
|
+
readonly type: "bytes32";
|
|
144
|
+
}, {
|
|
145
|
+
readonly name: "timestamp";
|
|
146
|
+
readonly type: "uint256";
|
|
147
|
+
}, {
|
|
148
|
+
readonly name: "nonce";
|
|
149
|
+
readonly type: "string";
|
|
150
|
+
}];
|
|
151
|
+
};
|
|
152
|
+
interface SignRequestParams {
|
|
153
|
+
account: Account;
|
|
154
|
+
chainId: number;
|
|
155
|
+
domainName: string;
|
|
156
|
+
domainVersion: string;
|
|
157
|
+
method: string;
|
|
158
|
+
path: string;
|
|
159
|
+
body: string;
|
|
160
|
+
}
|
|
161
|
+
interface SignedHeaders {
|
|
162
|
+
"X-Mneme-Wallet": string;
|
|
163
|
+
"X-Mneme-Timestamp": string;
|
|
164
|
+
"X-Mneme-Nonce": string;
|
|
165
|
+
"Authorization": string;
|
|
166
|
+
}
|
|
167
|
+
declare function signRequest(p: SignRequestParams): Promise<SignedHeaders>;
|
|
168
|
+
|
|
169
|
+
export { COLUMN_TYPES, Collection, type ColumnDef, type ColumnInfo, type ColumnType, type CreateTableArgs, DEFAULT_TABLES, type DefaultTable, type DocumentRow, type EventRow, type KvRow, MNEME_TYPES, type MemoryRow, Mneme, type MnemeAuth, MnemeError, type MnemeOptions, type SignRequestParams, type SignedHeaders, type StatsResponse, type TableInfo, type VectorSearchArgs, signRequest };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// src/sign.ts
|
|
2
|
+
import { keccak256, toBytes } from "viem";
|
|
3
|
+
var MNEME_TYPES = {
|
|
4
|
+
MnemeRequest: [
|
|
5
|
+
{ name: "method", type: "string" },
|
|
6
|
+
{ name: "path", type: "string" },
|
|
7
|
+
{ name: "bodyHash", type: "bytes32" },
|
|
8
|
+
{ name: "timestamp", type: "uint256" },
|
|
9
|
+
{ name: "nonce", type: "string" }
|
|
10
|
+
]
|
|
11
|
+
};
|
|
12
|
+
async function signRequest(p) {
|
|
13
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
14
|
+
const nonce = randomNonce();
|
|
15
|
+
const bodyHash = keccak256(toBytes(p.body));
|
|
16
|
+
if (!p.account.signTypedData) {
|
|
17
|
+
throw new Error("Account must support signTypedData (use privateKeyToAccount or a viem LocalAccount)");
|
|
18
|
+
}
|
|
19
|
+
const signature = await p.account.signTypedData({
|
|
20
|
+
domain: { name: p.domainName, version: p.domainVersion, chainId: p.chainId },
|
|
21
|
+
types: MNEME_TYPES,
|
|
22
|
+
primaryType: "MnemeRequest",
|
|
23
|
+
message: {
|
|
24
|
+
method: p.method,
|
|
25
|
+
path: p.path,
|
|
26
|
+
bodyHash,
|
|
27
|
+
timestamp: BigInt(timestamp),
|
|
28
|
+
nonce
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
"X-Mneme-Wallet": p.account.address,
|
|
33
|
+
"X-Mneme-Timestamp": String(timestamp),
|
|
34
|
+
"X-Mneme-Nonce": nonce,
|
|
35
|
+
"Authorization": `Mneme ${signature}`
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function randomNonce() {
|
|
39
|
+
const bytes = new Uint8Array(16);
|
|
40
|
+
crypto.getRandomValues(bytes);
|
|
41
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/client.ts
|
|
45
|
+
var MnemeError = class extends Error {
|
|
46
|
+
constructor(status, message) {
|
|
47
|
+
super(message);
|
|
48
|
+
this.status = status;
|
|
49
|
+
this.name = "MnemeError";
|
|
50
|
+
}
|
|
51
|
+
status;
|
|
52
|
+
};
|
|
53
|
+
var Mneme = class {
|
|
54
|
+
auth;
|
|
55
|
+
gatewayUrl;
|
|
56
|
+
chainId;
|
|
57
|
+
domainName;
|
|
58
|
+
domainVersion;
|
|
59
|
+
/** Convenience accessors for the four always-on default tables. */
|
|
60
|
+
memories;
|
|
61
|
+
documents;
|
|
62
|
+
events;
|
|
63
|
+
kvs;
|
|
64
|
+
constructor(opts) {
|
|
65
|
+
this.auth = "accessToken" in opts && opts.accessToken ? { accessToken: opts.accessToken } : { account: opts.account };
|
|
66
|
+
this.gatewayUrl = opts.gatewayUrl.replace(/\/$/, "");
|
|
67
|
+
this.chainId = opts.chainId ?? 8453;
|
|
68
|
+
this.domainName = opts.domainName ?? "Mneme";
|
|
69
|
+
this.domainVersion = opts.domainVersion ?? "1";
|
|
70
|
+
this.memories = new Collection(this, "memories");
|
|
71
|
+
this.documents = new Collection(this, "documents");
|
|
72
|
+
this.events = new Collection(this, "events");
|
|
73
|
+
this.kvs = new Collection(this, "kvs");
|
|
74
|
+
}
|
|
75
|
+
// ─── DDL ──────────────────────────────────────────────────────────────────
|
|
76
|
+
createTable(args) {
|
|
77
|
+
return this.request("POST", "/v1/tables", args);
|
|
78
|
+
}
|
|
79
|
+
listTables() {
|
|
80
|
+
return this.request("GET", "/v1/tables");
|
|
81
|
+
}
|
|
82
|
+
// ─── Vector & stats ───────────────────────────────────────────────────────
|
|
83
|
+
vectorSearch(args) {
|
|
84
|
+
return this.request("POST", "/v1/vector/search", args);
|
|
85
|
+
}
|
|
86
|
+
stats() {
|
|
87
|
+
return this.request("GET", "/v1/stats");
|
|
88
|
+
}
|
|
89
|
+
// ─── Generic CRUD against any table the agent owns ───────────────────────
|
|
90
|
+
from(table) {
|
|
91
|
+
return new Collection(this, table);
|
|
92
|
+
}
|
|
93
|
+
async request(method, path, body) {
|
|
94
|
+
const bodyText = body === void 0 ? "" : JSON.stringify(body);
|
|
95
|
+
const headers = { "Content-Type": "application/json" };
|
|
96
|
+
if ("accessToken" in this.auth && this.auth.accessToken) {
|
|
97
|
+
headers["Authorization"] = `Bearer ${this.auth.accessToken}`;
|
|
98
|
+
} else if ("account" in this.auth && this.auth.account) {
|
|
99
|
+
const signed = await signRequest({
|
|
100
|
+
account: this.auth.account,
|
|
101
|
+
chainId: this.chainId,
|
|
102
|
+
domainName: this.domainName,
|
|
103
|
+
domainVersion: this.domainVersion,
|
|
104
|
+
method,
|
|
105
|
+
path,
|
|
106
|
+
body: bodyText
|
|
107
|
+
});
|
|
108
|
+
Object.assign(headers, signed);
|
|
109
|
+
} else {
|
|
110
|
+
throw new Error("Mneme: either { account } or { accessToken } is required");
|
|
111
|
+
}
|
|
112
|
+
const res = await fetch(`${this.gatewayUrl}${path}`, {
|
|
113
|
+
method,
|
|
114
|
+
headers,
|
|
115
|
+
body: method === "GET" ? void 0 : bodyText
|
|
116
|
+
});
|
|
117
|
+
const json = await res.json().catch(() => ({}));
|
|
118
|
+
if (!res.ok) throw new MnemeError(res.status, json.error ?? "request failed");
|
|
119
|
+
return json;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
var Collection = class {
|
|
123
|
+
constructor(mneme, table) {
|
|
124
|
+
this.mneme = mneme;
|
|
125
|
+
this.table = table;
|
|
126
|
+
}
|
|
127
|
+
mneme;
|
|
128
|
+
table;
|
|
129
|
+
insert(rows) {
|
|
130
|
+
return this.mneme.request(
|
|
131
|
+
"POST",
|
|
132
|
+
`/v1/rows/${this.table}`,
|
|
133
|
+
rows
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
list(opts) {
|
|
137
|
+
const q = new URLSearchParams();
|
|
138
|
+
if (opts?.limit != null) q.set("limit", String(opts.limit));
|
|
139
|
+
if (opts?.offset != null) q.set("offset", String(opts.offset));
|
|
140
|
+
if (opts?.order) q.set("order", opts.order);
|
|
141
|
+
const qs = q.toString() ? `?${q}` : "";
|
|
142
|
+
return this.mneme.request("GET", `/v1/rows/${this.table}${qs}`);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// src/types.ts
|
|
147
|
+
var COLUMN_TYPES = [
|
|
148
|
+
"text",
|
|
149
|
+
"int",
|
|
150
|
+
"bigint",
|
|
151
|
+
"bool",
|
|
152
|
+
"jsonb",
|
|
153
|
+
"timestamptz",
|
|
154
|
+
"vector",
|
|
155
|
+
"numeric",
|
|
156
|
+
"uuid",
|
|
157
|
+
"date"
|
|
158
|
+
];
|
|
159
|
+
var DEFAULT_TABLES = ["memories", "documents", "events", "kvs"];
|
|
160
|
+
export {
|
|
161
|
+
COLUMN_TYPES,
|
|
162
|
+
Collection,
|
|
163
|
+
DEFAULT_TABLES,
|
|
164
|
+
MNEME_TYPES,
|
|
165
|
+
Mneme,
|
|
166
|
+
MnemeError,
|
|
167
|
+
signRequest
|
|
168
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mneme-sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "TypeScript SDK for Mneme — agent-native Postgres database platform on Base. Wallet-auth, runtime DDL, pgvector built-in.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": ["dist", "README.md"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
19
|
+
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mneme",
|
|
24
|
+
"agent",
|
|
25
|
+
"database",
|
|
26
|
+
"postgres",
|
|
27
|
+
"pgvector",
|
|
28
|
+
"vector",
|
|
29
|
+
"base",
|
|
30
|
+
"wallet",
|
|
31
|
+
"eip712",
|
|
32
|
+
"mcp",
|
|
33
|
+
"ai"
|
|
34
|
+
],
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"homepage": "https://mnemedb.dev",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/mnemedb/mnemedb.git",
|
|
40
|
+
"directory": "sdk"
|
|
41
|
+
},
|
|
42
|
+
"author": "mnemedb",
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"viem": "^2.21.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"tsup": "^8.0.0",
|
|
48
|
+
"typescript": "^5.6.0",
|
|
49
|
+
"viem": "^2.21.0"
|
|
50
|
+
}
|
|
51
|
+
}
|