xmemory 1.2.0 → 2.1.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 +144 -55
- package/dist/client.d.ts +39 -41
- package/dist/client.js +184 -132
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/instance.d.ts +48 -0
- package/dist/instance.js +188 -0
- package/dist/types.d.ts +121 -45
- package/dist/types.js +28 -5
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -2,121 +2,202 @@
|
|
|
2
2
|
|
|
3
3
|
TypeScript/JavaScript client library for the [Xmemory](https://xmemory.ai) API.
|
|
4
4
|
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install xmemory
|
|
9
|
+
```
|
|
10
|
+
|
|
5
11
|
## Quick start
|
|
6
12
|
|
|
7
13
|
```typescript
|
|
8
|
-
import {
|
|
14
|
+
import { XmemoryClient } from "xmemory";
|
|
9
15
|
|
|
10
|
-
const
|
|
11
|
-
url: "https://api.xmemory.ai",
|
|
12
|
-
token: "<your-token>",
|
|
16
|
+
const xm = new XmemoryClient({
|
|
17
|
+
url: "https://api.xmemory.ai", // or set XMEM_API_URL env var
|
|
18
|
+
token: "<your-token>", // or set XMEM_AUTH_TOKEN env var
|
|
13
19
|
});
|
|
14
20
|
|
|
15
|
-
|
|
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
|
|
21
|
+
// Write and read from an existing instance
|
|
22
|
+
const inst = xm.instance("<your-instance-id>");
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
await inst.write("Alice is a software engineer who loves TypeScript.");
|
|
25
|
+
const result = await inst.read("What does Alice do?");
|
|
26
|
+
console.log(result.reader_result);
|
|
26
27
|
```
|
|
27
28
|
|
|
28
29
|
## Configuration
|
|
29
30
|
|
|
30
|
-
| Parameter | Env var | Default
|
|
31
|
-
|
|
32
|
-
| `url` | `XMEM_API_URL` | `
|
|
33
|
-
| `token` | `XMEM_AUTH_TOKEN` | `undefined`
|
|
34
|
-
| `timeoutMs` | — | `60000`
|
|
31
|
+
| Parameter | Env var | Default | Description |
|
|
32
|
+
|-------------|-------------------|----------------------------|----------------------------------------|
|
|
33
|
+
| `url` | `XMEM_API_URL` | `https://api.xmemory.ai` | Base URL of the Xmemory API |
|
|
34
|
+
| `token` | `XMEM_AUTH_TOKEN` | `undefined` | Bearer token for authentication |
|
|
35
|
+
| `timeoutMs` | — | `60000` | Default request timeout in milliseconds |
|
|
35
36
|
|
|
36
37
|
## Creating a client
|
|
37
38
|
|
|
38
39
|
```typescript
|
|
39
40
|
import { XmemoryClient, xmemoryInstance } from "xmemory";
|
|
40
41
|
|
|
41
|
-
// Option 1:
|
|
42
|
-
const
|
|
42
|
+
// Option 1: constructor (no health check)
|
|
43
|
+
const xm1 = new XmemoryClient({ token: "..." });
|
|
43
44
|
|
|
44
|
-
// Option 2:
|
|
45
|
-
const
|
|
45
|
+
// Option 2: factory with health check
|
|
46
|
+
const xm2 = await XmemoryClient.create({ token: "..." });
|
|
46
47
|
|
|
47
|
-
// Option 3:
|
|
48
|
-
const
|
|
48
|
+
// Option 3: convenience function (same as Option 2)
|
|
49
|
+
const xm3 = await xmemoryInstance({ token: "..." });
|
|
49
50
|
```
|
|
50
51
|
|
|
51
|
-
##
|
|
52
|
+
## Admin operations
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
All cluster and instance management lives under `client.admin`.
|
|
55
|
+
|
|
56
|
+
### Clusters
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const clusters = await xm.admin.listClusters();
|
|
60
|
+
const cluster = await xm.admin.getCluster(clusterId);
|
|
61
|
+
```
|
|
54
62
|
|
|
55
|
-
Create
|
|
56
|
-
is saved automatically and used for subsequent calls.
|
|
63
|
+
### Create an instance
|
|
57
64
|
|
|
58
65
|
```typescript
|
|
59
66
|
import { SchemaType } from "xmemory";
|
|
60
67
|
|
|
61
|
-
const
|
|
62
|
-
|
|
68
|
+
const inst = await xm.admin.createInstance(
|
|
69
|
+
clusterId,
|
|
70
|
+
"my-instance",
|
|
71
|
+
schemaYml,
|
|
72
|
+
SchemaType.YML,
|
|
73
|
+
{ description: "User profiles" },
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// inst is an InstanceHandle — use it directly for data operations
|
|
77
|
+
await inst.write("Alice joined the team.");
|
|
63
78
|
```
|
|
64
79
|
|
|
65
|
-
###
|
|
80
|
+
### List and get instances
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
const instances = await xm.admin.listInstances();
|
|
84
|
+
const info = await xm.admin.getInstance(instanceId);
|
|
85
|
+
```
|
|
66
86
|
|
|
67
|
-
|
|
87
|
+
### Schema operations
|
|
68
88
|
|
|
69
89
|
```typescript
|
|
70
|
-
const
|
|
71
|
-
|
|
90
|
+
const schema = await xm.admin.getInstanceSchema(instanceId);
|
|
91
|
+
await xm.admin.updateInstanceSchema(instanceId, newYml, SchemaType.YML);
|
|
72
92
|
```
|
|
73
93
|
|
|
74
|
-
|
|
94
|
+
### Generate schema
|
|
75
95
|
|
|
76
|
-
|
|
96
|
+
```typescript
|
|
97
|
+
const result = await xm.admin.generateSchema(clusterId, "Track user profiles and preferences");
|
|
98
|
+
console.log(result.data_schema);
|
|
99
|
+
```
|
|
77
100
|
|
|
78
|
-
|
|
101
|
+
### Update metadata and delete
|
|
79
102
|
|
|
80
103
|
```typescript
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
104
|
+
await xm.admin.updateInstanceMetadata(instanceId, "new-name", "new description");
|
|
105
|
+
const deletedIds = await xm.admin.deleteInstance(instanceId);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Instance data operations
|
|
109
|
+
|
|
110
|
+
Get a handle to an instance and use it for reads, writes, and extractions.
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const inst = xm.instance("<instance-id>");
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### `inst.write(text, options?)` → `WriteResult`
|
|
117
|
+
|
|
118
|
+
Extract and store structured objects from text.
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
const result = await inst.write("Bob is a designer based in Berlin.");
|
|
122
|
+
console.log(result.write_id, result.trace_id);
|
|
85
123
|
```
|
|
86
124
|
|
|
87
|
-
Options: `{
|
|
125
|
+
Options: `{ extractionLogic?, diffEngine?, timeoutMs? }` — `extractionLogic` defaults to `"deep"`.
|
|
126
|
+
|
|
127
|
+
### `inst.writeAsync(text, options?)` → `AsyncWriteResult`
|
|
128
|
+
|
|
129
|
+
Start an asynchronous write. Returns a `write_id` for tracking.
|
|
88
130
|
|
|
89
|
-
|
|
131
|
+
```typescript
|
|
132
|
+
const { write_id } = await inst.writeAsync("Carol manages the London office.");
|
|
133
|
+
```
|
|
90
134
|
|
|
91
|
-
|
|
135
|
+
### `inst.writeStatus(writeId, options?)` → `WriteStatusResult`
|
|
136
|
+
|
|
137
|
+
Poll the status of an async write.
|
|
92
138
|
|
|
93
139
|
```typescript
|
|
94
|
-
const status = await
|
|
140
|
+
const status = await inst.writeStatus(write_id);
|
|
95
141
|
console.log(status.write_status); // "queued" | "processing" | "completed" | "failed" | "not_found"
|
|
96
142
|
```
|
|
97
143
|
|
|
98
|
-
### `read(query, options?) →
|
|
144
|
+
### `inst.read(query, options?)` → `ReadResult`
|
|
145
|
+
|
|
146
|
+
Query the instance.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
const result = await inst.read("Who is on the team?");
|
|
150
|
+
console.log(result.reader_result);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Options: `{ readMode?, traceId?, timeoutMs? }` — `readMode` defaults to `"single-answer"`.
|
|
99
154
|
|
|
100
|
-
|
|
155
|
+
### `inst.extract(text, options?)` → `ExtractResult`
|
|
156
|
+
|
|
157
|
+
Extract objects from text without storing them.
|
|
101
158
|
|
|
102
159
|
```typescript
|
|
103
|
-
const
|
|
104
|
-
console.log(
|
|
160
|
+
const result = await inst.extract("Dave is an engineer in Tokyo.");
|
|
161
|
+
console.log(result.objects_extracted);
|
|
105
162
|
```
|
|
106
163
|
|
|
107
|
-
|
|
164
|
+
### `inst.getSchema(options?)` → `InstanceSchemaInfo`
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const schema = await inst.getSchema();
|
|
168
|
+
console.log(schema.data_schema);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### `inst.describe(options?)` → `DescribeResult`
|
|
172
|
+
|
|
173
|
+
Get agent-facing tool descriptions enriched with the instance's schema.
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const desc = await inst.describe();
|
|
177
|
+
console.log(desc.asText()); // plain text for system prompts
|
|
178
|
+
const tools = desc.asAnthropicTools(); // Anthropic tool-use format
|
|
179
|
+
const tools = desc.asOpenaiTools(); // OpenAI function-calling format
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Results are cached for 5 minutes. Call `inst.clearDescribeCache()` to force a refresh.
|
|
108
183
|
|
|
109
184
|
## Error handling
|
|
110
185
|
|
|
111
|
-
All errors
|
|
186
|
+
All errors throw `XmemoryAPIError`. Health check failures throw `XmemoryHealthCheckError` (a subclass).
|
|
112
187
|
|
|
113
188
|
```typescript
|
|
114
|
-
import { XmemoryAPIError,
|
|
189
|
+
import { XmemoryClient, XmemoryAPIError, XmemoryHealthCheckError } from "xmemory";
|
|
115
190
|
|
|
116
|
-
|
|
191
|
+
try {
|
|
192
|
+
const xm = await XmemoryClient.create({ token: "..." });
|
|
193
|
+
} catch (e) {
|
|
194
|
+
if (e instanceof XmemoryHealthCheckError) {
|
|
195
|
+
console.error("Server unreachable:", e.message);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
117
198
|
|
|
118
199
|
try {
|
|
119
|
-
|
|
200
|
+
await inst.read("query");
|
|
120
201
|
} catch (e) {
|
|
121
202
|
if (e instanceof XmemoryAPIError) {
|
|
122
203
|
console.error(`API error (HTTP ${e.status}): ${e.message}`);
|
|
@@ -124,6 +205,14 @@ try {
|
|
|
124
205
|
}
|
|
125
206
|
```
|
|
126
207
|
|
|
208
|
+
## All timeouts are per-request
|
|
209
|
+
|
|
210
|
+
Every method accepts an optional `timeoutMs` in its options bag, overriding the client default.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
const result = await inst.read("query", { timeoutMs: 120_000 });
|
|
214
|
+
```
|
|
215
|
+
|
|
127
216
|
---
|
|
128
217
|
|
|
129
218
|
## Mastra integration
|
package/dist/client.d.ts
CHANGED
|
@@ -1,46 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* XmemoryClient — main entry point for the xmemory API.
|
|
3
3
|
*/
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
import { InstanceHandle } from "./instance.js";
|
|
5
|
+
import { type ClusterInfo, type CreateInstanceOptions, type GenerateSchemaOptions, type GenerateSchemaResult, type InstanceInfo, type InstanceSchemaInfo, type RequestOptions, type SchemaTypeValue, type XmemoryClientOptions } from "./types.js";
|
|
6
|
+
export interface AdminNamespace {
|
|
7
|
+
listClusters(options?: RequestOptions & {
|
|
8
|
+
ids?: string[];
|
|
9
|
+
}): Promise<ClusterInfo[]>;
|
|
10
|
+
getCluster(clusterId: string, options?: RequestOptions): Promise<ClusterInfo>;
|
|
11
|
+
createInstance(clusterId: string, name: string, schemaText: string, schemaType: SchemaTypeValue, options?: CreateInstanceOptions): Promise<InstanceHandle>;
|
|
12
|
+
listInstances(options?: RequestOptions & {
|
|
13
|
+
ids?: string[];
|
|
14
|
+
}): Promise<InstanceInfo[]>;
|
|
15
|
+
getInstance(instanceId: string, options?: RequestOptions): Promise<InstanceInfo>;
|
|
16
|
+
deleteInstance(instanceId: string, options?: RequestOptions): Promise<string[]>;
|
|
17
|
+
getInstanceSchema(instanceId: string, options?: RequestOptions): Promise<InstanceSchemaInfo>;
|
|
18
|
+
updateInstanceSchema(instanceId: string, schemaText: string, schemaType: SchemaTypeValue, options?: RequestOptions): Promise<InstanceInfo>;
|
|
19
|
+
updateInstanceMetadata(instanceId: string, name: string, description: string, options?: RequestOptions): Promise<InstanceInfo>;
|
|
20
|
+
generateSchema(clusterId: string, schemaDescription: string, options?: GenerateSchemaOptions): Promise<GenerateSchemaResult>;
|
|
15
21
|
}
|
|
16
22
|
export declare class XmemoryClient {
|
|
17
|
-
readonly
|
|
18
|
-
readonly
|
|
19
|
-
readonly
|
|
20
|
-
|
|
21
|
-
constructor(options?:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
timeoutMs?: number;
|
|
37
|
-
}): Promise<WriteStatusResponse>;
|
|
38
|
-
read(query: string, options?: {
|
|
39
|
-
timeoutMs?: number;
|
|
40
|
-
}): Promise<ReadResponse>;
|
|
41
|
-
get instance_id(): string | null;
|
|
23
|
+
private readonly _baseUrl;
|
|
24
|
+
private readonly _timeoutMs;
|
|
25
|
+
private readonly _token;
|
|
26
|
+
readonly admin: AdminNamespace;
|
|
27
|
+
constructor(options?: XmemoryClientOptions);
|
|
28
|
+
/** Factory that performs a health check before returning the client. */
|
|
29
|
+
static create(options?: XmemoryClientOptions): Promise<XmemoryClient>;
|
|
30
|
+
/** Return an InstanceHandle scoped to the given instance ID. */
|
|
31
|
+
instance(instanceId: string): InstanceHandle;
|
|
32
|
+
/** GET /healthz — throws XmemoryHealthCheckError on failure. */
|
|
33
|
+
checkHealth(): Promise<void>;
|
|
34
|
+
private _fetch;
|
|
35
|
+
private _headers;
|
|
36
|
+
/** Core request — returns the raw API wrapper `{ids, items, errors}`. */
|
|
37
|
+
private _request;
|
|
38
|
+
private _requestOne;
|
|
39
|
+
private _requestList;
|
|
40
|
+
private _requestIds;
|
|
41
|
+
private _buildAdmin;
|
|
42
42
|
}
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
*/
|
|
46
|
-
export declare function xmemoryInstance(options?: XmemoryInstanceOptions): Promise<XmemoryClient>;
|
|
43
|
+
/** Convenience factory — creates a client with a health check. */
|
|
44
|
+
export declare function xmemoryInstance(options?: XmemoryClientOptions): Promise<XmemoryClient>;
|
package/dist/client.js
CHANGED
|
@@ -1,156 +1,208 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* XmemoryClient — main entry point for the xmemory API.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { InstanceHandle } from "./instance.js";
|
|
5
|
+
import { XmemoryAPIError, XmemoryHealthCheckError, buildInstanceSchema, } from "./types.js";
|
|
6
|
+
const DEFAULT_BASE_URL = "https://api.xmemory.ai";
|
|
6
7
|
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
}
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Client
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
69
11
|
export class XmemoryClient {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
12
|
+
_baseUrl;
|
|
13
|
+
_timeoutMs;
|
|
14
|
+
_token;
|
|
15
|
+
admin;
|
|
74
16
|
constructor(options = {}) {
|
|
75
|
-
|
|
76
|
-
this.
|
|
77
|
-
this.
|
|
17
|
+
const env = typeof process !== "undefined" ? process.env : undefined;
|
|
18
|
+
this._baseUrl = (options.url ?? env?.XMEM_API_URL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
19
|
+
this._token = options.token ?? env?.XMEM_AUTH_TOKEN;
|
|
20
|
+
this._timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
21
|
+
this.admin = this._buildAdmin();
|
|
78
22
|
}
|
|
23
|
+
/** Factory that performs a health check before returning the client. */
|
|
79
24
|
static async create(options = {}) {
|
|
80
|
-
const
|
|
81
|
-
const token = options.token ?? (await getEnv("XMEM_AUTH_TOKEN"));
|
|
82
|
-
const client = new XmemoryClient({ ...options, url, token });
|
|
25
|
+
const client = new XmemoryClient(options);
|
|
83
26
|
await client.checkHealth();
|
|
84
27
|
return client;
|
|
85
28
|
}
|
|
29
|
+
/** Return an InstanceHandle scoped to the given instance ID. */
|
|
30
|
+
instance(instanceId) {
|
|
31
|
+
return new InstanceHandle(instanceId, this._requestOne.bind(this));
|
|
32
|
+
}
|
|
33
|
+
/** GET /healthz — throws XmemoryHealthCheckError on failure. */
|
|
86
34
|
async checkHealth() {
|
|
87
|
-
const url = `${this.
|
|
88
|
-
|
|
89
|
-
method: "GET",
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (!res.ok) {
|
|
94
|
-
throw new XmemoryAPIError(`Health check failed: ${res.status} at ${url}`, res.status);
|
|
35
|
+
const url = `${this._baseUrl}/healthz`;
|
|
36
|
+
try {
|
|
37
|
+
const res = await this._fetch(url, { method: "GET" }, this._timeoutMs);
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
throw new XmemoryHealthCheckError(`Health check failed: HTTP ${res.status} at ${url}`, res.status);
|
|
40
|
+
}
|
|
95
41
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
throw new
|
|
42
|
+
catch (err) {
|
|
43
|
+
if (err instanceof XmemoryHealthCheckError)
|
|
44
|
+
throw err;
|
|
45
|
+
throw new XmemoryHealthCheckError(`Health check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
100
46
|
}
|
|
101
|
-
return this.instanceId;
|
|
102
47
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
48
|
+
// -----------------------------------------------------------------------
|
|
49
|
+
// Private: HTTP layer
|
|
50
|
+
// -----------------------------------------------------------------------
|
|
51
|
+
async _fetch(url, init, timeoutMs) {
|
|
52
|
+
const controller = new AbortController();
|
|
53
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
54
|
+
try {
|
|
55
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
clearTimeout(timer);
|
|
109
59
|
}
|
|
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
60
|
}
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
const body = {
|
|
125
|
-
instance_id: iid,
|
|
126
|
-
text,
|
|
127
|
-
extraction_logic: options?.extractionLogic ?? "deep",
|
|
61
|
+
_headers(hasBody = false) {
|
|
62
|
+
const h = {
|
|
63
|
+
Accept: "application/json",
|
|
128
64
|
};
|
|
129
|
-
if (
|
|
130
|
-
|
|
65
|
+
if (hasBody)
|
|
66
|
+
h["Content-Type"] = "application/json";
|
|
67
|
+
if (this._token)
|
|
68
|
+
h["Authorization"] = `Bearer ${this._token}`;
|
|
69
|
+
return h;
|
|
70
|
+
}
|
|
71
|
+
/** Core request — returns the raw API wrapper `{ids, items, errors}`. */
|
|
72
|
+
async _request(method, path, options) {
|
|
73
|
+
let url = `${this._baseUrl}${path}`;
|
|
74
|
+
if (options?.params) {
|
|
75
|
+
const sp = new URLSearchParams();
|
|
76
|
+
for (const [key, val] of Object.entries(options.params)) {
|
|
77
|
+
if (Array.isArray(val)) {
|
|
78
|
+
for (const v of val)
|
|
79
|
+
sp.append(key, v);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
sp.append(key, val);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const qs = sp.toString();
|
|
86
|
+
if (qs)
|
|
87
|
+
url += `?${qs}`;
|
|
131
88
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
89
|
+
const timeoutMs = options?.timeoutMs ?? this._timeoutMs;
|
|
90
|
+
const hasBody = !!(options?.body && method !== "GET");
|
|
91
|
+
const init = { method, headers: this._headers(hasBody) };
|
|
92
|
+
if (hasBody) {
|
|
93
|
+
init.body = JSON.stringify(options.body);
|
|
94
|
+
}
|
|
95
|
+
const res = await this._fetch(url, init, timeoutMs);
|
|
96
|
+
const raw = await res.text();
|
|
97
|
+
let payload;
|
|
98
|
+
try {
|
|
99
|
+
payload = raw ? JSON.parse(raw) : {};
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
throw new XmemoryAPIError(`Invalid JSON from server (${res.status}): ${raw.slice(0, 200)}`, res.status);
|
|
103
|
+
}
|
|
104
|
+
if (!res.ok) {
|
|
105
|
+
const msg = typeof payload === "object" && payload !== null && "message" in payload
|
|
106
|
+
? String(payload.message)
|
|
107
|
+
: raw.slice(0, 200);
|
|
108
|
+
throw new XmemoryAPIError(`HTTP ${res.status}: ${msg}`, res.status);
|
|
109
|
+
}
|
|
110
|
+
const response = payload;
|
|
111
|
+
if (response.errors?.length) {
|
|
112
|
+
const first = response.errors[0];
|
|
113
|
+
throw new XmemoryAPIError(`API error: ${first.message} (${first.code})`, res.status);
|
|
114
|
+
}
|
|
115
|
+
return response;
|
|
146
116
|
}
|
|
147
|
-
|
|
148
|
-
|
|
117
|
+
async _requestOne(method, path, options) {
|
|
118
|
+
const response = await this._request(method, path, options);
|
|
119
|
+
const items = response.items ?? [];
|
|
120
|
+
if (items.length === 0) {
|
|
121
|
+
throw new XmemoryAPIError(`Expected one item from ${method} ${path}, got none`);
|
|
122
|
+
}
|
|
123
|
+
if (items.length > 1) {
|
|
124
|
+
throw new XmemoryAPIError(`Expected one item from ${method} ${path}, got ${items.length}`);
|
|
125
|
+
}
|
|
126
|
+
return items[0];
|
|
127
|
+
}
|
|
128
|
+
async _requestList(method, path, options) {
|
|
129
|
+
const response = await this._request(method, path, options);
|
|
130
|
+
return (response.items ?? []);
|
|
131
|
+
}
|
|
132
|
+
async _requestIds(method, path, options) {
|
|
133
|
+
const response = await this._request(method, path, options);
|
|
134
|
+
return response.ids ?? [];
|
|
135
|
+
}
|
|
136
|
+
// -----------------------------------------------------------------------
|
|
137
|
+
// Private: build admin namespace
|
|
138
|
+
// -----------------------------------------------------------------------
|
|
139
|
+
_buildAdmin() {
|
|
140
|
+
return {
|
|
141
|
+
listClusters: async (options) => {
|
|
142
|
+
const params = options?.ids ? { ids: options.ids } : undefined;
|
|
143
|
+
return this._requestList("GET", "/clusters", { params, timeoutMs: options?.timeoutMs });
|
|
144
|
+
},
|
|
145
|
+
getCluster: async (clusterId, options) => {
|
|
146
|
+
return this._requestOne("GET", `/clusters/${clusterId}`, {
|
|
147
|
+
timeoutMs: options?.timeoutMs,
|
|
148
|
+
});
|
|
149
|
+
},
|
|
150
|
+
createInstance: async (clusterId, name, schemaText, schemaType, options) => {
|
|
151
|
+
const body = {
|
|
152
|
+
name,
|
|
153
|
+
instance_schema: buildInstanceSchema(schemaText, schemaType),
|
|
154
|
+
};
|
|
155
|
+
if (options?.description != null)
|
|
156
|
+
body.description = options.description;
|
|
157
|
+
if (options?.schemaDescription != null)
|
|
158
|
+
body.schema_description = options.schemaDescription;
|
|
159
|
+
const info = await this._requestOne("POST", `/clusters/${clusterId}/instances`, {
|
|
160
|
+
body,
|
|
161
|
+
timeoutMs: options?.timeoutMs,
|
|
162
|
+
});
|
|
163
|
+
return this.instance(info.id);
|
|
164
|
+
},
|
|
165
|
+
listInstances: async (options) => {
|
|
166
|
+
const params = options?.ids ? { ids: options.ids } : undefined;
|
|
167
|
+
return this._requestList("GET", "/instances", { params, timeoutMs: options?.timeoutMs });
|
|
168
|
+
},
|
|
169
|
+
getInstance: async (instanceId, options) => {
|
|
170
|
+
return this._requestOne("GET", `/instances/${instanceId}`, {
|
|
171
|
+
timeoutMs: options?.timeoutMs,
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
deleteInstance: async (instanceId, options) => {
|
|
175
|
+
return this._requestIds("DELETE", `/instances/${instanceId}`, {
|
|
176
|
+
timeoutMs: options?.timeoutMs,
|
|
177
|
+
});
|
|
178
|
+
},
|
|
179
|
+
getInstanceSchema: async (instanceId, options) => {
|
|
180
|
+
return this._requestOne("GET", `/instances/${instanceId}/schema`, {
|
|
181
|
+
timeoutMs: options?.timeoutMs,
|
|
182
|
+
});
|
|
183
|
+
},
|
|
184
|
+
updateInstanceSchema: async (instanceId, schemaText, schemaType, options) => {
|
|
185
|
+
return this._requestOne("PUT", `/instances/${instanceId}/schema`, {
|
|
186
|
+
body: { instance_schema: buildInstanceSchema(schemaText, schemaType) },
|
|
187
|
+
timeoutMs: options?.timeoutMs,
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
updateInstanceMetadata: async (instanceId, name, description, options) => {
|
|
191
|
+
return this._requestOne("PUT", `/instances/${instanceId}`, {
|
|
192
|
+
body: { name, description },
|
|
193
|
+
timeoutMs: options?.timeoutMs,
|
|
194
|
+
});
|
|
195
|
+
},
|
|
196
|
+
generateSchema: async (clusterId, schemaDescription, options) => {
|
|
197
|
+
const body = { schema_description: schemaDescription };
|
|
198
|
+
if (options?.currentYmlSchema != null)
|
|
199
|
+
body.current_yml_schema = options.currentYmlSchema;
|
|
200
|
+
return this._requestOne("POST", `/clusters/${clusterId}/instances/generate_schema`, { body, timeoutMs: options?.timeoutMs });
|
|
201
|
+
},
|
|
202
|
+
};
|
|
149
203
|
}
|
|
150
204
|
}
|
|
151
|
-
/**
|
|
152
|
-
* Create an xmemory client.
|
|
153
|
-
*/
|
|
205
|
+
/** Convenience factory — creates a client with a health check. */
|
|
154
206
|
export async function xmemoryInstance(options = {}) {
|
|
155
207
|
return XmemoryClient.create(options);
|
|
156
208
|
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xmemory — TypeScript client for the xmemory API.
|
|
3
|
+
*/
|
|
4
|
+
export { XmemoryClient, xmemoryInstance } from "./client.js";
|
|
5
|
+
export type { AdminNamespace } from "./client.js";
|
|
6
|
+
export { DescribeResult, InstanceHandle } from "./instance.js";
|
|
7
|
+
export { XmemoryAPIError, XmemoryHealthCheckError } from "./types.js";
|
|
8
|
+
export { SchemaType } from "./types.js";
|
|
9
|
+
export type { SchemaTypeValue, ExtractionLogic, ReadMode, WriteQueueStatus } from "./types.js";
|
|
10
|
+
export type { XmemoryClientOptions, RequestOptions, ReadOptions, WriteOptions, ExtractOptions, CreateInstanceOptions, GenerateSchemaOptions, } from "./types.js";
|
|
11
|
+
export type { ClusterInfo, InstanceInfo, InstanceSchemaInfo, ReadResult, WriteResult, AsyncWriteResult, WriteStatusResult, ExtractResult, GenerateSchemaResult, ToolDescription, ToolParameterDescription, RawDescribeResult, } from "./types.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xmemory — TypeScript client for the xmemory API.
|
|
3
|
+
*/
|
|
4
|
+
// Client
|
|
5
|
+
export { XmemoryClient, xmemoryInstance } from "./client.js";
|
|
6
|
+
// Instance handle
|
|
7
|
+
export { DescribeResult, InstanceHandle } from "./instance.js";
|
|
8
|
+
// Error classes
|
|
9
|
+
export { XmemoryAPIError, XmemoryHealthCheckError } from "./types.js";
|
|
10
|
+
// Enums
|
|
11
|
+
export { SchemaType } from "./types.js";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InstanceHandle — scoped data operations on a single xmemory instance.
|
|
3
|
+
*/
|
|
4
|
+
import type { AsyncWriteResult, ExtractOptions, ExtractResult, InstanceSchemaInfo, RawDescribeResult, ReadOptions, ReadResult, RequestOneFn, RequestOptions, ToolDescription, WriteOptions, WriteResult, WriteStatusResult } from "./types.js";
|
|
5
|
+
export declare class DescribeResult {
|
|
6
|
+
readonly instanceId: string;
|
|
7
|
+
readonly instanceName: string;
|
|
8
|
+
readonly schemaSummary: string;
|
|
9
|
+
readonly tools: readonly ToolDescription[];
|
|
10
|
+
constructor(raw: RawDescribeResult);
|
|
11
|
+
/**
|
|
12
|
+
* Plain-text representation suitable for injecting into an LLM system prompt.
|
|
13
|
+
*
|
|
14
|
+
* By default, tools are presented as method calls (matching the SDK).
|
|
15
|
+
* Set `includeHttp` to `true` to also show HTTP method and path for
|
|
16
|
+
* raw REST callers.
|
|
17
|
+
*/
|
|
18
|
+
asText(options?: {
|
|
19
|
+
includeHttp?: boolean;
|
|
20
|
+
}): string;
|
|
21
|
+
/** Tool definitions in the Anthropic tool-use format. */
|
|
22
|
+
asAnthropicTools(): Record<string, unknown>[];
|
|
23
|
+
/** Tool definitions in the OpenAI function-calling format. */
|
|
24
|
+
asOpenaiTools(): Record<string, unknown>[];
|
|
25
|
+
}
|
|
26
|
+
export declare class InstanceHandle {
|
|
27
|
+
readonly id: string;
|
|
28
|
+
private readonly _requestOne;
|
|
29
|
+
private _describeCache;
|
|
30
|
+
private _describeCacheAt;
|
|
31
|
+
private _describeTtlMs;
|
|
32
|
+
constructor(id: string, requestOne: RequestOneFn);
|
|
33
|
+
read(query: string, options?: ReadOptions): Promise<ReadResult>;
|
|
34
|
+
write(text: string, options?: WriteOptions): Promise<WriteResult>;
|
|
35
|
+
writeAsync(text: string, options?: WriteOptions): Promise<AsyncWriteResult>;
|
|
36
|
+
writeStatus(writeId: string, options?: RequestOptions): Promise<WriteStatusResult>;
|
|
37
|
+
extract(text: string, options?: ExtractOptions): Promise<ExtractResult>;
|
|
38
|
+
getSchema(options?: RequestOptions): Promise<InstanceSchemaInfo>;
|
|
39
|
+
/**
|
|
40
|
+
* Return agent-facing tool descriptions enriched with the instance schema.
|
|
41
|
+
*
|
|
42
|
+
* Results are cached locally with a TTL (default 5 min).
|
|
43
|
+
* Call `clearDescribeCache()` to force a refresh.
|
|
44
|
+
*/
|
|
45
|
+
describe(options?: RequestOptions): Promise<DescribeResult>;
|
|
46
|
+
/** Clear the cached describe result so the next `describe()` call fetches fresh data. */
|
|
47
|
+
clearDescribeCache(): void;
|
|
48
|
+
}
|
package/dist/instance.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InstanceHandle — scoped data operations on a single xmemory instance.
|
|
3
|
+
*/
|
|
4
|
+
const DEFAULT_DESCRIBE_TTL_MS = 300_000; // 5 minutes
|
|
5
|
+
export class DescribeResult {
|
|
6
|
+
instanceId;
|
|
7
|
+
instanceName;
|
|
8
|
+
schemaSummary;
|
|
9
|
+
tools;
|
|
10
|
+
constructor(raw) {
|
|
11
|
+
this.instanceId = raw.instance_id;
|
|
12
|
+
this.instanceName = raw.instance_name;
|
|
13
|
+
this.schemaSummary = raw.schema_summary;
|
|
14
|
+
this.tools = raw.tools;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Plain-text representation suitable for injecting into an LLM system prompt.
|
|
18
|
+
*
|
|
19
|
+
* By default, tools are presented as method calls (matching the SDK).
|
|
20
|
+
* Set `includeHttp` to `true` to also show HTTP method and path for
|
|
21
|
+
* raw REST callers.
|
|
22
|
+
*/
|
|
23
|
+
asText(options) {
|
|
24
|
+
const includeHttp = options?.includeHttp ?? false;
|
|
25
|
+
const lines = [];
|
|
26
|
+
lines.push(`Instance: ${this.instanceName} (${this.instanceId})`);
|
|
27
|
+
if (this.schemaSummary) {
|
|
28
|
+
lines.push(`\n${this.schemaSummary}`);
|
|
29
|
+
}
|
|
30
|
+
lines.push("\nAvailable tools:\n");
|
|
31
|
+
for (const tool of this.tools) {
|
|
32
|
+
const paramsSig = tool.parameters
|
|
33
|
+
.map((p) => p.name + (p.required ? "" : "?"))
|
|
34
|
+
.join(", ");
|
|
35
|
+
lines.push(`## ${tool.name}(${paramsSig})`);
|
|
36
|
+
lines.push(tool.description);
|
|
37
|
+
lines.push(`When to use: ${tool.when_to_use}`);
|
|
38
|
+
if (includeHttp) {
|
|
39
|
+
lines.push(`HTTP: ${tool.http_method} ${tool.http_path}`);
|
|
40
|
+
}
|
|
41
|
+
if (tool.parameters.length > 0) {
|
|
42
|
+
lines.push("Parameters:");
|
|
43
|
+
for (const p of tool.parameters) {
|
|
44
|
+
const req = p.required ? "required" : "optional";
|
|
45
|
+
lines.push(` - ${p.name} (${p.type}, ${req}): ${p.description}`);
|
|
46
|
+
if (p.enum) {
|
|
47
|
+
lines.push(` Allowed values: ${p.enum.join(", ")}`);
|
|
48
|
+
}
|
|
49
|
+
if (p.default != null) {
|
|
50
|
+
lines.push(` Default: ${p.default}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
lines.push("");
|
|
55
|
+
}
|
|
56
|
+
return lines.join("\n");
|
|
57
|
+
}
|
|
58
|
+
/** Tool definitions in the Anthropic tool-use format. */
|
|
59
|
+
asAnthropicTools() {
|
|
60
|
+
return this.tools.map((tool) => {
|
|
61
|
+
const { properties, required } = buildJsonSchemaProps(tool.parameters);
|
|
62
|
+
return {
|
|
63
|
+
name: tool.name,
|
|
64
|
+
description: `${tool.description}\n\nWhen to use: ${tool.when_to_use}`,
|
|
65
|
+
input_schema: { type: "object", properties, required },
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** Tool definitions in the OpenAI function-calling format. */
|
|
70
|
+
asOpenaiTools() {
|
|
71
|
+
return this.tools.map((tool) => {
|
|
72
|
+
const { properties, required } = buildJsonSchemaProps(tool.parameters);
|
|
73
|
+
return {
|
|
74
|
+
type: "function",
|
|
75
|
+
function: {
|
|
76
|
+
name: tool.name,
|
|
77
|
+
description: `${tool.description}\n\nWhen to use: ${tool.when_to_use}`,
|
|
78
|
+
parameters: { type: "object", properties, required },
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function buildJsonSchemaProps(params) {
|
|
85
|
+
const properties = {};
|
|
86
|
+
const required = [];
|
|
87
|
+
for (const p of params) {
|
|
88
|
+
const prop = { type: p.type, description: p.description };
|
|
89
|
+
if (p.enum)
|
|
90
|
+
prop.enum = p.enum;
|
|
91
|
+
properties[p.name] = prop;
|
|
92
|
+
if (p.required)
|
|
93
|
+
required.push(p.name);
|
|
94
|
+
}
|
|
95
|
+
return { properties, required };
|
|
96
|
+
}
|
|
97
|
+
export class InstanceHandle {
|
|
98
|
+
id;
|
|
99
|
+
_requestOne;
|
|
100
|
+
_describeCache = null;
|
|
101
|
+
_describeCacheAt = 0;
|
|
102
|
+
_describeTtlMs = DEFAULT_DESCRIBE_TTL_MS;
|
|
103
|
+
constructor(id, requestOne) {
|
|
104
|
+
this.id = id;
|
|
105
|
+
this._requestOne = requestOne;
|
|
106
|
+
}
|
|
107
|
+
async read(query, options) {
|
|
108
|
+
const body = {
|
|
109
|
+
query,
|
|
110
|
+
mode: options?.readMode ?? "single-answer",
|
|
111
|
+
};
|
|
112
|
+
if (options?.traceId != null)
|
|
113
|
+
body.trace_id = options.traceId;
|
|
114
|
+
return this._requestOne("POST", `/instances/${this.id}/read`, {
|
|
115
|
+
body,
|
|
116
|
+
timeoutMs: options?.timeoutMs,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
async write(text, options) {
|
|
120
|
+
const body = {
|
|
121
|
+
text,
|
|
122
|
+
extraction_logic: options?.extractionLogic ?? "deep",
|
|
123
|
+
};
|
|
124
|
+
if (options?.diffEngine != null)
|
|
125
|
+
body.diff_engine = options.diffEngine;
|
|
126
|
+
return this._requestOne("POST", `/instances/${this.id}/write`, {
|
|
127
|
+
body,
|
|
128
|
+
timeoutMs: options?.timeoutMs,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async writeAsync(text, options) {
|
|
132
|
+
const body = {
|
|
133
|
+
text,
|
|
134
|
+
extraction_logic: options?.extractionLogic ?? "deep",
|
|
135
|
+
};
|
|
136
|
+
if (options?.diffEngine != null)
|
|
137
|
+
body.diff_engine = options.diffEngine;
|
|
138
|
+
return this._requestOne("POST", `/instances/${this.id}/write_async`, {
|
|
139
|
+
body,
|
|
140
|
+
timeoutMs: options?.timeoutMs,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async writeStatus(writeId, options) {
|
|
144
|
+
return this._requestOne("POST", `/instances/${this.id}/write_status`, {
|
|
145
|
+
body: { write_id: writeId },
|
|
146
|
+
timeoutMs: options?.timeoutMs,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
async extract(text, options) {
|
|
150
|
+
const body = {
|
|
151
|
+
text,
|
|
152
|
+
extraction_logic: options?.extractionLogic ?? "deep",
|
|
153
|
+
};
|
|
154
|
+
return this._requestOne("POST", `/instances/${this.id}/extract`, {
|
|
155
|
+
body,
|
|
156
|
+
timeoutMs: options?.timeoutMs,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
async getSchema(options) {
|
|
160
|
+
return this._requestOne("GET", `/instances/${this.id}/schema`, {
|
|
161
|
+
timeoutMs: options?.timeoutMs,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Return agent-facing tool descriptions enriched with the instance schema.
|
|
166
|
+
*
|
|
167
|
+
* Results are cached locally with a TTL (default 5 min).
|
|
168
|
+
* Call `clearDescribeCache()` to force a refresh.
|
|
169
|
+
*/
|
|
170
|
+
async describe(options) {
|
|
171
|
+
const now = Date.now();
|
|
172
|
+
if (this._describeCache && now - this._describeCacheAt < this._describeTtlMs) {
|
|
173
|
+
return this._describeCache;
|
|
174
|
+
}
|
|
175
|
+
const raw = await this._requestOne("GET", `/instances/${this.id}/describe`, {
|
|
176
|
+
timeoutMs: options?.timeoutMs,
|
|
177
|
+
});
|
|
178
|
+
const result = new DescribeResult(raw);
|
|
179
|
+
this._describeCache = result;
|
|
180
|
+
this._describeCacheAt = now;
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
/** Clear the cached describe result so the next `describe()` call fetches fresh data. */
|
|
184
|
+
clearDescribeCache() {
|
|
185
|
+
this._describeCache = null;
|
|
186
|
+
this._describeCacheAt = 0;
|
|
187
|
+
}
|
|
188
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,57 +1,133 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Types for the xmemory API.
|
|
2
|
+
* Types, enums, and error classes for the xmemory API.
|
|
3
3
|
*/
|
|
4
4
|
export declare const SchemaType: {
|
|
5
5
|
readonly YML: 0;
|
|
6
6
|
readonly JSON: 1;
|
|
7
7
|
};
|
|
8
8
|
export type SchemaTypeValue = (typeof SchemaType)[keyof typeof SchemaType];
|
|
9
|
-
export
|
|
10
|
-
|
|
9
|
+
export type ExtractionLogic = "fast" | "regular" | "deep";
|
|
10
|
+
export type ReadMode = "single-answer" | "raw-tables" | "xresponse";
|
|
11
|
+
export type WriteQueueStatus = "queued" | "processing" | "completed" | "failed" | "not_found";
|
|
12
|
+
export declare class XmemoryAPIError extends Error {
|
|
13
|
+
readonly status?: number | undefined;
|
|
14
|
+
constructor(message: string, status?: number | undefined);
|
|
11
15
|
}
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
instance_id?: string | null;
|
|
15
|
-
error_message?: string | null;
|
|
16
|
+
export declare class XmemoryHealthCheckError extends XmemoryAPIError {
|
|
17
|
+
constructor(message: string, status?: number);
|
|
16
18
|
}
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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;
|
|
19
|
+
export interface ClusterInfo {
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly org_id: string;
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly description: string | null;
|
|
45
24
|
}
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
|
|
25
|
+
export interface InstanceInfo {
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly cluster_id: string;
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly description: string | null;
|
|
30
|
+
readonly data_schema: Record<string, unknown> | null;
|
|
31
|
+
}
|
|
32
|
+
export interface InstanceSchemaInfo {
|
|
33
|
+
readonly data_schema: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
export interface ReadResult {
|
|
36
|
+
readonly trace_id: string | null;
|
|
37
|
+
readonly reader_result: unknown;
|
|
38
|
+
}
|
|
39
|
+
export interface WriteResult {
|
|
40
|
+
readonly write_id: string;
|
|
41
|
+
readonly trace_id: string | null;
|
|
42
|
+
readonly cleaned_objects: unknown;
|
|
43
|
+
readonly diff_plan: unknown;
|
|
44
|
+
}
|
|
45
|
+
export interface AsyncWriteResult {
|
|
46
|
+
readonly write_id: string;
|
|
47
|
+
}
|
|
48
|
+
export interface WriteStatusResult {
|
|
49
|
+
readonly write_id: string;
|
|
50
|
+
readonly write_status: WriteQueueStatus;
|
|
51
|
+
readonly error_detail: string | null;
|
|
52
|
+
readonly completed_at: string | null;
|
|
53
|
+
}
|
|
54
|
+
export interface ExtractResult {
|
|
55
|
+
readonly trace_id: string | null;
|
|
56
|
+
readonly objects_extracted: unknown;
|
|
57
|
+
}
|
|
58
|
+
export interface GenerateSchemaResult {
|
|
59
|
+
readonly data_schema: Record<string, unknown>;
|
|
60
|
+
}
|
|
61
|
+
export interface ToolParameterDescription {
|
|
62
|
+
readonly name: string;
|
|
63
|
+
readonly type: string;
|
|
64
|
+
readonly description: string;
|
|
65
|
+
readonly required: boolean;
|
|
66
|
+
readonly enum?: string[];
|
|
67
|
+
readonly default?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface ToolDescription {
|
|
70
|
+
readonly name: string;
|
|
71
|
+
readonly description: string;
|
|
72
|
+
readonly when_to_use: string;
|
|
73
|
+
readonly parameters: ToolParameterDescription[];
|
|
74
|
+
readonly http_method: string;
|
|
75
|
+
readonly http_path: string;
|
|
76
|
+
}
|
|
77
|
+
export interface RawDescribeResult {
|
|
78
|
+
readonly instance_id: string;
|
|
79
|
+
readonly instance_name: string;
|
|
80
|
+
readonly schema_summary: string;
|
|
81
|
+
readonly tools: ToolDescription[];
|
|
82
|
+
}
|
|
83
|
+
export interface XmemoryClientOptions {
|
|
84
|
+
url?: string;
|
|
85
|
+
token?: string;
|
|
86
|
+
timeoutMs?: number;
|
|
87
|
+
}
|
|
88
|
+
export interface RequestOptions {
|
|
89
|
+
timeoutMs?: number;
|
|
90
|
+
}
|
|
91
|
+
export interface ReadOptions {
|
|
92
|
+
readMode?: ReadMode;
|
|
93
|
+
traceId?: string;
|
|
94
|
+
timeoutMs?: number;
|
|
95
|
+
}
|
|
96
|
+
export interface WriteOptions {
|
|
97
|
+
extractionLogic?: ExtractionLogic;
|
|
98
|
+
diffEngine?: boolean;
|
|
99
|
+
timeoutMs?: number;
|
|
100
|
+
}
|
|
101
|
+
export interface ExtractOptions {
|
|
102
|
+
extractionLogic?: ExtractionLogic;
|
|
103
|
+
timeoutMs?: number;
|
|
104
|
+
}
|
|
105
|
+
export interface CreateInstanceOptions {
|
|
106
|
+
description?: string;
|
|
107
|
+
schemaDescription?: string;
|
|
108
|
+
timeoutMs?: number;
|
|
109
|
+
}
|
|
110
|
+
export interface GenerateSchemaOptions {
|
|
111
|
+
currentYmlSchema?: string;
|
|
112
|
+
timeoutMs?: number;
|
|
113
|
+
}
|
|
114
|
+
export interface ApiError {
|
|
115
|
+
readonly code: string;
|
|
116
|
+
readonly message: string;
|
|
117
|
+
readonly field?: string;
|
|
118
|
+
readonly resource_id?: string;
|
|
119
|
+
}
|
|
120
|
+
export interface RawApiResponse {
|
|
121
|
+
readonly ids?: string[];
|
|
122
|
+
readonly items?: unknown[];
|
|
123
|
+
readonly errors?: ApiError[];
|
|
49
124
|
}
|
|
50
|
-
export interface
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
error_detail?: string | null;
|
|
55
|
-
completed_at?: string | null;
|
|
56
|
-
error_message?: string | null;
|
|
125
|
+
export interface InternalRequestOptions {
|
|
126
|
+
body?: Record<string, unknown>;
|
|
127
|
+
params?: Record<string, string | string[]>;
|
|
128
|
+
timeoutMs?: number;
|
|
57
129
|
}
|
|
130
|
+
export type RequestOneFn = <T>(method: string, path: string, options?: InternalRequestOptions) => Promise<T>;
|
|
131
|
+
export type RequestListFn = <T>(method: string, path: string, options?: InternalRequestOptions) => Promise<T[]>;
|
|
132
|
+
export type RequestIdsFn = (method: string, path: string, options?: InternalRequestOptions) => Promise<string[]>;
|
|
133
|
+
export declare function buildInstanceSchema(schemaText: string, schemaType: SchemaTypeValue): Record<string, unknown>;
|
package/dist/types.js
CHANGED
|
@@ -1,7 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Types for the xmemory API.
|
|
2
|
+
* Types, enums, and error classes for the xmemory API.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Enums
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
export const SchemaType = { YML: 0, JSON: 1 };
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Error classes
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
export class XmemoryAPIError extends Error {
|
|
12
|
+
status;
|
|
13
|
+
constructor(message, status) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.status = status;
|
|
16
|
+
this.name = "XmemoryAPIError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class XmemoryHealthCheckError extends XmemoryAPIError {
|
|
20
|
+
constructor(message, status) {
|
|
21
|
+
super(message, status);
|
|
22
|
+
this.name = "XmemoryHealthCheckError";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function buildInstanceSchema(schemaText, schemaType) {
|
|
26
|
+
if (schemaType === SchemaType.YML) {
|
|
27
|
+
return { yml: { value: schemaText } };
|
|
28
|
+
}
|
|
29
|
+
return { json_schema: { value: schemaText } };
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xmemory",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "xmemory",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"xmemory"
|
|
@@ -16,14 +16,15 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"author": "Dima Korolev",
|
|
18
18
|
"type": "module",
|
|
19
|
-
"main": "dist/
|
|
20
|
-
"types": "dist/
|
|
19
|
+
"main": "dist/index.js",
|
|
20
|
+
"types": "dist/index.d.ts",
|
|
21
21
|
"files": [
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsc",
|
|
26
26
|
"test": "tsc --noEmit && node --import tsx test.ts",
|
|
27
|
+
"test:types": "tsc --noEmit",
|
|
27
28
|
"prepublishOnly": "npm run build"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|