@agentuity/core 0.0.33 → 0.0.35

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.
Files changed (42) hide show
  1. package/dist/index.js +5 -0
  2. package/dist/index.js.map +1 -0
  3. package/dist/json.js +23 -0
  4. package/dist/json.js.map +1 -0
  5. package/dist/services/_util.js +107 -0
  6. package/dist/services/_util.js.map +1 -0
  7. package/dist/services/adapter.js +2 -0
  8. package/dist/services/adapter.js.map +1 -0
  9. package/dist/services/exception.js +8 -0
  10. package/dist/services/exception.js.map +1 -0
  11. package/dist/services/index.js +8 -0
  12. package/dist/services/index.js.map +1 -0
  13. package/dist/services/keyvalue.js +85 -0
  14. package/dist/services/keyvalue.js.map +1 -0
  15. package/dist/services/objectstore.js +218 -0
  16. package/dist/services/objectstore.js.map +1 -0
  17. package/dist/services/stream.js +392 -0
  18. package/dist/services/stream.js.map +1 -0
  19. package/dist/services/vector.js +242 -0
  20. package/dist/services/vector.js.map +1 -0
  21. package/dist/standard_schema.js +2 -0
  22. package/dist/standard_schema.js.map +1 -0
  23. package/dist/typehelper.js +2 -0
  24. package/dist/typehelper.js.map +1 -0
  25. package/package.json +5 -4
  26. package/src/index.ts +4 -0
  27. package/src/json.ts +26 -0
  28. package/src/services/__test__/keyvalue.test.ts +402 -0
  29. package/src/services/__test__/mock-adapter.ts +114 -0
  30. package/src/services/__test__/objectstore.test.ts +431 -0
  31. package/src/services/__test__/stream.test.ts +554 -0
  32. package/src/services/__test__/vector.test.ts +813 -0
  33. package/src/services/_util.ts +117 -0
  34. package/src/services/adapter.ts +33 -0
  35. package/src/services/exception.ts +7 -0
  36. package/src/services/index.ts +7 -0
  37. package/src/services/keyvalue.ts +185 -0
  38. package/src/services/objectstore.ts +466 -0
  39. package/src/services/stream.ts +614 -0
  40. package/src/services/vector.ts +599 -0
  41. package/src/standard_schema.ts +69 -0
  42. package/src/typehelper.ts +5 -0
