@layerum-team/rag-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/dist/index.cjs ADDED
@@ -0,0 +1,447 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ LayerumApiError: () => LayerumApiError,
24
+ LayerumClient: () => LayerumClient
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/error.ts
29
+ var LayerumApiError = class extends Error {
30
+ status;
31
+ details;
32
+ path;
33
+ method;
34
+ constructor(message, status, details, method, path) {
35
+ super(message);
36
+ this.name = "LayerumApiError";
37
+ this.status = status;
38
+ this.details = details;
39
+ this.method = method;
40
+ this.path = path;
41
+ }
42
+ };
43
+
44
+ // src/http.ts
45
+ function normalizeErrorMessage(payload, status) {
46
+ const fallback = `Request failed (${status})`;
47
+ if (!payload || typeof payload !== "object") return fallback;
48
+ const message = payload.message;
49
+ if (Array.isArray(message)) {
50
+ return message.map((item) => typeof item === "string" ? item : JSON.stringify(item)).join(", ");
51
+ }
52
+ if (typeof message === "string") return message;
53
+ if (message && typeof message === "object") {
54
+ const nested = message.message;
55
+ if (typeof nested === "string") return nested;
56
+ }
57
+ return fallback;
58
+ }
59
+ function shouldRetry(status, method, attempt, maxRetries) {
60
+ if (attempt >= maxRetries) return false;
61
+ if (method === "POST" || method === "PATCH" || method === "DELETE") return false;
62
+ return status === 429 || status >= 500;
63
+ }
64
+ function sleep(ms) {
65
+ return new Promise((resolve) => setTimeout(resolve, ms));
66
+ }
67
+ var HttpClient = class {
68
+ baseUrl;
69
+ apiKey;
70
+ timeoutMs;
71
+ maxRetries;
72
+ constructor(options) {
73
+ this.baseUrl = options.baseUrl.replace(/\/+$/, "");
74
+ this.apiKey = options.apiKey;
75
+ this.timeoutMs = options.timeoutMs;
76
+ this.maxRetries = options.maxRetries;
77
+ }
78
+ async request(path, options = {}) {
79
+ const method = options.method ?? "GET";
80
+ let attempt = 0;
81
+ while (true) {
82
+ const controller = new AbortController();
83
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
84
+ try {
85
+ const response = await fetch(`${this.baseUrl}${path}`, {
86
+ method,
87
+ headers: options.isFormData ? { Authorization: `Bearer ${this.apiKey}` } : {
88
+ "Content-Type": "application/json",
89
+ Authorization: `Bearer ${this.apiKey}`
90
+ },
91
+ body: options.body === void 0 ? void 0 : options.isFormData ? options.body : JSON.stringify(options.body),
92
+ signal: controller.signal
93
+ });
94
+ if (!response.ok) {
95
+ const payload = await response.json().catch(() => null);
96
+ const message = normalizeErrorMessage(payload, response.status);
97
+ if (shouldRetry(response.status, method, attempt, this.maxRetries)) {
98
+ attempt += 1;
99
+ await sleep(250 * attempt);
100
+ continue;
101
+ }
102
+ throw new LayerumApiError(
103
+ message,
104
+ response.status,
105
+ payload?.details,
106
+ method,
107
+ path
108
+ );
109
+ }
110
+ if (response.status === 204) return void 0;
111
+ return await response.json();
112
+ } catch (error) {
113
+ if (error instanceof LayerumApiError) throw error;
114
+ const message = error instanceof Error ? error.message : "Unknown network error";
115
+ throw new LayerumApiError(
116
+ `Network error while ${method} ${path}: ${message}`,
117
+ 0,
118
+ error,
119
+ method,
120
+ path
121
+ );
122
+ } finally {
123
+ clearTimeout(timeout);
124
+ }
125
+ }
126
+ }
127
+ };
128
+
129
+ // src/client.ts
130
+ function sleep2(ms) {
131
+ return new Promise((resolve) => setTimeout(resolve, ms));
132
+ }
133
+ function toBlob(file) {
134
+ if (typeof Blob !== "undefined" && file instanceof Blob) return file;
135
+ if (file instanceof ArrayBuffer) return new Blob([file]);
136
+ if (file instanceof Uint8Array) {
137
+ return new Blob([file]);
138
+ }
139
+ return new Blob([file]);
140
+ }
141
+ function unwrapItems(payload) {
142
+ if (!payload) return [];
143
+ if (Array.isArray(payload)) return payload;
144
+ return payload.items ?? [];
145
+ }
146
+ var EntitiesApi = class {
147
+ constructor(http) {
148
+ this.http = http;
149
+ }
150
+ async list(parentId) {
151
+ const payload = await this.http.request("/v1/entities");
152
+ const items = unwrapItems(payload);
153
+ if (!parentId) return items;
154
+ return items.filter(
155
+ (item) => (item.parentId ?? item.parent_id ?? null) === parentId
156
+ );
157
+ }
158
+ async tree() {
159
+ const payload = await this.http.request("/v1/entities/tree");
160
+ return unwrapItems(payload);
161
+ }
162
+ create(input) {
163
+ return this.http.request("/v1/entities", {
164
+ method: "POST",
165
+ body: {
166
+ entity_type_id: input.entityTypeId,
167
+ name: input.name,
168
+ description: input.description,
169
+ parent_id: input.parentId,
170
+ metadata: input.metadata
171
+ }
172
+ });
173
+ }
174
+ remove(entityId) {
175
+ return this.http.request(`/v1/entities/${entityId}`, {
176
+ method: "DELETE"
177
+ });
178
+ }
179
+ };
180
+ var EntityTypesApi = class {
181
+ constructor(http) {
182
+ this.http = http;
183
+ }
184
+ async list() {
185
+ const payload = await this.http.request(
186
+ "/v1/entity-types"
187
+ );
188
+ return unwrapItems(payload);
189
+ }
190
+ get(entityTypeId) {
191
+ return this.http.request(`/v1/entity-types/${entityTypeId}`);
192
+ }
193
+ create(input) {
194
+ return this.http.request("/v1/entity-types", {
195
+ method: "POST",
196
+ body: {
197
+ name: input.name,
198
+ label: input.label
199
+ }
200
+ });
201
+ }
202
+ remove(entityTypeId) {
203
+ return this.http.request(
204
+ `/v1/entity-types/${entityTypeId}`,
205
+ {
206
+ method: "DELETE"
207
+ }
208
+ );
209
+ }
210
+ };
211
+ var DocumentsApi = class {
212
+ constructor(http) {
213
+ this.http = http;
214
+ }
215
+ async list(input) {
216
+ const path = input.allInWorkspace ? "/v1/documents" : `/v1/entities/${input.entityId}/documents`;
217
+ const payload = await this.http.request(path);
218
+ return unwrapItems(payload);
219
+ }
220
+ get(entityId, sourceId) {
221
+ return this.http.request(
222
+ `/v1/entities/${entityId}/documents/${sourceId}`
223
+ );
224
+ }
225
+ upload(input) {
226
+ const form = new FormData();
227
+ form.set("file", toBlob(input.file), input.fileName);
228
+ if (input.visibility) form.set("visibility", input.visibility);
229
+ if (input.modelConfigId) form.set("model_config_id", input.modelConfigId);
230
+ return this.http.request(
231
+ `/v1/entities/${input.entityId}/documents/upload`,
232
+ {
233
+ method: "POST",
234
+ body: form,
235
+ isFormData: true
236
+ }
237
+ );
238
+ }
239
+ uploadInit(input) {
240
+ return this.http.request(
241
+ `/v1/entities/${input.entityId}/documents/upload/init`,
242
+ {
243
+ method: "POST",
244
+ body: {
245
+ file_name: input.fileName,
246
+ file_size_bytes: input.fileSizeBytes,
247
+ content_type: input.contentType,
248
+ visibility: input.visibility,
249
+ model_config_id: input.modelConfigId
250
+ }
251
+ }
252
+ );
253
+ }
254
+ uploadComplete(input) {
255
+ return this.http.request(
256
+ `/v1/entities/${input.entityId}/documents/upload/complete`,
257
+ {
258
+ method: "POST",
259
+ body: {
260
+ upload_id: input.uploadId,
261
+ display_name: input.displayName,
262
+ visibility: input.visibility,
263
+ model_config_id: input.modelConfigId,
264
+ checksum: input.checksum
265
+ }
266
+ }
267
+ );
268
+ }
269
+ async uploadDirect(input) {
270
+ const blob = toBlob(input.file);
271
+ const contentType = input.contentType || blob.type || "application/octet-stream";
272
+ const initialized = await this.uploadInit({
273
+ entityId: input.entityId,
274
+ fileName: input.fileName,
275
+ fileSizeBytes: blob.size,
276
+ contentType,
277
+ visibility: input.visibility,
278
+ modelConfigId: input.modelConfigId
279
+ });
280
+ const form = new FormData();
281
+ for (const [key, value] of Object.entries(initialized.fields ?? {})) {
282
+ form.set(key, value);
283
+ }
284
+ form.set("file", blob, input.fileName);
285
+ const uploadRes = await fetch(initialized.uploadUrl, {
286
+ method: initialized.method ?? "POST",
287
+ body: form
288
+ });
289
+ if (!uploadRes.ok) {
290
+ throw new Error(`Direct upload failed with status ${uploadRes.status}`);
291
+ }
292
+ return this.uploadComplete({
293
+ entityId: input.entityId,
294
+ uploadId: initialized.uploadId,
295
+ displayName: input.fileName,
296
+ visibility: input.visibility,
297
+ modelConfigId: input.modelConfigId
298
+ });
299
+ }
300
+ createText(input) {
301
+ return this.http.request(`/v1/entities/${input.entityId}/documents`, {
302
+ method: "POST",
303
+ body: {
304
+ source_type: "text",
305
+ display_name: input.displayName,
306
+ raw_text: input.rawText,
307
+ visibility: input.visibility ?? "self_and_descendants",
308
+ model_config_id: input.modelConfigId
309
+ }
310
+ });
311
+ }
312
+ createUrl(input) {
313
+ return this.http.request(`/v1/entities/${input.entityId}/documents`, {
314
+ method: "POST",
315
+ body: {
316
+ source_type: "url",
317
+ display_name: input.displayName,
318
+ source_url: input.sourceUrl,
319
+ visibility: input.visibility ?? "self_and_descendants",
320
+ model_config_id: input.modelConfigId
321
+ }
322
+ });
323
+ }
324
+ remove(input) {
325
+ return this.http.request(
326
+ `/v1/entities/${input.entityId}/documents/${input.sourceId}`,
327
+ {
328
+ method: "DELETE"
329
+ }
330
+ );
331
+ }
332
+ };
333
+ var IngestionApi = class {
334
+ constructor(http, documentsApi) {
335
+ this.http = http;
336
+ this.documentsApi = documentsApi;
337
+ }
338
+ retry(input) {
339
+ return this.http.request(
340
+ `/v1/entities/${input.entityId}/documents/${input.sourceId}/retry`,
341
+ {
342
+ method: "POST"
343
+ }
344
+ );
345
+ }
346
+ error(input) {
347
+ return this.http.request(
348
+ `/v1/entities/${input.entityId}/documents/${input.sourceId}/error`
349
+ );
350
+ }
351
+ async waitUntilReady(input) {
352
+ const timeoutMs = input.timeoutMs ?? 12e4;
353
+ const intervalMs = input.intervalMs ?? 2e3;
354
+ const start = Date.now();
355
+ while (true) {
356
+ const source = await this.documentsApi.get(input.entityId, input.sourceId);
357
+ if (source.status === "completed") return source;
358
+ if (source.status === "failed") {
359
+ const details = await this.error({
360
+ entityId: input.entityId,
361
+ sourceId: input.sourceId
362
+ }).catch(() => null);
363
+ throw new Error(
364
+ `Ingestion failed for source ${input.sourceId}${details?.latestJob?.error_message ? `: ${details.latestJob.error_message}` : ""}`
365
+ );
366
+ }
367
+ if (Date.now() - start >= timeoutMs) {
368
+ throw new Error(
369
+ `Timed out waiting for source ${input.sourceId} to complete ingestion`
370
+ );
371
+ }
372
+ await sleep2(intervalMs);
373
+ }
374
+ }
375
+ };
376
+ var QueryApi = class {
377
+ constructor(http) {
378
+ this.http = http;
379
+ }
380
+ run(input) {
381
+ return this.http.request("/v1/query", {
382
+ method: "POST",
383
+ body: {
384
+ entityId: input.entityId,
385
+ modelConfigId: input.modelConfigId,
386
+ query: input.query,
387
+ topK: input.topK,
388
+ includeParentScopes: input.includeParentScopes
389
+ }
390
+ });
391
+ }
392
+ runDebug(input) {
393
+ return this.http.request("/v1/query/debug", {
394
+ method: "POST",
395
+ body: {
396
+ entityId: input.entityId,
397
+ modelConfigId: input.modelConfigId,
398
+ query: input.query,
399
+ topK: input.topK,
400
+ includeParentScopes: input.includeParentScopes
401
+ }
402
+ });
403
+ }
404
+ };
405
+ var ModelsApi = class {
406
+ constructor(http) {
407
+ this.http = http;
408
+ }
409
+ async listConfigs() {
410
+ const payload = await this.http.request("/v1/models");
411
+ return unwrapItems(payload);
412
+ }
413
+ async listDefinitions(input) {
414
+ const query = input?.type ? `?type=${encodeURIComponent(input.type)}` : "";
415
+ const payload = await this.http.request(
416
+ `/v1/model-definitions${query}`
417
+ );
418
+ return unwrapItems(payload);
419
+ }
420
+ };
421
+ var LayerumClient = class {
422
+ entities;
423
+ entityTypes;
424
+ documents;
425
+ ingestion;
426
+ query;
427
+ models;
428
+ constructor(options) {
429
+ const http = new HttpClient({
430
+ apiKey: options.apiKey,
431
+ baseUrl: options.baseUrl ?? "http://localhost:4000",
432
+ timeoutMs: options.timeoutMs ?? 3e4,
433
+ maxRetries: options.maxRetries ?? 2
434
+ });
435
+ this.entities = new EntitiesApi(http);
436
+ this.entityTypes = new EntityTypesApi(http);
437
+ this.documents = new DocumentsApi(http);
438
+ this.ingestion = new IngestionApi(http, this.documents);
439
+ this.query = new QueryApi(http);
440
+ this.models = new ModelsApi(http);
441
+ }
442
+ };
443
+ // Annotate the CommonJS export names for ESM import in node:
444
+ 0 && (module.exports = {
445
+ LayerumApiError,
446
+ LayerumClient
447
+ });