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 CHANGED
@@ -1,8 +1,134 @@
1
- # `xmemory`
1
+ # xmemory
2
2
 
3
- Integration code with `xmemory`.
3
+ TypeScript/JavaScript client library for the [Xmemory](https://xmemory.ai) API.
4
4
 
5
- For now just the Mastra prompt.
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
 
@@ -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
+ }
@@ -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
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Types for the xmemory API.
3
+ */
4
+ export const SchemaType = {
5
+ YML: 0,
6
+ JSON: 1,
7
+ };
package/package.json CHANGED
@@ -1,8 +1,10 @@
1
1
  {
2
2
  "name": "xmemory",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "xmemory",
5
- "keywords": [ "xmemory" ],
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": "commonjs",
17
- "main": "index.js",
18
- "bin": {
19
- "xmemory": "cli.js"
20
- },
18
+ "type": "module",
19
+ "main": "dist/client.js",
20
+ "types": "dist/client.d.ts",
21
+ "files": [
22
+ "dist"
23
+ ],
21
24
  "scripts": {
22
- "test": "echo \"Error: no test specified\" && exit 1"
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
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const greet = require("./index");
4
-
5
- const name = process.argv[2];
6
- console.log(greet(name));
package/index.js DELETED
@@ -1,11 +0,0 @@
1
- // NOTE(dkorolev): There will be more to this module.
2
- // For now it's just the prompt to connect `xmemory` to Mastra.
3
-
4
- function greet(name) {
5
- if (name) {
6
- return `Hello, ${name}!`;
7
- }
8
- return "Hello, xmemory!";
9
- }
10
-
11
- module.exports = greet;