@@ -0,0 +1,466 @@
1
+ import type { FetchAdapter, FetchRequest, Body } from './adapter';
2
+ import { buildUrl, toServiceException } from './_util';
3
+
4
+ /**
5
+ * Parameters for putting an object into the object store
6
+ */
7
+ export interface ObjectStorePutParams {
8
+ /**
9
+ * the content type of the object
10
+ */
11
+ contentType?: string;
12
+
13
+ /**
14
+ * the content encoding of the object
15
+ */
16
+ contentEncoding?: string;
17
+
18
+ /**
19
+ * the cache control header for the object
20
+ */
21
+ cacheControl?: string;
22
+
23
+ /**
24
+ * the content disposition header for the object
25
+ */
26
+ contentDisposition?: string;
27
+
28
+ /**
29
+ * the content language header for the object
30
+ */
31
+ contentLanguage?: string;
32
+
33
+ /**
34
+ * arbitrary metadata to attach to the object but not returned as part of the object when fetched via HTTP
35
+ */
36
+ metadata?: Record<string, string>;
37
+ }
38
+
39
+ /**
40
+ * Result when an object is found in the object store
41
+ */
42
+ export interface ObjectResultFound {
43
+ /**
44
+ * the object data
45
+ */
46
+ data: Uint8Array;
47
+
48
+ /**
49
+ * the content type of the object
50
+ */
51
+ contentType: string;
52
+
53
+ /**
54
+ * the object was found
55
+ */
56
+ exists: true;
57
+ }
58
+
59
+ /**
60
+ * Result when an object is not found in the object store
61
+ */
62
+ export interface ObjectResultNotFound {
63
+ data: never;
64
+
65
+ /**
66
+ * the object was not found
67
+ */
68
+ exists: false;
69
+ }
70
+
71
+ /**
72
+ * The result of an object store get operation
73
+ */
74
+ export type ObjectResult = ObjectResultFound | ObjectResultNotFound;
75
+
76
+ /**
77
+ * Parameters for creating a public URL
78
+ */
79
+ export interface CreatePublicURLParams {
80
+ /**
81
+ * the duration of the signed URL in milliseconds. If not provided, the default is 1 hour.
82
+ */
83
+ expiresDuration?: number;
84
+ }
85
+
86
+ interface ObjectStoreCreatePublicURLSuccessResponse {
87
+ success: true;
88
+ url: string;
89
+ }
90
+
91
+ interface ObjectStoreCreatePublicURLErrorResponse {
92
+ success: false;
93
+ message: string;
94
+ }
95
+
96
+ type ObjectStoreCreatePublicURLResponse =
97
+ | ObjectStoreCreatePublicURLSuccessResponse
98
+ | ObjectStoreCreatePublicURLErrorResponse;
99
+
100
+ /**
101
+ * Object store service for storing and retrieving binary data
102
+ */
103
+ export interface ObjectStorage {
104
+ /**
105
+ * Get an object from the object store
106
+ *
107
+ * @param bucket - the bucket to get the object from
108
+ * @param key - the key of the object to get
109
+ * @returns a Promise that resolves to the object result
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const result = await objectStore.get('my-bucket', 'my-key');
114
+ * if (result.exists) {
115
+ * console.log('Content type:', result.contentType);
116
+ * console.log('Data:', result.data);
117
+ * }
118
+ * ```
119
+ */
120
+ get(bucket: string, key: string): Promise<ObjectResult>;
121
+
122
+ /**
123
+ * Put an object into the object store
124
+ *
125
+ * @param bucket - the bucket to put the object into
126
+ * @param key - the key of the object to put
127
+ * @param data - the data to put (Uint8Array, ArrayBuffer, or ReadableStream)
128
+ * @param params - optional parameters for the put operation
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const data = new TextEncoder().encode('Hello, world!');
133
+ * await objectStore.put('my-bucket', 'greeting.txt', data, {
134
+ * contentType: 'text/plain',
135
+ * metadata: { author: 'user123' }
136
+ * });
137
+ * ```
138
+ */
139
+ put(
140
+ bucket: string,
141
+ key: string,
142
+ data: Uint8Array | ArrayBuffer | ReadableStream,
143
+ params?: ObjectStorePutParams
144
+ ): Promise<void>;
145
+
146
+ /**
147
+ * Delete an object from the object store
148
+ *
149
+ * @param bucket - the bucket to delete the object from
150
+ * @param key - the key of the object to delete
151
+ * @returns true if the object was deleted, false if the object did not exist
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * const deleted = await objectStore.delete('my-bucket', 'my-key');
156
+ * if (deleted) {
157
+ * console.log('Object was deleted');
158
+ * } else {
159
+ * console.log('Object did not exist');
160
+ * }
161
+ * ```
162
+ */
163
+ delete(bucket: string, key: string): Promise<boolean>;
164
+
165
+ /**
166
+ * Create a public URL for an object. This URL can be used to access the object without authentication.
167
+ *
168
+ * @param bucket - the bucket to create the signed URL for
169
+ * @param key - the key of the object to create the signed URL for
170
+ * @param params - optional parameters including expiration duration
171
+ * @returns the public URL
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * const url = await objectStore.createPublicURL('my-bucket', 'my-key', {
176
+ * expiresDuration: 3600000 // 1 hour in milliseconds
177
+ * });
178
+ * console.log('Public URL:', url);
179
+ * ```
180
+ */
181
+ createPublicURL(bucket: string, key: string, params?: CreatePublicURLParams): Promise<string>;
182
+ }
183
+
184
+ /**
185
+ * Implementation of the ObjectStorage interface
186
+ */
187
+ export class ObjectStorageService implements ObjectStorage {
188
+ #adapter: FetchAdapter;
189
+ #baseUrl: string;
190
+
191
+ constructor(baseUrl: string, adapter: FetchAdapter) {
192
+ this.#baseUrl = baseUrl;
193
+ this.#adapter = adapter;
194
+ }
195
+
196
+ async get(bucket: string, key: string): Promise<ObjectResult> {
197
+ if (!bucket?.trim()) {
198
+ throw new Error('bucket is required and cannot be empty');
199
+ }
200
+ if (!key?.trim()) {
201
+ throw new Error('key is required and cannot be empty');
202
+ }
203
+
204
+ const url = buildUrl(
205
+ this.#baseUrl,
206
+ `/object/2025-03-17/${encodeURIComponent(bucket)}/${encodeURIComponent(key)}`
207
+ );
208
+
209
+ const signal = AbortSignal.timeout(10_000);
210
+ const options: FetchRequest = {
211
+ method: 'GET',
212
+ signal,
213
+ telemetry: {
214
+ name: 'agentuity.objectstore.get',
215
+ attributes: {
216
+ 'objectstore.bucket': bucket,
217
+ 'objectstore.key': key,
218
+ },
219
+ },
220
+ };
221
+
222
+ try {
223
+ const result = await this.#adapter.invoke<ArrayBuffer>(url, options);
224
+
225
+ if (result.response.status === 404) {
226
+ return { exists: false } as ObjectResultNotFound;
227
+ }
228
+
229
+ if (!result.ok) {
230
+ throw new Error(
231
+ `Failed to get object: ${result.response.statusText} (${result.response.status})`
232
+ );
233
+ }
234
+
235
+ const data = result.data;
236
+ if (!(data instanceof ArrayBuffer)) {
237
+ throw new Error('Expected ArrayBuffer response from object store');
238
+ }
239
+
240
+ const contentType =
241
+ result.response.headers.get('content-type') || 'application/octet-stream';
242
+
243
+ return {
244
+ exists: true,
245
+ data: new Uint8Array(data),
246
+ contentType,
247
+ } as ObjectResultFound;
248
+ } catch (err) {
249
+ if (err instanceof Response) {
250
+ throw await toServiceException(err);
251
+ }
252
+ throw err;
253
+ }
254
+ }
255
+
256
+ async put(
257
+ bucket: string,
258
+ key: string,
259
+ data: Uint8Array | ArrayBuffer | ReadableStream,
260
+ params?: ObjectStorePutParams
261
+ ): Promise<void> {
262
+ if (!bucket?.trim()) {
263
+ throw new Error('bucket is required and cannot be empty');
264
+ }
265
+ if (!key?.trim()) {
266
+ throw new Error('key is required and cannot be empty');
267
+ }
268
+ if (!data) {
269
+ throw new Error('data is required');
270
+ }
271
+
272
+ const url = buildUrl(
273
+ this.#baseUrl,
274
+ `/object/2025-03-17/${encodeURIComponent(bucket)}/${encodeURIComponent(key)}`
275
+ );
276
+
277
+ const headers: Record<string, string> = {
278
+ 'Content-Type': params?.contentType || 'application/octet-stream',
279
+ };
280
+
281
+ if (params?.contentEncoding) {
282
+ headers['Content-Encoding'] = params.contentEncoding;
283
+ }
284
+
285
+ if (params?.cacheControl) {
286
+ headers['Cache-Control'] = params.cacheControl;
287
+ }
288
+
289
+ if (params?.contentDisposition) {
290
+ headers['Content-Disposition'] = params.contentDisposition;
291
+ }
292
+
293
+ if (params?.contentLanguage) {
294
+ headers['Content-Language'] = params.contentLanguage;
295
+ }
296
+
297
+ if (params?.metadata) {
298
+ for (const [metaKey, metaValue] of Object.entries(params.metadata)) {
299
+ headers[`x-metadata-${metaKey}`] = metaValue;
300
+ }
301
+ }
302
+
303
+ let body: Body;
304
+ if (data instanceof ArrayBuffer) {
305
+ body = data;
306
+ } else if (data instanceof Uint8Array) {
307
+ if (data.byteOffset !== 0 || data.byteLength !== data.buffer.byteLength) {
308
+ body = data.buffer.slice(
309
+ data.byteOffset,
310
+ data.byteOffset + data.byteLength
311
+ ) as ArrayBuffer;
312
+ } else {
313
+ body = data.buffer as ArrayBuffer;
314
+ }
315
+ } else {
316
+ body = data;
317
+ }
318
+
319
+ const signal = AbortSignal.timeout(30_000);
320
+ const options: FetchRequest = {
321
+ method: 'PUT',
322
+ headers,
323
+ body,
324
+ signal,
325
+ telemetry: {
326
+ name: 'agentuity.objectstore.put',
327
+ attributes: {
328
+ 'objectstore.bucket': bucket,
329
+ 'objectstore.key': key,
330
+ 'objectstore.contentType': params?.contentType || 'application/octet-stream',
331
+ },
332
+ },
333
+ };
334
+
335
+ try {
336
+ const result = await this.#adapter.invoke(url, options);
337
+
338
+ if (!result.ok || (result.response.status !== 200 && result.response.status !== 201)) {
339
+ throw new Error(
340
+ `Failed to put object: ${result.response.statusText} (${result.response.status})`
341
+ );
342
+ }
343
+ } catch (err) {
344
+ if (err instanceof Response) {
345
+ throw await toServiceException(err);
346
+ }
347
+ throw err;
348
+ }
349
+ }
350
+
351
+ async delete(bucket: string, key: string): Promise<boolean> {
352
+ if (!bucket?.trim()) {
353
+ throw new Error('bucket is required and cannot be empty');
354
+ }
355
+ if (!key?.trim()) {
356
+ throw new Error('key is required and cannot be empty');
357
+ }
358
+
359
+ const url = buildUrl(
360
+ this.#baseUrl,
361
+ `/object/2025-03-17/${encodeURIComponent(bucket)}/${encodeURIComponent(key)}`
362
+ );
363
+
364
+ const signal = AbortSignal.timeout(10_000);
365
+ const options: FetchRequest = {
366
+ method: 'DELETE',
367
+ signal,
368
+ telemetry: {
369
+ name: 'agentuity.objectstore.delete',
370
+ attributes: {
371
+ 'objectstore.bucket': bucket,
372
+ 'objectstore.key': key,
373
+ },
374
+ },
375
+ };
376
+
377
+ try {
378
+ const result = await this.#adapter.invoke(url, options);
379
+
380
+ if (result.response.status === 404) {
381
+ return false;
382
+ }
383
+
384
+ if (result.response.status === 200) {
385
+ return true;
386
+ }
387
+
388
+ throw new Error(
389
+ `Failed to delete object: ${result.response.statusText} (${result.response.status})`
390
+ );
391
+ } catch (err) {
392
+ if (err instanceof Response) {
393
+ throw await toServiceException(err);
394
+ }
395
+ throw err;
396
+ }
397
+ }
398
+
399
+ async createPublicURL(
400
+ bucket: string,
401
+ key: string,
402
+ params?: CreatePublicURLParams
403
+ ): Promise<string> {
404
+ if (!bucket?.trim()) {
405
+ throw new Error('bucket is required and cannot be empty');
406
+ }
407
+ if (!key?.trim()) {
408
+ throw new Error('key is required and cannot be empty');
409
+ }
410
+
411
+ const url = buildUrl(
412
+ this.#baseUrl,
413
+ `/object/2025-03-17/presigned/${encodeURIComponent(bucket)}/${encodeURIComponent(key)}`
414
+ );
415
+
416
+ const requestBody: { expires?: number } = {};
417
+ if (params?.expiresDuration) {
418
+ requestBody.expires = params.expiresDuration;
419
+ }
420
+
421
+ const signal = AbortSignal.timeout(10_000);
422
+ const options: FetchRequest = {
423
+ method: 'POST',
424
+ contentType: 'application/json',
425
+ body: JSON.stringify(requestBody),
426
+ signal,
427
+ telemetry: {
428
+ name: 'agentuity.objectstore.createPublicURL',
429
+ attributes: {
430
+ 'objectstore.bucket': bucket,
431
+ 'objectstore.key': key,
432
+ 'objectstore.expiresDuration': params?.expiresDuration?.toString() || '',
433
+ },
434
+ },
435
+ };
436
+
437
+ try {
438
+ const result = await this.#adapter.invoke<ObjectStoreCreatePublicURLResponse>(
439
+ url,
440
+ options
441
+ );
442
+
443
+ if (!result.ok) {
444
+ throw new Error(
445
+ `Failed to create public URL: ${result.response.statusText} (${result.response.status})`
446
+ );
447
+ }
448
+
449
+ const data = result.data;
450
+
451
+ if (!data.success) {
452
+ throw new Error(data.message || 'Failed to create public URL');
453
+ }
454
+
455
+ return data.url;
456
+ } catch (err) {
457
+ if (err instanceof Error && err.message.includes('Object not found')) {
458
+ throw err;
459
+ }
460
+ if (err instanceof Response) {
461
+ throw await toServiceException(err);
462
+ }
463
+ throw err;
464
+ }
465
+ }
466
+ }