xmemory 1.0.0 → 1.2.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 +129 -3
- package/dist/client.d.ts +46 -0
- package/dist/client.js +156 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.js +7 -0
- package/package.json +18 -8
- package/cli.js +0 -6
- package/index.js +0 -11
package/README.md
CHANGED
|
@@ -1,8 +1,134 @@
|
|
|
1
|
-
#
|
|
1
|
+
# xmemory
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript/JavaScript client library for the [Xmemory](https://xmemory.ai) API.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { xmemoryInstance } from "xmemory";
|
|
9
|
+
|
|
10
|
+
const mem = await xmemoryInstance({
|
|
11
|
+
url: "https://api.xmemory.ai", // or set XMEM_API_URL env var
|
|
12
|
+
token: "<your-token>", // or set XMEM_AUTH_TOKEN env var
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
mem.instanceId = "<your-instance-id>";
|
|
16
|
+
|
|
17
|
+
await mem.write("Alice is a software engineer who loves TypeScript.");
|
|
18
|
+
const result = await mem.read("What does Alice do?");
|
|
19
|
+
console.log(result.reader_result?.answer);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install xmemory
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Configuration
|
|
29
|
+
|
|
30
|
+
| Parameter | Env var | Default | Description |
|
|
31
|
+
|-------------|-------------------|---------------------------|---------------------------------------|
|
|
32
|
+
| `url` | `XMEM_API_URL` | `http://0.0.0.0:8000` | Base URL of the Xmemory API |
|
|
33
|
+
| `token` | `XMEM_AUTH_TOKEN` | `undefined` | Bearer token for authentication |
|
|
34
|
+
| `timeoutMs` | — | `60000` | Default request timeout in milliseconds |
|
|
35
|
+
|
|
36
|
+
## Creating a client
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { XmemoryClient, xmemoryInstance } from "xmemory";
|
|
40
|
+
|
|
41
|
+
// Option 1: factory function (runs a health check automatically)
|
|
42
|
+
const mem = await xmemoryInstance({ url: "https://api.xmemory.ai", token: "..." });
|
|
43
|
+
|
|
44
|
+
// Option 2: static create method (also runs a health check)
|
|
45
|
+
const mem = await XmemoryClient.create({ url: "https://api.xmemory.ai", token: "..." });
|
|
46
|
+
|
|
47
|
+
// Option 3: constructor (no health check)
|
|
48
|
+
const mem = new XmemoryClient({ url: "https://api.xmemory.ai", token: "..." });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Methods
|
|
52
|
+
|
|
53
|
+
### `createInstance(schemaText, schemaType, timeoutMs?) → Promise<boolean>`
|
|
54
|
+
|
|
55
|
+
Create a new instance with the given schema. On success the new `instanceId`
|
|
56
|
+
is saved automatically and used for subsequent calls.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { SchemaType } from "xmemory";
|
|
60
|
+
|
|
61
|
+
const ok = await mem.createInstance(schemaYml, SchemaType.YML);
|
|
62
|
+
const ok = await mem.createInstance(schemaJson, SchemaType.JSON);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### `write(text, options?) → Promise<WriteResponse>`
|
|
66
|
+
|
|
67
|
+
Extract structured objects from `text` and store them in the instance.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const resp = await mem.write("Bob joined the team on Monday as a designer.");
|
|
71
|
+
console.log(resp.status); // "ok" or "error"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Options: `{ timeoutMs?, extractionLogic? }` where `extractionLogic` is `"fast"`, `"regular"`, or `"deep"` (default: `"deep"`).
|
|
75
|
+
|
|
76
|
+
### `writeAsync(text, options?) → Promise<AsyncWriteResponse>`
|
|
77
|
+
|
|
78
|
+
Start an asynchronous write and return immediately with a `write_id` for tracking.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
const resp = await mem.writeAsync("Carol is a manager based in Berlin.", {
|
|
82
|
+
extractionLogic: "deep",
|
|
83
|
+
});
|
|
84
|
+
console.log(resp.write_id); // use this to check status
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Options: `{ timeoutMs?, extractionLogic?, extractWriteId? }`.
|
|
88
|
+
|
|
89
|
+
### `writeStatus(writeId, options?) → Promise<WriteStatusResponse>`
|
|
90
|
+
|
|
91
|
+
Check the status of an async write operation.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const status = await mem.writeStatus(resp.write_id);
|
|
95
|
+
console.log(status.write_status); // "queued" | "processing" | "completed" | "failed" | "not_found"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `read(query, options?) → Promise<ReadResponse>`
|
|
99
|
+
|
|
100
|
+
Query the instance and get a natural-language answer.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
const resp = await mem.read("Who is on the team?");
|
|
104
|
+
console.log(resp.reader_result?.answer);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Options: `{ timeoutMs? }`.
|
|
108
|
+
|
|
109
|
+
## Error handling
|
|
110
|
+
|
|
111
|
+
All errors raise `XmemoryAPIError`.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { XmemoryAPIError, xmemoryInstance } from "xmemory";
|
|
115
|
+
|
|
116
|
+
const mem = await xmemoryInstance({ url: "https://api.xmemory.ai", token: "..." });
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const resp = await mem.read("something");
|
|
120
|
+
} catch (e) {
|
|
121
|
+
if (e instanceof XmemoryAPIError) {
|
|
122
|
+
console.error(`API error (HTTP ${e.status}): ${e.message}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Mastra integration
|
|
130
|
+
|
|
131
|
+
You can also use `xmemory` as an MCP server within [Mastra.ai](https://mastra.ai).
|
|
6
132
|
|
|
7
133
|
First, create a local Mastra instance:
|
|
8
134
|
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xmemory HTTP client for Node.js.
|
|
3
|
+
*/
|
|
4
|
+
import type { AsyncWriteResponse, ExtractionLogic, ReadResponse, SchemaTypeValue, WriteResponse, WriteStatusResponse } from "./types.js";
|
|
5
|
+
export { SchemaType } from "./types.js";
|
|
6
|
+
export type { AsyncWriteResponse, CreateInstanceResponse, ExtractionLogic, ReadResponse, ReaderResult, SchemaTypeValue, WriteQueueStatus, WriteResponse, WriteStatusResponse, } from "./types.js";
|
|
7
|
+
export declare class XmemoryAPIError extends Error {
|
|
8
|
+
readonly status?: number | undefined;
|
|
9
|
+
constructor(message: string, status?: number | undefined);
|
|
10
|
+
}
|
|
11
|
+
export interface XmemoryInstanceOptions {
|
|
12
|
+
url?: string;
|
|
13
|
+
token?: string;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class XmemoryClient {
|
|
17
|
+
readonly baseUrl: string;
|
|
18
|
+
readonly timeoutMs: number;
|
|
19
|
+
readonly token: string | undefined;
|
|
20
|
+
instanceId: string | null;
|
|
21
|
+
constructor(options?: XmemoryInstanceOptions);
|
|
22
|
+
static create(options?: XmemoryInstanceOptions): Promise<XmemoryClient>;
|
|
23
|
+
private checkHealth;
|
|
24
|
+
private requireInstanceId;
|
|
25
|
+
createInstance(schemaText: string, schemaType: SchemaTypeValue, timeoutMs?: number): Promise<boolean>;
|
|
26
|
+
write(text: string, options?: {
|
|
27
|
+
timeoutMs?: number;
|
|
28
|
+
extractionLogic?: ExtractionLogic;
|
|
29
|
+
}): Promise<WriteResponse>;
|
|
30
|
+
writeAsync(text: string, options?: {
|
|
31
|
+
timeoutMs?: number;
|
|
32
|
+
extractionLogic?: ExtractionLogic;
|
|
33
|
+
extractWriteId?: string;
|
|
34
|
+
}): Promise<AsyncWriteResponse>;
|
|
35
|
+
writeStatus(writeId: string, options?: {
|
|
36
|
+
timeoutMs?: number;
|
|
37
|
+
}): Promise<WriteStatusResponse>;
|
|
38
|
+
read(query: string, options?: {
|
|
39
|
+
timeoutMs?: number;
|
|
40
|
+
}): Promise<ReadResponse>;
|
|
41
|
+
get instance_id(): string | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create an xmemory client.
|
|
45
|
+
*/
|
|
46
|
+
export declare function xmemoryInstance(options?: XmemoryInstanceOptions): Promise<XmemoryClient>;
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xmemory HTTP client for Node.js.
|
|
3
|
+
*/
|
|
4
|
+
export { SchemaType } from "./types.js";
|
|
5
|
+
const DEFAULT_BASE_URL = "http://0.0.0.0:8000";
|
|
6
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
7
|
+
export class XmemoryAPIError extends Error {
|
|
8
|
+
status;
|
|
9
|
+
constructor(message, status) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.status = status;
|
|
12
|
+
this.name = "XmemoryAPIError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async function getEnv(name) {
|
|
16
|
+
if (typeof process !== "undefined" && process.env) {
|
|
17
|
+
return process.env[name];
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
async function fetchWithTimeout(url, options) {
|
|
22
|
+
const { timeoutMs = DEFAULT_TIMEOUT_MS, ...fetchOptions } = options;
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
const id = setTimeout(() => controller.abort(), timeoutMs);
|
|
25
|
+
try {
|
|
26
|
+
const res = await fetch(url, {
|
|
27
|
+
...fetchOptions,
|
|
28
|
+
signal: controller.signal,
|
|
29
|
+
});
|
|
30
|
+
return res;
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
clearTimeout(id);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function postJson(baseUrl, path, body, token, timeoutMs) {
|
|
37
|
+
const url = `${baseUrl.replace(/\/$/, "")}${path}`;
|
|
38
|
+
const headers = {
|
|
39
|
+
Accept: "application/json",
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
};
|
|
42
|
+
if (token) {
|
|
43
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
44
|
+
}
|
|
45
|
+
const res = await fetchWithTimeout(url, {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers,
|
|
48
|
+
body: JSON.stringify(body),
|
|
49
|
+
timeoutMs,
|
|
50
|
+
});
|
|
51
|
+
const raw = await res.text();
|
|
52
|
+
let payload;
|
|
53
|
+
try {
|
|
54
|
+
payload = raw ? JSON.parse(raw) : {};
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
throw new XmemoryAPIError(`Invalid JSON from server (${res.status})`, res.status);
|
|
58
|
+
}
|
|
59
|
+
if (typeof payload === "object" && payload !== null && payload.status === "error") {
|
|
60
|
+
const err = payload;
|
|
61
|
+
const msg = err.error_message || err.error || String(payload);
|
|
62
|
+
throw new XmemoryAPIError(`${path} failed: ${msg}`, res.status);
|
|
63
|
+
}
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
throw new XmemoryAPIError(`HTTP ${res.status}: ${raw.slice(0, 200)}`, res.status);
|
|
66
|
+
}
|
|
67
|
+
return payload;
|
|
68
|
+
}
|
|
69
|
+
export class XmemoryClient {
|
|
70
|
+
baseUrl;
|
|
71
|
+
timeoutMs;
|
|
72
|
+
token;
|
|
73
|
+
instanceId = null;
|
|
74
|
+
constructor(options = {}) {
|
|
75
|
+
this.baseUrl = options.url ?? "";
|
|
76
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
77
|
+
this.token = options.token;
|
|
78
|
+
}
|
|
79
|
+
static async create(options = {}) {
|
|
80
|
+
const url = options.url ?? (await getEnv("XMEM_API_URL")) ?? DEFAULT_BASE_URL;
|
|
81
|
+
const token = options.token ?? (await getEnv("XMEM_AUTH_TOKEN"));
|
|
82
|
+
const client = new XmemoryClient({ ...options, url, token });
|
|
83
|
+
await client.checkHealth();
|
|
84
|
+
return client;
|
|
85
|
+
}
|
|
86
|
+
async checkHealth() {
|
|
87
|
+
const url = `${this.baseUrl.replace(/\/$/, "")}/api/healthz`;
|
|
88
|
+
const res = await fetchWithTimeout(url, {
|
|
89
|
+
method: "GET",
|
|
90
|
+
headers: { Accept: "application/json" },
|
|
91
|
+
timeoutMs: this.timeoutMs,
|
|
92
|
+
});
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
throw new XmemoryAPIError(`Health check failed: ${res.status} at ${url}`, res.status);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
requireInstanceId(op) {
|
|
98
|
+
if (!this.instanceId) {
|
|
99
|
+
throw new XmemoryAPIError(`instance_id is required for ${op}() but none was provided or saved.`);
|
|
100
|
+
}
|
|
101
|
+
return this.instanceId;
|
|
102
|
+
}
|
|
103
|
+
async createInstance(schemaText, schemaType, timeoutMs) {
|
|
104
|
+
const path = "/instance/create";
|
|
105
|
+
const body = schemaType === 0 ? { yml_schema: schemaText } : { json_schema: schemaText };
|
|
106
|
+
const response = await postJson(this.baseUrl, path, body, this.token, timeoutMs ?? this.timeoutMs);
|
|
107
|
+
if (response.status === "ok" && response.instance_id) {
|
|
108
|
+
this.instanceId = response.instance_id;
|
|
109
|
+
}
|
|
110
|
+
return response.status === "ok";
|
|
111
|
+
}
|
|
112
|
+
async write(text, options) {
|
|
113
|
+
const iid = this.requireInstanceId("write");
|
|
114
|
+
const timeoutMs = options?.timeoutMs ?? this.timeoutMs;
|
|
115
|
+
return postJson(this.baseUrl, "/write", {
|
|
116
|
+
instance_id: iid,
|
|
117
|
+
text,
|
|
118
|
+
extraction_logic: options?.extractionLogic ?? "deep",
|
|
119
|
+
}, this.token, timeoutMs);
|
|
120
|
+
}
|
|
121
|
+
async writeAsync(text, options) {
|
|
122
|
+
const iid = this.requireInstanceId("writeAsync");
|
|
123
|
+
const timeoutMs = options?.timeoutMs ?? this.timeoutMs;
|
|
124
|
+
const body = {
|
|
125
|
+
instance_id: iid,
|
|
126
|
+
text,
|
|
127
|
+
extraction_logic: options?.extractionLogic ?? "deep",
|
|
128
|
+
};
|
|
129
|
+
if (options?.extractWriteId != null) {
|
|
130
|
+
body["extract_write_id"] = options.extractWriteId;
|
|
131
|
+
}
|
|
132
|
+
return postJson(this.baseUrl, "/write_async", body, this.token, timeoutMs);
|
|
133
|
+
}
|
|
134
|
+
async writeStatus(writeId, options) {
|
|
135
|
+
const timeoutMs = options?.timeoutMs ?? this.timeoutMs;
|
|
136
|
+
return postJson(this.baseUrl, "/write_status", { write_id: writeId }, this.token, timeoutMs);
|
|
137
|
+
}
|
|
138
|
+
async read(query, options) {
|
|
139
|
+
const iid = this.requireInstanceId("read");
|
|
140
|
+
const timeoutMs = options?.timeoutMs ?? this.timeoutMs;
|
|
141
|
+
return postJson(this.baseUrl, "/read", {
|
|
142
|
+
instance_id: iid,
|
|
143
|
+
query,
|
|
144
|
+
mode: "single-answer",
|
|
145
|
+
}, this.token, timeoutMs);
|
|
146
|
+
}
|
|
147
|
+
get instance_id() {
|
|
148
|
+
return this.instanceId;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Create an xmemory client.
|
|
153
|
+
*/
|
|
154
|
+
export async function xmemoryInstance(options = {}) {
|
|
155
|
+
return XmemoryClient.create(options);
|
|
156
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the xmemory API.
|
|
3
|
+
*/
|
|
4
|
+
export declare const SchemaType: {
|
|
5
|
+
readonly YML: 0;
|
|
6
|
+
readonly JSON: 1;
|
|
7
|
+
};
|
|
8
|
+
export type SchemaTypeValue = (typeof SchemaType)[keyof typeof SchemaType];
|
|
9
|
+
export interface CreateInstanceYMLRequest {
|
|
10
|
+
yml_schema: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CreateInstanceResponse {
|
|
13
|
+
status: "ok" | "error";
|
|
14
|
+
instance_id?: string | null;
|
|
15
|
+
error_message?: string | null;
|
|
16
|
+
}
|
|
17
|
+
export type ExtractionLogic = "fast" | "regular" | "deep";
|
|
18
|
+
export interface WriteRequest {
|
|
19
|
+
instance_id: string;
|
|
20
|
+
text: string;
|
|
21
|
+
extraction_logic?: ExtractionLogic;
|
|
22
|
+
}
|
|
23
|
+
export interface WriteResponse {
|
|
24
|
+
status: "ok" | "error";
|
|
25
|
+
error_message?: string | null;
|
|
26
|
+
}
|
|
27
|
+
export interface ReadRequest {
|
|
28
|
+
instance_id: string;
|
|
29
|
+
query: string;
|
|
30
|
+
mode?: "single-answer" | "raw-tables" | "xresponse";
|
|
31
|
+
}
|
|
32
|
+
export interface ReaderResult {
|
|
33
|
+
answer?: string;
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
export interface ReadResponse {
|
|
37
|
+
status: "ok" | "error";
|
|
38
|
+
reader_result?: ReaderResult | null;
|
|
39
|
+
error_message?: string | null;
|
|
40
|
+
}
|
|
41
|
+
export interface AsyncWriteResponse {
|
|
42
|
+
status: "ok" | "error";
|
|
43
|
+
write_id?: string | null;
|
|
44
|
+
error_message?: string | null;
|
|
45
|
+
}
|
|
46
|
+
export type WriteQueueStatus = "queued" | "processing" | "completed" | "failed" | "not_found";
|
|
47
|
+
export interface WriteStatusRequest {
|
|
48
|
+
write_id: string;
|
|
49
|
+
}
|
|
50
|
+
export interface WriteStatusResponse {
|
|
51
|
+
status: "ok" | "error";
|
|
52
|
+
write_id: string;
|
|
53
|
+
write_status: WriteQueueStatus;
|
|
54
|
+
error_detail?: string | null;
|
|
55
|
+
completed_at?: string | null;
|
|
56
|
+
error_message?: string | null;
|
|
57
|
+
}
|
package/dist/types.js
ADDED
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xmemory",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "xmemory",
|
|
5
|
-
"keywords": [
|
|
5
|
+
"keywords": [
|
|
6
|
+
"xmemory"
|
|
7
|
+
],
|
|
6
8
|
"homepage": "https://github.com/xmemory-ai/xmemory-npm",
|
|
7
9
|
"bugs": {
|
|
8
10
|
"url": "https://github.com/xmemory-ai/xmemory-npm/issues"
|
|
@@ -13,12 +15,20 @@
|
|
|
13
15
|
},
|
|
14
16
|
"license": "MIT",
|
|
15
17
|
"author": "Dima Korolev",
|
|
16
|
-
"type": "
|
|
17
|
-
"main": "
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "dist/client.js",
|
|
20
|
+
"types": "dist/client.d.ts",
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
21
24
|
"scripts": {
|
|
22
|
-
"
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"test": "tsc --noEmit && node --import tsx test.ts",
|
|
27
|
+
"prepublishOnly": "npm run build"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^25.4.0",
|
|
31
|
+
"tsx": "^4.21.0",
|
|
32
|
+
"typescript": "^5.6.0"
|
|
23
33
|
}
|
|
24
34
|
}
|
package/cli.js
DELETED
package/index.js
DELETED