@persistmemory/sdk 0.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/LICENSE +21 -0
- package/README.md +520 -0
- package/dist/backoff.d.ts +73 -0
- package/dist/client.d.ts +46 -0
- package/dist/errors.d.ts +159 -0
- package/dist/http.d.ts +114 -0
- package/dist/index.cjs +1038 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +1015 -0
- package/dist/index.js.map +7 -0
- package/dist/pagination.d.ts +45 -0
- package/dist/query.d.ts +35 -0
- package/dist/resources/conversations.d.ts +38 -0
- package/dist/resources/health.d.ts +20 -0
- package/dist/resources/ingestion.d.ts +37 -0
- package/dist/resources/integrations.d.ts +48 -0
- package/dist/resources/knowledge.d.ts +70 -0
- package/dist/resources/memories.d.ts +40 -0
- package/dist/resources/search.d.ts +40 -0
- package/dist/resources/spaces.d.ts +55 -0
- package/dist/types.d.ts +500 -0
- package/package.json +59 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1015 @@
|
|
|
1
|
+
// src/query.ts
|
|
2
|
+
function encodeQuery(params) {
|
|
3
|
+
if (!params) return "";
|
|
4
|
+
const search = new URLSearchParams();
|
|
5
|
+
for (const [key, value] of Object.entries(params)) {
|
|
6
|
+
if (value === void 0) continue;
|
|
7
|
+
if (Array.isArray(value)) {
|
|
8
|
+
for (const one of value) search.append(key, String(one));
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
search.append(key, String(value));
|
|
12
|
+
}
|
|
13
|
+
const encoded = search.toString();
|
|
14
|
+
return encoded ? `?${encoded}` : "";
|
|
15
|
+
}
|
|
16
|
+
function pageQuery(params, cursor, extra) {
|
|
17
|
+
return {
|
|
18
|
+
...params.limit !== void 0 ? { limit: params.limit } : {},
|
|
19
|
+
...cursor !== void 0 ? { cursor } : params.cursor !== void 0 ? { cursor: params.cursor } : {},
|
|
20
|
+
...extra
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/backoff.ts
|
|
25
|
+
var DEFAULT_BACKOFF = { baseMs: 250, maxMs: 8e3, factor: 2, jitter: 1 };
|
|
26
|
+
function backoffMs(attempt, options = {}) {
|
|
27
|
+
const base = options.baseMs ?? DEFAULT_BACKOFF.baseMs;
|
|
28
|
+
const max = options.maxMs ?? DEFAULT_BACKOFF.maxMs;
|
|
29
|
+
const factor = options.factor ?? DEFAULT_BACKOFF.factor;
|
|
30
|
+
const jitter = clamp01(options.jitter ?? DEFAULT_BACKOFF.jitter);
|
|
31
|
+
const random = options.random ?? Math.random;
|
|
32
|
+
const exponent = Math.max(0, Math.floor(attempt) - 1);
|
|
33
|
+
const ceiling = Math.min(max, base * Math.pow(factor, exponent));
|
|
34
|
+
if (jitter <= 0) return Math.round(ceiling);
|
|
35
|
+
const fixed = ceiling * (1 - jitter);
|
|
36
|
+
return Math.round(fixed + random() * (ceiling - fixed));
|
|
37
|
+
}
|
|
38
|
+
function delayFor(args) {
|
|
39
|
+
const computed = backoffMs(args.attempt, args.options ?? {});
|
|
40
|
+
if (args.retryAfterSeconds === void 0 || !Number.isFinite(args.retryAfterSeconds)) {
|
|
41
|
+
return computed;
|
|
42
|
+
}
|
|
43
|
+
return Math.max(computed, Math.max(0, args.retryAfterSeconds) * 1e3);
|
|
44
|
+
}
|
|
45
|
+
function clamp01(value) {
|
|
46
|
+
if (!Number.isFinite(value)) return 0;
|
|
47
|
+
return Math.min(1, Math.max(0, value));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/errors.ts
|
|
51
|
+
var PersistMemoryError = class extends Error {
|
|
52
|
+
status;
|
|
53
|
+
code;
|
|
54
|
+
fields;
|
|
55
|
+
requestId;
|
|
56
|
+
retryAfterSeconds;
|
|
57
|
+
/** Retrying this exact request could plausibly succeed. */
|
|
58
|
+
retryable = false;
|
|
59
|
+
constructor(init) {
|
|
60
|
+
super(redact(init.message));
|
|
61
|
+
this.name = new.target.name;
|
|
62
|
+
this.status = init.status;
|
|
63
|
+
this.code = init.code;
|
|
64
|
+
if (init.fields) this.fields = init.fields;
|
|
65
|
+
if (init.requestId) this.requestId = init.requestId;
|
|
66
|
+
if (init.retryAfterSeconds !== void 0) this.retryAfterSeconds = init.retryAfterSeconds;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A one-line summary safe to log.
|
|
70
|
+
*
|
|
71
|
+
* Provided so callers reach for this instead of `JSON.stringify(error)`,
|
|
72
|
+
* which walks own properties and would pick up anything a future field
|
|
73
|
+
* holds. Everything here is already server-supplied and key-free.
|
|
74
|
+
*/
|
|
75
|
+
toString() {
|
|
76
|
+
const id = this.requestId ? ` requestId=${this.requestId}` : "";
|
|
77
|
+
return `${this.name}: [${this.status} ${this.code}] ${this.message}${id}`;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
var AuthenticationError = class extends PersistMemoryError {
|
|
81
|
+
};
|
|
82
|
+
var PermissionDeniedError = class extends PersistMemoryError {
|
|
83
|
+
};
|
|
84
|
+
var NotFoundError = class extends PersistMemoryError {
|
|
85
|
+
};
|
|
86
|
+
var ValidationError = class extends PersistMemoryError {
|
|
87
|
+
};
|
|
88
|
+
var ConflictError = class extends PersistMemoryError {
|
|
89
|
+
};
|
|
90
|
+
var RateLimitError = class extends PersistMemoryError {
|
|
91
|
+
retryable = true;
|
|
92
|
+
};
|
|
93
|
+
var ServerError = class extends PersistMemoryError {
|
|
94
|
+
retryable = true;
|
|
95
|
+
};
|
|
96
|
+
var ConnectionError = class extends PersistMemoryError {
|
|
97
|
+
retryable = true;
|
|
98
|
+
constructor(message) {
|
|
99
|
+
super({ status: 0, code: "CONNECTION_ERROR", message });
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var TimeoutError = class extends PersistMemoryError {
|
|
103
|
+
retryable = true;
|
|
104
|
+
constructor(message) {
|
|
105
|
+
super({ status: 0, code: "TIMEOUT", message });
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
var AbortError = class extends PersistMemoryError {
|
|
109
|
+
constructor(message = "The request was aborted by the caller.") {
|
|
110
|
+
super({ status: 0, code: "ABORTED", message });
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
function errorFromResponse(status, body, headers) {
|
|
114
|
+
const envelope = body ?? {};
|
|
115
|
+
const code = typeof envelope.error?.code === "string" ? envelope.error.code : codeForStatus(status);
|
|
116
|
+
const message = typeof envelope.error?.message === "string" && envelope.error.message.length > 0 ? envelope.error.message : defaultMessage(status);
|
|
117
|
+
const retryAfterSeconds = status === 429 || status === 503 ? retryAfterOf(headers) : void 0;
|
|
118
|
+
const init = {
|
|
119
|
+
status,
|
|
120
|
+
code,
|
|
121
|
+
message,
|
|
122
|
+
...isFieldMap(envelope.error?.fields) ? { fields: envelope.error.fields } : {},
|
|
123
|
+
...typeof envelope.error?.requestId === "string" ? { requestId: envelope.error.requestId } : {},
|
|
124
|
+
...retryAfterSeconds !== void 0 ? { retryAfterSeconds } : {}
|
|
125
|
+
};
|
|
126
|
+
if (status === 429 || code === "RATE_LIMITED") return new RateLimitError(init);
|
|
127
|
+
if (status === 401 || code === "UNAUTHORIZED") return new AuthenticationError(init);
|
|
128
|
+
if (status === 403 || code === "FORBIDDEN") return new PermissionDeniedError(init);
|
|
129
|
+
if (status === 404 || code === "NOT_FOUND") return new NotFoundError(init);
|
|
130
|
+
if (status === 409 || code === "CONFLICT") return new ConflictError(init);
|
|
131
|
+
if (status === 400 || status === 413 || status === 422) return new ValidationError(init);
|
|
132
|
+
if (status >= 500) return new ServerError(init);
|
|
133
|
+
return new PersistMemoryError(init);
|
|
134
|
+
}
|
|
135
|
+
function retryAfterOf(headers) {
|
|
136
|
+
const raw = headers.get("retry-after");
|
|
137
|
+
if (!raw) return void 0;
|
|
138
|
+
const seconds = Number(raw.trim());
|
|
139
|
+
if (!Number.isFinite(seconds) || seconds < 0) return void 0;
|
|
140
|
+
return Math.min(seconds, 300);
|
|
141
|
+
}
|
|
142
|
+
function isFieldMap(value) {
|
|
143
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
144
|
+
return Object.values(value).every((one) => typeof one === "string");
|
|
145
|
+
}
|
|
146
|
+
function codeForStatus(status) {
|
|
147
|
+
if (status === 401) return "UNAUTHORIZED";
|
|
148
|
+
if (status === 403) return "FORBIDDEN";
|
|
149
|
+
if (status === 404) return "NOT_FOUND";
|
|
150
|
+
if (status === 409) return "CONFLICT";
|
|
151
|
+
if (status === 429) return "RATE_LIMITED";
|
|
152
|
+
if (status === 413) return "PAYLOAD_TOO_LARGE";
|
|
153
|
+
if (status >= 500) return "INTERNAL_ERROR";
|
|
154
|
+
return "VALIDATION_ERROR";
|
|
155
|
+
}
|
|
156
|
+
function defaultMessage(status) {
|
|
157
|
+
return `The API returned ${status} with no readable error body.`;
|
|
158
|
+
}
|
|
159
|
+
function redact(text) {
|
|
160
|
+
return text.replace(/pm_(live|test)_[A-Za-z0-9_-]+/g, "pm_$1_[redacted]");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/http.ts
|
|
164
|
+
var DEFAULT_BASE_URL = "https://api.persistmemory.com";
|
|
165
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
166
|
+
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
167
|
+
var RETRY_WITHOUT_ASKING = /* @__PURE__ */ new Set(["GET", "HEAD", "PATCH", "DELETE"]);
|
|
168
|
+
var HttpClient = class {
|
|
169
|
+
/**
|
|
170
|
+
* The credential, in a private field, and never anywhere else.
|
|
171
|
+
*
|
|
172
|
+
* Private (`#`) rather than `readonly`: a public field is enumerable, so
|
|
173
|
+
* `JSON.stringify(client)` and every structured logger that walks own
|
|
174
|
+
* properties would write the key into a log line. `toJSON` and the inspect
|
|
175
|
+
* hook below close the two remaining paths - a bug report pasted from
|
|
176
|
+
* `console.log(client)` is exactly how a key gets shared with strangers.
|
|
177
|
+
*/
|
|
178
|
+
#apiKey;
|
|
179
|
+
#baseUrl;
|
|
180
|
+
#fetch;
|
|
181
|
+
#timeoutMs;
|
|
182
|
+
#maxAttempts;
|
|
183
|
+
#backoff;
|
|
184
|
+
#sleep;
|
|
185
|
+
#userAgent;
|
|
186
|
+
constructor(options) {
|
|
187
|
+
if (typeof options.apiKey !== "string" || options.apiKey.trim().length === 0) {
|
|
188
|
+
throw new PersistMemoryError({
|
|
189
|
+
status: 0,
|
|
190
|
+
code: "VALIDATION_ERROR",
|
|
191
|
+
message: "An API key is required. Pass `apiKey`, or set PERSISTMEMORY_API_KEY."
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
const key = options.apiKey.trim();
|
|
195
|
+
if (/[\r\n\0]/.test(key)) {
|
|
196
|
+
throw new PersistMemoryError({
|
|
197
|
+
status: 0,
|
|
198
|
+
code: "VALIDATION_ERROR",
|
|
199
|
+
message: "The API key contains characters that cannot go in a header."
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
this.#apiKey = key;
|
|
203
|
+
this.#baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
204
|
+
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
205
|
+
this.#timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
206
|
+
this.#maxAttempts = Math.max(1, options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS);
|
|
207
|
+
this.#backoff = options.backoff ?? {};
|
|
208
|
+
this.#sleep = options.sleep ?? defaultSleep;
|
|
209
|
+
this.#userAgent = options.userAgent ?? "persistmemory-sdk-js/0.1.0";
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* What this object looks like when something serialises it.
|
|
213
|
+
*
|
|
214
|
+
* Both hooks return the same key-free shape. `toJSON` covers
|
|
215
|
+
* `JSON.stringify`, the inspect symbol covers `console.log` under Node, and
|
|
216
|
+
* between them they cover how a credential actually escapes: not through a
|
|
217
|
+
* deliberate log line, but through an object dumped into a bug report.
|
|
218
|
+
*/
|
|
219
|
+
toJSON() {
|
|
220
|
+
return { baseUrl: this.#baseUrl, apiKey: "[redacted]" };
|
|
221
|
+
}
|
|
222
|
+
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
223
|
+
return this.toJSON();
|
|
224
|
+
}
|
|
225
|
+
async get(path, query, options) {
|
|
226
|
+
return this.#request({
|
|
227
|
+
method: "GET",
|
|
228
|
+
path,
|
|
229
|
+
...query ? { query } : {},
|
|
230
|
+
...options ? { options } : {}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
async post(path, body, options) {
|
|
234
|
+
return this.#request({
|
|
235
|
+
method: "POST",
|
|
236
|
+
path,
|
|
237
|
+
...body !== void 0 ? { body } : {},
|
|
238
|
+
...options ? { options } : {}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
async patch(path, body, options) {
|
|
242
|
+
return this.#request({
|
|
243
|
+
method: "PATCH",
|
|
244
|
+
path,
|
|
245
|
+
...body !== void 0 ? { body } : {},
|
|
246
|
+
...options ? { options } : {}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
async delete(path, body, options) {
|
|
250
|
+
return this.#request({
|
|
251
|
+
method: "DELETE",
|
|
252
|
+
path,
|
|
253
|
+
...body !== void 0 ? { body } : {},
|
|
254
|
+
...options ? { options } : {}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
async #request(request) {
|
|
258
|
+
const maxAttempts = Math.max(1, request.options?.maxAttempts ?? this.#maxAttempts);
|
|
259
|
+
const url = this.#baseUrl + request.path + encodeQuery(request.query);
|
|
260
|
+
let attempt = 0;
|
|
261
|
+
for (; ; ) {
|
|
262
|
+
attempt += 1;
|
|
263
|
+
let error;
|
|
264
|
+
try {
|
|
265
|
+
return await this.#attempt(request, url);
|
|
266
|
+
} catch (thrown) {
|
|
267
|
+
if (!(thrown instanceof PersistMemoryError)) throw thrown;
|
|
268
|
+
error = thrown;
|
|
269
|
+
}
|
|
270
|
+
if (attempt >= maxAttempts) throw error;
|
|
271
|
+
if (!mayRetry(error, request)) throw error;
|
|
272
|
+
const delay = delayFor({
|
|
273
|
+
attempt,
|
|
274
|
+
...error.retryAfterSeconds !== void 0 ? { retryAfterSeconds: error.retryAfterSeconds } : {},
|
|
275
|
+
options: this.#backoff
|
|
276
|
+
});
|
|
277
|
+
await this.#sleep(delay, request.options?.signal);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
async #attempt(request, url) {
|
|
281
|
+
const timeoutMs = request.options?.timeoutMs ?? this.#timeoutMs;
|
|
282
|
+
const deadline = new AbortController();
|
|
283
|
+
const timer = setTimeout(() => deadline.abort(), timeoutMs);
|
|
284
|
+
const onCallerAbort = () => deadline.abort();
|
|
285
|
+
const caller = request.options?.signal;
|
|
286
|
+
caller?.addEventListener("abort", onCallerAbort, { once: true });
|
|
287
|
+
try {
|
|
288
|
+
if (caller?.aborted) throw new AbortError();
|
|
289
|
+
const response = await untilAborted(
|
|
290
|
+
this.#fetch(url, {
|
|
291
|
+
method: request.method,
|
|
292
|
+
headers: this.#headers(request),
|
|
293
|
+
...request.body !== void 0 ? { body: JSON.stringify(request.body) } : {},
|
|
294
|
+
signal: deadline.signal
|
|
295
|
+
}),
|
|
296
|
+
deadline.signal
|
|
297
|
+
);
|
|
298
|
+
const payload = await readBody(response);
|
|
299
|
+
if (!response.ok) throw errorFromResponse(response.status, payload, response.headers);
|
|
300
|
+
return payload;
|
|
301
|
+
} catch (thrown) {
|
|
302
|
+
if (thrown instanceof PersistMemoryError) throw thrown;
|
|
303
|
+
if (caller?.aborted) throw new AbortError();
|
|
304
|
+
if (deadline.signal.aborted) {
|
|
305
|
+
throw new TimeoutError(`The request did not complete within ${timeoutMs}ms.`);
|
|
306
|
+
}
|
|
307
|
+
const detail = thrown instanceof Error ? redact(thrown.message) : "transport failure";
|
|
308
|
+
throw new ConnectionError(`Could not reach the API: ${detail}`);
|
|
309
|
+
} finally {
|
|
310
|
+
clearTimeout(timer);
|
|
311
|
+
caller?.removeEventListener("abort", onCallerAbort);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
#headers(request) {
|
|
315
|
+
return {
|
|
316
|
+
// The only place the key is ever read.
|
|
317
|
+
authorization: `Bearer ${this.#apiKey}`,
|
|
318
|
+
accept: "application/json",
|
|
319
|
+
"user-agent": this.#userAgent,
|
|
320
|
+
...request.body !== void 0 ? { "content-type": "application/json" } : {},
|
|
321
|
+
...request.options?.idempotencyKey ? { "idempotency-key": request.options.idempotencyKey } : {}
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
function mayRetry(error, request) {
|
|
326
|
+
if (!error.retryable) return false;
|
|
327
|
+
if (RETRY_WITHOUT_ASKING.has(request.method)) return true;
|
|
328
|
+
if (request.options?.idempotencyKey) return true;
|
|
329
|
+
return error.status === 429;
|
|
330
|
+
}
|
|
331
|
+
async function readBody(response) {
|
|
332
|
+
if (response.status === 204) return void 0;
|
|
333
|
+
const text = await response.text().catch(() => "");
|
|
334
|
+
if (text.length === 0) return void 0;
|
|
335
|
+
const type = response.headers.get("content-type") ?? "";
|
|
336
|
+
if (!type.includes("json")) return { raw: text.slice(0, 500) };
|
|
337
|
+
try {
|
|
338
|
+
return JSON.parse(text);
|
|
339
|
+
} catch {
|
|
340
|
+
return { raw: text.slice(0, 500) };
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
var SignalFired = class extends Error {
|
|
344
|
+
constructor() {
|
|
345
|
+
super("signal fired");
|
|
346
|
+
this.name = "SignalFired";
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
function untilAborted(work, signal) {
|
|
350
|
+
work.catch(() => void 0);
|
|
351
|
+
return new Promise((resolve, reject) => {
|
|
352
|
+
if (signal.aborted) {
|
|
353
|
+
reject(new SignalFired());
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
const onAbort = () => reject(new SignalFired());
|
|
357
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
358
|
+
work.then(
|
|
359
|
+
(value) => {
|
|
360
|
+
signal.removeEventListener("abort", onAbort);
|
|
361
|
+
resolve(value);
|
|
362
|
+
},
|
|
363
|
+
(error) => {
|
|
364
|
+
signal.removeEventListener("abort", onAbort);
|
|
365
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function defaultSleep(ms, signal) {
|
|
371
|
+
return new Promise((resolve, reject) => {
|
|
372
|
+
if (signal?.aborted) {
|
|
373
|
+
reject(new AbortError());
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const timer = setTimeout(() => {
|
|
377
|
+
signal?.removeEventListener("abort", onAbort);
|
|
378
|
+
resolve();
|
|
379
|
+
}, ms);
|
|
380
|
+
function onAbort() {
|
|
381
|
+
clearTimeout(timer);
|
|
382
|
+
reject(new AbortError());
|
|
383
|
+
}
|
|
384
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/pagination.ts
|
|
389
|
+
var Paginated = class {
|
|
390
|
+
#fetchPage;
|
|
391
|
+
constructor(fetchPage) {
|
|
392
|
+
this.#fetchPage = fetchPage;
|
|
393
|
+
}
|
|
394
|
+
/** The first page, and nothing more. For a UI that renders one page at a time. */
|
|
395
|
+
async first() {
|
|
396
|
+
return this.#fetchPage(void 0);
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Page by page, for a caller that wants the cursors or wants to stop early.
|
|
400
|
+
*
|
|
401
|
+
* A generator rather than an array of pages: fetching them all up front
|
|
402
|
+
* would make "show me the first ten" cost every page in the account.
|
|
403
|
+
*/
|
|
404
|
+
async *pages() {
|
|
405
|
+
let cursor;
|
|
406
|
+
const seen = /* @__PURE__ */ new Set();
|
|
407
|
+
for (; ; ) {
|
|
408
|
+
const page = await this.#fetchPage(cursor);
|
|
409
|
+
yield page;
|
|
410
|
+
const next = page.pagination.nextCursor;
|
|
411
|
+
if (!next) return;
|
|
412
|
+
if (seen.has(next)) return;
|
|
413
|
+
seen.add(next);
|
|
414
|
+
cursor = next;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
/** Every item across every page. `for await (const memory of ...)`. */
|
|
418
|
+
async *[Symbol.asyncIterator]() {
|
|
419
|
+
for await (const page of this.pages()) {
|
|
420
|
+
for (const item of page.data) yield item;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Everything, in one array.
|
|
425
|
+
*
|
|
426
|
+
* `maxItems` is not optional, and that is the point. An unbounded `all()` on
|
|
427
|
+
* an account with two hundred thousand memories is a request loop that runs
|
|
428
|
+
* for minutes and an array that exhausts the heap, and the call site that
|
|
429
|
+
* does it reads as innocently as any other. Ask for a number you can hold.
|
|
430
|
+
*/
|
|
431
|
+
async all(maxItems) {
|
|
432
|
+
const collected = [];
|
|
433
|
+
if (maxItems <= 0) return collected;
|
|
434
|
+
for await (const item of this) {
|
|
435
|
+
collected.push(item);
|
|
436
|
+
if (collected.length >= maxItems) break;
|
|
437
|
+
}
|
|
438
|
+
return collected;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
// src/resources/memories.ts
|
|
443
|
+
var Memories = class {
|
|
444
|
+
#http;
|
|
445
|
+
constructor(http) {
|
|
446
|
+
this.#http = http;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* One page, plus the cursor loop.
|
|
450
|
+
*
|
|
451
|
+
* Returns a `Paginated`, so `await memories.list().first()` gets a page and
|
|
452
|
+
* `for await (const memory of memories.list())` walks the lot. The filters
|
|
453
|
+
* are carried into every page automatically - a caller re-passing them per
|
|
454
|
+
* page is a caller who will eventually forget one, and the pages after that
|
|
455
|
+
* come from a differently filtered list.
|
|
456
|
+
*/
|
|
457
|
+
list(params = {}, options) {
|
|
458
|
+
return new Paginated(
|
|
459
|
+
(cursor) => this.#http.get(
|
|
460
|
+
"/api/v1/memories",
|
|
461
|
+
pageQuery(params, cursor, toQuery(params)),
|
|
462
|
+
options
|
|
463
|
+
)
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
async get(id, options) {
|
|
467
|
+
return this.#http.get(`/api/v1/memories/${encodeURIComponent(id)}`, void 0, options);
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Hands material to the ingestion pipeline. Needs a key with `write` scope.
|
|
471
|
+
*
|
|
472
|
+
* This does NOT create a memory, and the return type says so: it answers 202
|
|
473
|
+
* with a job id. Extraction, entity resolution, deduplication and conflict
|
|
474
|
+
* detection all run afterwards and may produce one memory, several, or none.
|
|
475
|
+
* Poll `client.jobs.get(result.jobId)` to find out which.
|
|
476
|
+
*
|
|
477
|
+
* Pass an `idempotencyKey` if this can be retried by anything - a queue, a
|
|
478
|
+
* user pressing a button twice, or this client's own retry loop, which
|
|
479
|
+
* refuses to repeat a POST without one. `remember:note-42`, not a fresh
|
|
480
|
+
* random value per call.
|
|
481
|
+
*/
|
|
482
|
+
async remember(params, options) {
|
|
483
|
+
return this.#http.post("/api/v1/remember", params, options);
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
function toQuery(params) {
|
|
487
|
+
return {
|
|
488
|
+
...params.type !== void 0 ? { type: params.type } : {},
|
|
489
|
+
...params.state !== void 0 ? { state: params.state } : {},
|
|
490
|
+
...params.scope !== void 0 ? { scope: params.scope } : {},
|
|
491
|
+
...params.spaceIds !== void 0 ? { spaceIds: params.spaceIds } : {},
|
|
492
|
+
...params.createdAfter !== void 0 ? { createdAfter: params.createdAfter } : {},
|
|
493
|
+
...params.createdBefore !== void 0 ? { createdBefore: params.createdBefore } : {},
|
|
494
|
+
...params.minConfidence !== void 0 ? { minConfidence: params.minConfidence } : {},
|
|
495
|
+
...params.includeHistorical !== void 0 ? { includeHistorical: params.includeHistorical } : {}
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/resources/search.ts
|
|
500
|
+
var Search = class {
|
|
501
|
+
#http;
|
|
502
|
+
constructor(http) {
|
|
503
|
+
this.#http = http;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Ranked results, with an account of how they were found.
|
|
507
|
+
*
|
|
508
|
+
* Read `diagnostics.degraded` before showing the results. Search degrades
|
|
509
|
+
* rather than fails - with embeddings unavailable it falls back to
|
|
510
|
+
* deterministic retrieval and still answers - and a UI that cannot tell
|
|
511
|
+
* degraded from healthy tells the user the system knows nothing when it is
|
|
512
|
+
* merely looking with one eye.
|
|
513
|
+
*/
|
|
514
|
+
async query(params, options) {
|
|
515
|
+
const query = {
|
|
516
|
+
query: params.query,
|
|
517
|
+
...params.limit !== void 0 ? { limit: params.limit } : {},
|
|
518
|
+
...params.scope !== void 0 ? { scope: params.scope } : {},
|
|
519
|
+
...params.spaceIds !== void 0 ? { spaceIds: params.spaceIds } : {},
|
|
520
|
+
...params.types !== void 0 ? { types: params.types } : {},
|
|
521
|
+
...params.minScore !== void 0 ? { minScore: params.minScore } : {},
|
|
522
|
+
...params.asOf !== void 0 ? { asOf: params.asOf } : {},
|
|
523
|
+
...params.includeHistorical !== void 0 ? { includeHistorical: params.includeHistorical } : {},
|
|
524
|
+
...params.includeEvidence !== void 0 ? { includeEvidence: params.includeEvidence } : {},
|
|
525
|
+
...params.explain !== void 0 ? { explain: params.explain } : {}
|
|
526
|
+
};
|
|
527
|
+
return this.#http.get("/api/v1/search", query, options);
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* A context window, assembled and ready to paste into a prompt.
|
|
531
|
+
*
|
|
532
|
+
* A POST that is safe to repeat - it reads and returns, it writes nothing -
|
|
533
|
+
* so this is one of the few places where retrying without an idempotency key
|
|
534
|
+
* would be harmless. It still is not retried by default: the request loop
|
|
535
|
+
* decides by METHOD, and a per-endpoint exception is a rule that holds until
|
|
536
|
+
* someone adds a POST next to it that does write.
|
|
537
|
+
*/
|
|
538
|
+
async context(params, options) {
|
|
539
|
+
return this.#http.post("/api/v1/context", params, options);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
// src/resources/spaces.ts
|
|
544
|
+
var Spaces = class {
|
|
545
|
+
#http;
|
|
546
|
+
constructor(http) {
|
|
547
|
+
this.#http = http;
|
|
548
|
+
}
|
|
549
|
+
list(params = {}, options) {
|
|
550
|
+
return new Paginated(
|
|
551
|
+
(cursor) => this.#http.get(
|
|
552
|
+
"/api/v1/spaces",
|
|
553
|
+
pageQuery(params, cursor, {
|
|
554
|
+
...params.includeArchived !== void 0 ? { includeArchived: params.includeArchived } : {}
|
|
555
|
+
}),
|
|
556
|
+
options
|
|
557
|
+
)
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
async get(id, options) {
|
|
561
|
+
return this.#http.get(`/api/v1/spaces/${encodeURIComponent(id)}`, void 0, options);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Creates a Space. Answers 201.
|
|
565
|
+
*
|
|
566
|
+
* Worth an idempotency key when a person is behind it: a double-clicked
|
|
567
|
+
* "create Space" button makes two Spaces called Work, and nothing later can
|
|
568
|
+
* tell which of them memories should have gone into.
|
|
569
|
+
*/
|
|
570
|
+
async create(params, options) {
|
|
571
|
+
return this.#http.post("/api/v1/spaces", params, options);
|
|
572
|
+
}
|
|
573
|
+
/** Renaming, retention, and archiving - `archived` is a field, not a verb. */
|
|
574
|
+
async update(id, params, options) {
|
|
575
|
+
return this.#http.patch(`/api/v1/spaces/${encodeURIComponent(id)}`, params, options);
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* The memories filed in a Space.
|
|
579
|
+
*
|
|
580
|
+
* This endpoint answers `{ data, pagination: { limit } }` with no cursor: it
|
|
581
|
+
* returns the first `limit` members and stops. Wrapped in a `Paginated`
|
|
582
|
+
* anyway so it reads like every other list, and it simply yields one page -
|
|
583
|
+
* a caller who needs more should filter `memories.list` by `spaceIds`, which
|
|
584
|
+
* is the endpoint that actually pages.
|
|
585
|
+
*/
|
|
586
|
+
memories(id, params = {}, options) {
|
|
587
|
+
return new Paginated(
|
|
588
|
+
() => this.#http.get(
|
|
589
|
+
`/api/v1/spaces/${encodeURIComponent(id)}/memories`,
|
|
590
|
+
{ ...params.limit !== void 0 ? { limit: params.limit } : {} },
|
|
591
|
+
options
|
|
592
|
+
)
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
async addMemories(id, memoryIds, options) {
|
|
596
|
+
return this.#http.post(
|
|
597
|
+
`/api/v1/spaces/${encodeURIComponent(id)}/memories`,
|
|
598
|
+
{ memoryIds },
|
|
599
|
+
options
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Removes memberships. The memories themselves are untouched.
|
|
604
|
+
*
|
|
605
|
+
* A body on a DELETE, which is unusual and is what the API takes: the
|
|
606
|
+
* alternative is five hundred ids in a query string, and every proxy in
|
|
607
|
+
* between has its own limit on how long a URL may be.
|
|
608
|
+
*/
|
|
609
|
+
async removeMemories(id, memoryIds, options) {
|
|
610
|
+
return this.#http.delete(
|
|
611
|
+
`/api/v1/spaces/${encodeURIComponent(id)}/memories`,
|
|
612
|
+
{ memoryIds },
|
|
613
|
+
options
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
// src/resources/ingestion.ts
|
|
619
|
+
var Sources = class {
|
|
620
|
+
#http;
|
|
621
|
+
constructor(http) {
|
|
622
|
+
this.#http = http;
|
|
623
|
+
}
|
|
624
|
+
list(params = {}, options) {
|
|
625
|
+
return new Paginated(
|
|
626
|
+
(cursor) => this.#http.get(
|
|
627
|
+
"/api/v1/sources",
|
|
628
|
+
pageQuery(params, cursor, {
|
|
629
|
+
...params.provider !== void 0 ? { provider: params.provider } : {}
|
|
630
|
+
}),
|
|
631
|
+
options
|
|
632
|
+
)
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
async get(id, options) {
|
|
636
|
+
return this.#http.get(`/api/v1/sources/${encodeURIComponent(id)}`, void 0, options);
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
var Documents = class {
|
|
640
|
+
#http;
|
|
641
|
+
constructor(http) {
|
|
642
|
+
this.#http = http;
|
|
643
|
+
}
|
|
644
|
+
list(params = {}, options) {
|
|
645
|
+
return new Paginated(
|
|
646
|
+
(cursor) => this.#http.get(
|
|
647
|
+
"/api/v1/documents",
|
|
648
|
+
pageQuery(params, cursor, {
|
|
649
|
+
...params.sourceId !== void 0 ? { sourceId: params.sourceId } : {},
|
|
650
|
+
...params.status !== void 0 ? { status: params.status } : {}
|
|
651
|
+
}),
|
|
652
|
+
options
|
|
653
|
+
)
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
async get(id, options) {
|
|
657
|
+
return this.#http.get(
|
|
658
|
+
`/api/v1/documents/${encodeURIComponent(id)}`,
|
|
659
|
+
void 0,
|
|
660
|
+
options
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
var Jobs = class {
|
|
665
|
+
#http;
|
|
666
|
+
constructor(http) {
|
|
667
|
+
this.#http = http;
|
|
668
|
+
}
|
|
669
|
+
list(params = {}, options) {
|
|
670
|
+
return new Paginated(
|
|
671
|
+
(cursor) => this.#http.get(
|
|
672
|
+
"/api/v1/jobs",
|
|
673
|
+
pageQuery(params, cursor, {
|
|
674
|
+
...params.status !== void 0 ? { status: params.status } : {},
|
|
675
|
+
...params.type !== void 0 ? { type: params.type } : {}
|
|
676
|
+
}),
|
|
677
|
+
options
|
|
678
|
+
)
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* One job, by id. This is what `remember` hands back a reference to.
|
|
683
|
+
*
|
|
684
|
+
* `completed` is the terminal success state - the store's own word, not
|
|
685
|
+
* `succeeded`. A caller polling for a state the API never writes waits
|
|
686
|
+
* forever with nothing to show why.
|
|
687
|
+
*/
|
|
688
|
+
async get(id, options) {
|
|
689
|
+
return this.#http.get(`/api/v1/jobs/${encodeURIComponent(id)}`, void 0, options);
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
// src/resources/knowledge.ts
|
|
694
|
+
var Entities = class {
|
|
695
|
+
#http;
|
|
696
|
+
constructor(http) {
|
|
697
|
+
this.#http = http;
|
|
698
|
+
}
|
|
699
|
+
list(params = {}, options) {
|
|
700
|
+
return new Paginated(
|
|
701
|
+
(cursor) => this.#http.get(
|
|
702
|
+
"/api/v1/entities",
|
|
703
|
+
pageQuery(params, cursor, {
|
|
704
|
+
...params.type !== void 0 ? { type: params.type } : {},
|
|
705
|
+
...params.q !== void 0 ? { q: params.q } : {}
|
|
706
|
+
}),
|
|
707
|
+
options
|
|
708
|
+
)
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
async get(id, options) {
|
|
712
|
+
return this.#http.get(`/api/v1/entities/${encodeURIComponent(id)}`, void 0, options);
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Which memories mention this entity, and how.
|
|
716
|
+
*
|
|
717
|
+
* Returns MENTIONS - a memory id, a role and a confidence - not the memories
|
|
718
|
+
* themselves. "Memories about Sam" and "memories Sam appears in" are
|
|
719
|
+
* different questions, and `role` is what separates them.
|
|
720
|
+
*
|
|
721
|
+
* Like the Space membership list, this endpoint answers with a `pagination`
|
|
722
|
+
* block that carries no cursor, so it yields one page and stops.
|
|
723
|
+
*/
|
|
724
|
+
memories(id, params = {}, options) {
|
|
725
|
+
return new Paginated(
|
|
726
|
+
(cursor) => this.#http.get(
|
|
727
|
+
`/api/v1/entities/${encodeURIComponent(id)}/memories`,
|
|
728
|
+
pageQuery(params, cursor, {
|
|
729
|
+
...params.role !== void 0 ? { role: params.role } : {},
|
|
730
|
+
...params.minConfidence !== void 0 ? { minConfidence: params.minConfidence } : {}
|
|
731
|
+
}),
|
|
732
|
+
options
|
|
733
|
+
)
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
var Graph = class {
|
|
738
|
+
#http;
|
|
739
|
+
constructor(http) {
|
|
740
|
+
this.#http = http;
|
|
741
|
+
}
|
|
742
|
+
async traverse(params, options) {
|
|
743
|
+
return this.#http.get(
|
|
744
|
+
"/api/v1/graph",
|
|
745
|
+
{
|
|
746
|
+
from: params.from,
|
|
747
|
+
...params.depth !== void 0 ? { depth: params.depth } : {},
|
|
748
|
+
...params.maxNodes !== void 0 ? { maxNodes: params.maxNodes } : {},
|
|
749
|
+
...params.memoryLimit !== void 0 ? { memoryLimit: params.memoryLimit } : {}
|
|
750
|
+
},
|
|
751
|
+
options
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
var Conflicts = class {
|
|
756
|
+
#http;
|
|
757
|
+
constructor(http) {
|
|
758
|
+
this.#http = http;
|
|
759
|
+
}
|
|
760
|
+
list(params = {}, options) {
|
|
761
|
+
return new Paginated(
|
|
762
|
+
(cursor) => this.#http.get(
|
|
763
|
+
"/api/v1/conflicts",
|
|
764
|
+
pageQuery(params, cursor, {
|
|
765
|
+
...params.includeResolved !== void 0 ? { includeResolved: params.includeResolved } : {},
|
|
766
|
+
...params.type !== void 0 ? { type: params.type } : {}
|
|
767
|
+
}),
|
|
768
|
+
options
|
|
769
|
+
)
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
async get(id, options) {
|
|
773
|
+
return this.#http.get(
|
|
774
|
+
`/api/v1/conflicts/${encodeURIComponent(id)}`,
|
|
775
|
+
void 0,
|
|
776
|
+
options
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Settles one.
|
|
781
|
+
*
|
|
782
|
+
* `keep` names the winner and supersedes the loser; it does not delete it.
|
|
783
|
+
* `dismiss` records that the detector was wrong, which is worth knowing when
|
|
784
|
+
* the same pair trips it again.
|
|
785
|
+
*
|
|
786
|
+
* The parameter type is a union, so `keep` without a `keepId` does not
|
|
787
|
+
* compile. The server rejects it too - this just moves the failure from a
|
|
788
|
+
* 400 in production to a red squiggle.
|
|
789
|
+
*/
|
|
790
|
+
async resolve(id, params, options) {
|
|
791
|
+
return this.#http.post(
|
|
792
|
+
`/api/v1/conflicts/${encodeURIComponent(id)}/resolve`,
|
|
793
|
+
params,
|
|
794
|
+
options
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
|
|
799
|
+
// src/resources/conversations.ts
|
|
800
|
+
var Conversations = class {
|
|
801
|
+
#http;
|
|
802
|
+
constructor(http) {
|
|
803
|
+
this.#http = http;
|
|
804
|
+
}
|
|
805
|
+
list(params = {}, options) {
|
|
806
|
+
return new Paginated(
|
|
807
|
+
(cursor) => this.#http.get(
|
|
808
|
+
"/api/v1/conversations",
|
|
809
|
+
pageQuery(params, cursor, {
|
|
810
|
+
...params.channel !== void 0 ? { channel: params.channel } : {}
|
|
811
|
+
}),
|
|
812
|
+
options
|
|
813
|
+
)
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
async get(id, options) {
|
|
817
|
+
return this.#http.get(
|
|
818
|
+
`/api/v1/conversations/${encodeURIComponent(id)}`,
|
|
819
|
+
void 0,
|
|
820
|
+
options
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
async create(params = {}, options) {
|
|
824
|
+
return this.#http.post("/api/v1/conversations", params, options);
|
|
825
|
+
}
|
|
826
|
+
messages(id, params = {}, options) {
|
|
827
|
+
return new Paginated(
|
|
828
|
+
(cursor) => this.#http.get(
|
|
829
|
+
`/api/v1/conversations/${encodeURIComponent(id)}/messages`,
|
|
830
|
+
pageQuery(params, cursor, {}),
|
|
831
|
+
options
|
|
832
|
+
)
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Appends turns, and by default extracts memories from them.
|
|
837
|
+
*
|
|
838
|
+
* Check `extracting` on the result. With no queue configured the turns are
|
|
839
|
+
* stored and never become memory, and the API says so in `note` rather than
|
|
840
|
+
* reporting a success - a caller that ignores it believes a memory is on its
|
|
841
|
+
* way that never arrives.
|
|
842
|
+
*
|
|
843
|
+
* `system` and `tool` turns are stored but never extracted: a system prompt
|
|
844
|
+
* is configuration, and remembering it would file our own instructions as
|
|
845
|
+
* the user's facts.
|
|
846
|
+
*
|
|
847
|
+
* Give this an `idempotencyKey`. Appending the same turn twice is the most
|
|
848
|
+
* likely duplicate in the whole API - a client reconnecting after a dropped
|
|
849
|
+
* response has no other way to tell whether its last write landed.
|
|
850
|
+
*/
|
|
851
|
+
async append(id, params, options) {
|
|
852
|
+
return this.#http.post(
|
|
853
|
+
`/api/v1/conversations/${encodeURIComponent(id)}/messages`,
|
|
854
|
+
params,
|
|
855
|
+
options
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
|
|
860
|
+
// src/resources/integrations.ts
|
|
861
|
+
var Integrations = class {
|
|
862
|
+
#http;
|
|
863
|
+
constructor(http) {
|
|
864
|
+
this.#http = http;
|
|
865
|
+
}
|
|
866
|
+
list(params = {}, options) {
|
|
867
|
+
return new Paginated(
|
|
868
|
+
(cursor) => this.#http.get(
|
|
869
|
+
"/api/v1/integrations",
|
|
870
|
+
pageQuery(params, cursor, {
|
|
871
|
+
...params.provider !== void 0 ? { provider: params.provider } : {},
|
|
872
|
+
...params.status !== void 0 ? { status: params.status } : {}
|
|
873
|
+
}),
|
|
874
|
+
options
|
|
875
|
+
)
|
|
876
|
+
);
|
|
877
|
+
}
|
|
878
|
+
/** Providers that can be connected at all. Not the user's own connections. */
|
|
879
|
+
async available(options) {
|
|
880
|
+
return this.#http.get("/api/v1/integrations/available", void 0, options);
|
|
881
|
+
}
|
|
882
|
+
async get(id, options) {
|
|
883
|
+
return this.#http.get(
|
|
884
|
+
`/api/v1/integrations/${encodeURIComponent(id)}`,
|
|
885
|
+
void 0,
|
|
886
|
+
options
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
async connect(params, options) {
|
|
890
|
+
return this.#http.post(
|
|
891
|
+
"/api/v1/integrations/connect",
|
|
892
|
+
params,
|
|
893
|
+
options
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
async update(id, params, options) {
|
|
897
|
+
return this.#http.patch(
|
|
898
|
+
`/api/v1/integrations/${encodeURIComponent(id)}`,
|
|
899
|
+
params,
|
|
900
|
+
options
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Asks for a sync now rather than waiting for the schedule. Answers 202.
|
|
905
|
+
*
|
|
906
|
+
* `full` re-reads everything and is deliberately opt-in: on a large Drive
|
|
907
|
+
* that is thousands of documents and a real bill. The incremental default is
|
|
908
|
+
* what should run almost always.
|
|
909
|
+
*/
|
|
910
|
+
async sync(id, params = {}, options) {
|
|
911
|
+
return this.#http.post(
|
|
912
|
+
`/api/v1/integrations/${encodeURIComponent(id)}/sync`,
|
|
913
|
+
params,
|
|
914
|
+
options
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Destroys the credentials. The row stays.
|
|
919
|
+
*
|
|
920
|
+
* History still has to attribute the memories this connection produced, and
|
|
921
|
+
* deleting the row would leave them pointing at nothing.
|
|
922
|
+
*/
|
|
923
|
+
async disconnect(id, options) {
|
|
924
|
+
return this.#http.delete(
|
|
925
|
+
`/api/v1/integrations/${encodeURIComponent(id)}`,
|
|
926
|
+
void 0,
|
|
927
|
+
options
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
|
|
932
|
+
// src/resources/health.ts
|
|
933
|
+
var Health = class {
|
|
934
|
+
#http;
|
|
935
|
+
constructor(http) {
|
|
936
|
+
this.#http = http;
|
|
937
|
+
}
|
|
938
|
+
async live(options) {
|
|
939
|
+
return this.#http.get("/health/live", void 0, options);
|
|
940
|
+
}
|
|
941
|
+
async ready(options) {
|
|
942
|
+
return this.#http.get("/health/ready", void 0, options);
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
// src/client.ts
|
|
947
|
+
var PersistMemory = class {
|
|
948
|
+
memories;
|
|
949
|
+
search;
|
|
950
|
+
spaces;
|
|
951
|
+
sources;
|
|
952
|
+
documents;
|
|
953
|
+
jobs;
|
|
954
|
+
entities;
|
|
955
|
+
graph;
|
|
956
|
+
conflicts;
|
|
957
|
+
conversations;
|
|
958
|
+
integrations;
|
|
959
|
+
health;
|
|
960
|
+
#http;
|
|
961
|
+
constructor(options) {
|
|
962
|
+
this.#http = new HttpClient(options);
|
|
963
|
+
this.memories = new Memories(this.#http);
|
|
964
|
+
this.search = new Search(this.#http);
|
|
965
|
+
this.spaces = new Spaces(this.#http);
|
|
966
|
+
this.sources = new Sources(this.#http);
|
|
967
|
+
this.documents = new Documents(this.#http);
|
|
968
|
+
this.jobs = new Jobs(this.#http);
|
|
969
|
+
this.entities = new Entities(this.#http);
|
|
970
|
+
this.graph = new Graph(this.#http);
|
|
971
|
+
this.conflicts = new Conflicts(this.#http);
|
|
972
|
+
this.conversations = new Conversations(this.#http);
|
|
973
|
+
this.integrations = new Integrations(this.#http);
|
|
974
|
+
this.health = new Health(this.#http);
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* An escape hatch for an endpoint this package has not caught up with.
|
|
978
|
+
*
|
|
979
|
+
* Typed as `unknown` on purpose: a caller reaching past the typed surface is
|
|
980
|
+
* taking responsibility for the shape, and handing them `any` would let that
|
|
981
|
+
* responsibility spread silently through their codebase.
|
|
982
|
+
*/
|
|
983
|
+
async request(method, path, body, options) {
|
|
984
|
+
if (method === "GET") return this.#http.get(path, void 0, options);
|
|
985
|
+
if (method === "POST") return this.#http.post(path, body, options);
|
|
986
|
+
if (method === "PATCH") return this.#http.patch(path, body, options);
|
|
987
|
+
return this.#http.delete(path, body, options);
|
|
988
|
+
}
|
|
989
|
+
/** Never the key. See `HttpClient.toJSON`, which this delegates to. */
|
|
990
|
+
toJSON() {
|
|
991
|
+
return this.#http.toJSON();
|
|
992
|
+
}
|
|
993
|
+
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
994
|
+
return this.#http.toJSON();
|
|
995
|
+
}
|
|
996
|
+
};
|
|
997
|
+
export {
|
|
998
|
+
AbortError,
|
|
999
|
+
AuthenticationError,
|
|
1000
|
+
ConflictError,
|
|
1001
|
+
ConnectionError,
|
|
1002
|
+
DEFAULT_BACKOFF,
|
|
1003
|
+
NotFoundError,
|
|
1004
|
+
Paginated,
|
|
1005
|
+
PermissionDeniedError,
|
|
1006
|
+
PersistMemory,
|
|
1007
|
+
PersistMemoryError,
|
|
1008
|
+
RateLimitError,
|
|
1009
|
+
ServerError,
|
|
1010
|
+
TimeoutError,
|
|
1011
|
+
ValidationError,
|
|
1012
|
+
backoffMs,
|
|
1013
|
+
delayFor
|
|
1014
|
+
};
|
|
1015
|
+
//# sourceMappingURL=index.js.map
|