@agentuity/core 0.0.68 → 0.0.70
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/services/_util.d.ts.map +1 -1
- package/dist/services/_util.js +11 -1
- package/dist/services/_util.js.map +1 -1
- package/dist/services/index.d.ts +0 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +0 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/session.d.ts +4 -2
- package/dist/services/session.d.ts.map +1 -1
- package/dist/services/session.js +2 -1
- package/dist/services/session.js.map +1 -1
- package/dist/services/stream.d.ts.map +1 -1
- package/dist/services/stream.js +6 -5
- package/dist/services/stream.js.map +1 -1
- package/package.json +2 -1
- package/src/services/_util.ts +10 -1
- package/src/services/index.ts +0 -1
- package/src/services/session.ts +2 -1
- package/src/services/stream.ts +10 -8
- package/dist/services/objectstore.d.ts +0 -257
- package/dist/services/objectstore.d.ts.map +0 -1
- package/dist/services/objectstore.js +0 -422
- package/dist/services/objectstore.js.map +0 -1
- package/src/__test__/error.test.ts +0 -431
- package/src/services/__test__/keyvalue.test.ts +0 -402
- package/src/services/__test__/mock-adapter.ts +0 -114
- package/src/services/__test__/objectstore.test.ts +0 -431
- package/src/services/__test__/stream.test.ts +0 -554
- package/src/services/__test__/vector.test.ts +0 -819
- package/src/services/objectstore.ts +0 -816
|
@@ -1,816 +0,0 @@
|
|
|
1
|
-
import type { FetchAdapter, FetchRequest, Body } from './adapter';
|
|
2
|
-
import { buildUrl, toServiceException } from './_util';
|
|
3
|
-
import { StructuredError } from '../error';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Parameters for putting an object into the object store
|
|
7
|
-
*/
|
|
8
|
-
export interface ObjectStorePutParams {
|
|
9
|
-
/**
|
|
10
|
-
* the content type of the object
|
|
11
|
-
*/
|
|
12
|
-
contentType?: string;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* the content encoding of the object
|
|
16
|
-
*/
|
|
17
|
-
contentEncoding?: string;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* the cache control header for the object
|
|
21
|
-
*/
|
|
22
|
-
cacheControl?: string;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* the content disposition header for the object
|
|
26
|
-
*/
|
|
27
|
-
contentDisposition?: string;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* the content language header for the object
|
|
31
|
-
*/
|
|
32
|
-
contentLanguage?: string;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* arbitrary metadata to attach to the object but not returned as part of the object when fetched via HTTP
|
|
36
|
-
*/
|
|
37
|
-
metadata?: Record<string, string>;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Result when an object is found in the object store
|
|
42
|
-
*/
|
|
43
|
-
export interface ObjectResultFound {
|
|
44
|
-
/**
|
|
45
|
-
* the object data
|
|
46
|
-
*/
|
|
47
|
-
data: Uint8Array;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* the content type of the object
|
|
51
|
-
*/
|
|
52
|
-
contentType: string;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* the object was found
|
|
56
|
-
*/
|
|
57
|
-
exists: true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Result when an object is not found in the object store
|
|
62
|
-
*/
|
|
63
|
-
export interface ObjectResultNotFound {
|
|
64
|
-
data: never;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* the object was not found
|
|
68
|
-
*/
|
|
69
|
-
exists: false;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* The result of an object store get operation
|
|
74
|
-
*/
|
|
75
|
-
export type ObjectResult = ObjectResultFound | ObjectResultNotFound;
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Parameters for creating a public URL
|
|
79
|
-
*/
|
|
80
|
-
export interface CreatePublicURLParams {
|
|
81
|
-
/**
|
|
82
|
-
* the duration of the signed URL in milliseconds. If not provided, the default is 1 hour.
|
|
83
|
-
*/
|
|
84
|
-
expiresDuration?: number;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
interface ObjectStoreCreatePublicURLSuccessResponse {
|
|
88
|
-
success: true;
|
|
89
|
-
url: string;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
interface ObjectStoreCreatePublicURLErrorResponse {
|
|
93
|
-
success: false;
|
|
94
|
-
message: string;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
type ObjectStoreCreatePublicURLResponse =
|
|
98
|
-
| ObjectStoreCreatePublicURLSuccessResponse
|
|
99
|
-
| ObjectStoreCreatePublicURLErrorResponse;
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Information about an object in the object store
|
|
103
|
-
*/
|
|
104
|
-
export interface ObjectInfo {
|
|
105
|
-
key: string;
|
|
106
|
-
size: number;
|
|
107
|
-
etag: string;
|
|
108
|
-
created_at: string;
|
|
109
|
-
updated_at: string;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Information about a bucket in the object store
|
|
114
|
-
*/
|
|
115
|
-
export interface BucketInfo {
|
|
116
|
-
name: string;
|
|
117
|
-
object_count: number;
|
|
118
|
-
total_bytes: number;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Object store service for storing and retrieving binary data
|
|
123
|
-
*/
|
|
124
|
-
export interface ObjectStorage {
|
|
125
|
-
/**
|
|
126
|
-
* Get an object from the object store
|
|
127
|
-
*
|
|
128
|
-
* @param bucket - the bucket to get the object from
|
|
129
|
-
* @param key - the key of the object to get
|
|
130
|
-
* @returns a Promise that resolves to the object result
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
* ```typescript
|
|
134
|
-
* const result = await objectStore.get('my-bucket', 'my-key');
|
|
135
|
-
* if (result.exists) {
|
|
136
|
-
* console.log('Content type:', result.contentType);
|
|
137
|
-
* console.log('Data:', result.data);
|
|
138
|
-
* }
|
|
139
|
-
* ```
|
|
140
|
-
*/
|
|
141
|
-
get(bucket: string, key: string): Promise<ObjectResult>;
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Put an object into the object store
|
|
145
|
-
*
|
|
146
|
-
* @param bucket - the bucket to put the object into
|
|
147
|
-
* @param key - the key of the object to put
|
|
148
|
-
* @param data - the data to put (Uint8Array, ArrayBuffer, or ReadableStream)
|
|
149
|
-
* @param params - optional parameters for the put operation
|
|
150
|
-
*
|
|
151
|
-
* @example
|
|
152
|
-
* ```typescript
|
|
153
|
-
* const data = new TextEncoder().encode('Hello, world!');
|
|
154
|
-
* await objectStore.put('my-bucket', 'greeting.txt', data, {
|
|
155
|
-
* contentType: 'text/plain',
|
|
156
|
-
* metadata: { author: 'user123' }
|
|
157
|
-
* });
|
|
158
|
-
* ```
|
|
159
|
-
*/
|
|
160
|
-
put(
|
|
161
|
-
bucket: string,
|
|
162
|
-
key: string,
|
|
163
|
-
data: Uint8Array | ArrayBuffer | ReadableStream,
|
|
164
|
-
params?: ObjectStorePutParams
|
|
165
|
-
): Promise<void>;
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Delete an object from the object store
|
|
169
|
-
*
|
|
170
|
-
* @param bucket - the bucket to delete the object from
|
|
171
|
-
* @param key - the key of the object to delete
|
|
172
|
-
* @returns true if the object was deleted, false if the object did not exist
|
|
173
|
-
*
|
|
174
|
-
* @example
|
|
175
|
-
* ```typescript
|
|
176
|
-
* const deleted = await objectStore.delete('my-bucket', 'my-key');
|
|
177
|
-
* if (deleted) {
|
|
178
|
-
* console.log('Object was deleted');
|
|
179
|
-
* } else {
|
|
180
|
-
* console.log('Object did not exist');
|
|
181
|
-
* }
|
|
182
|
-
* ```
|
|
183
|
-
*/
|
|
184
|
-
delete(bucket: string, key: string): Promise<boolean>;
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Create a public URL for an object. This URL can be used to access the object without authentication.
|
|
188
|
-
*
|
|
189
|
-
* @param bucket - the bucket to create the signed URL for
|
|
190
|
-
* @param key - the key of the object to create the signed URL for
|
|
191
|
-
* @param params - optional parameters including expiration duration
|
|
192
|
-
* @returns the public URL
|
|
193
|
-
*
|
|
194
|
-
* @example
|
|
195
|
-
* ```typescript
|
|
196
|
-
* const url = await objectStore.createPublicURL('my-bucket', 'my-key', {
|
|
197
|
-
* expiresDuration: 3600000 // 1 hour in milliseconds
|
|
198
|
-
* });
|
|
199
|
-
* console.log('Public URL:', url);
|
|
200
|
-
* ```
|
|
201
|
-
*/
|
|
202
|
-
createPublicURL(bucket: string, key: string, params?: CreatePublicURLParams): Promise<string>;
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* List all buckets in the object store
|
|
206
|
-
*
|
|
207
|
-
* @returns array of bucket information
|
|
208
|
-
*
|
|
209
|
-
* @example
|
|
210
|
-
* ```typescript
|
|
211
|
-
* const buckets = await objectStore.listBuckets();
|
|
212
|
-
* for (const bucket of buckets) {
|
|
213
|
-
* console.log(`${bucket.name}: ${bucket.object_count} objects, ${bucket.total_bytes} bytes`);
|
|
214
|
-
* }
|
|
215
|
-
* ```
|
|
216
|
-
*/
|
|
217
|
-
listBuckets(): Promise<BucketInfo[]>;
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* List all keys in a bucket
|
|
221
|
-
*
|
|
222
|
-
* @param bucket - the bucket to list keys from
|
|
223
|
-
* @returns array of object information
|
|
224
|
-
*
|
|
225
|
-
* @example
|
|
226
|
-
* ```typescript
|
|
227
|
-
* const objects = await objectStore.listKeys('my-bucket');
|
|
228
|
-
* for (const obj of objects) {
|
|
229
|
-
* console.log(`${obj.key}: ${obj.size} bytes`);
|
|
230
|
-
* }
|
|
231
|
-
* ```
|
|
232
|
-
*/
|
|
233
|
-
listKeys(bucket: string): Promise<ObjectInfo[]>;
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* List objects in a bucket with optional filtering
|
|
237
|
-
*
|
|
238
|
-
* @param bucket - the bucket to list objects from
|
|
239
|
-
* @param options - optional filtering (prefix, limit)
|
|
240
|
-
* @returns array of object information
|
|
241
|
-
*
|
|
242
|
-
* @example
|
|
243
|
-
* ```typescript
|
|
244
|
-
* const objects = await objectStore.listObjects('my-bucket', { prefix: 'docs/', limit: 100 });
|
|
245
|
-
* for (const obj of objects) {
|
|
246
|
-
* console.log(`${obj.key}: ${obj.size} bytes`);
|
|
247
|
-
* }
|
|
248
|
-
* ```
|
|
249
|
-
*/
|
|
250
|
-
listObjects(
|
|
251
|
-
bucket: string,
|
|
252
|
-
options?: { prefix?: string; limit?: number }
|
|
253
|
-
): Promise<ObjectInfo[]>;
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Get object metadata without retrieving the data
|
|
257
|
-
*
|
|
258
|
-
* @param bucket - the bucket containing the object
|
|
259
|
-
* @param key - the key of the object
|
|
260
|
-
* @returns object metadata (size, contentType, etc.)
|
|
261
|
-
*
|
|
262
|
-
* @example
|
|
263
|
-
* ```typescript
|
|
264
|
-
* const metadata = await objectStore.headObject('my-bucket', 'my-key');
|
|
265
|
-
* console.log(`Size: ${metadata.size}, Type: ${metadata.contentType}`);
|
|
266
|
-
* ```
|
|
267
|
-
*/
|
|
268
|
-
headObject(bucket: string, key: string): Promise<ObjectInfo>;
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Delete a bucket and all its contents
|
|
272
|
-
*
|
|
273
|
-
* @param bucket - the bucket to delete
|
|
274
|
-
* @returns true if the bucket was deleted
|
|
275
|
-
*
|
|
276
|
-
* @example
|
|
277
|
-
* ```typescript
|
|
278
|
-
* await objectStore.deleteBucket('my-bucket');
|
|
279
|
-
* ```
|
|
280
|
-
*/
|
|
281
|
-
deleteBucket(bucket: string): Promise<boolean>;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
const ObjectStoreBucketMissingError = StructuredError(
|
|
285
|
-
'ObjectStoreBucketMissingError',
|
|
286
|
-
'bucket is required and cannot be empty'
|
|
287
|
-
);
|
|
288
|
-
|
|
289
|
-
const ObjectStoreKeyMissingError = StructuredError(
|
|
290
|
-
'ObjectStoreKeyMissingError',
|
|
291
|
-
'key is required and cannot be empty'
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
const ObjectStoreDataMissingError = StructuredError(
|
|
295
|
-
'ObjectStoreDataMissingError',
|
|
296
|
-
'data is required'
|
|
297
|
-
);
|
|
298
|
-
|
|
299
|
-
const ObjectStoreResponseError = StructuredError('ObjectStoreResponseError')<{ status: number }>();
|
|
300
|
-
const ObjectStoreResponseInvalidError = StructuredError('ObjectStoreResponseInvalidError');
|
|
301
|
-
|
|
302
|
-
const ObjectStoreNotFoundError = StructuredError('ObjectStoreNotFoundError', 'object not found');
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Implementation of the ObjectStorage interface
|
|
306
|
-
*/
|
|
307
|
-
export class ObjectStorageService implements ObjectStorage {
|
|
308
|
-
#adapter: FetchAdapter;
|
|
309
|
-
#baseUrl: string;
|
|
310
|
-
|
|
311
|
-
constructor(baseUrl: string, adapter: FetchAdapter) {
|
|
312
|
-
this.#baseUrl = baseUrl;
|
|
313
|
-
this.#adapter = adapter;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
async get(bucket: string, key: string): Promise<ObjectResult> {
|
|
317
|
-
if (!bucket?.trim()) {
|
|
318
|
-
throw new ObjectStoreBucketMissingError();
|
|
319
|
-
}
|
|
320
|
-
if (!key?.trim()) {
|
|
321
|
-
throw new ObjectStoreKeyMissingError();
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const url = buildUrl(
|
|
325
|
-
this.#baseUrl,
|
|
326
|
-
`/object/2025-03-17/${encodeURIComponent(bucket)}/${encodeURIComponent(key)}`
|
|
327
|
-
);
|
|
328
|
-
|
|
329
|
-
const signal = AbortSignal.timeout(10_000);
|
|
330
|
-
const options: FetchRequest = {
|
|
331
|
-
method: 'GET',
|
|
332
|
-
signal,
|
|
333
|
-
telemetry: {
|
|
334
|
-
name: 'agentuity.objectstore.get',
|
|
335
|
-
attributes: {
|
|
336
|
-
'objectstore.bucket': bucket,
|
|
337
|
-
'objectstore.key': key,
|
|
338
|
-
},
|
|
339
|
-
},
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
try {
|
|
343
|
-
const result = await this.#adapter.invoke<ArrayBuffer>(url, options);
|
|
344
|
-
|
|
345
|
-
if (result.response.status === 404) {
|
|
346
|
-
return { exists: false } as ObjectResultNotFound;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
if (!result.ok) {
|
|
350
|
-
throw new ObjectStoreResponseError({
|
|
351
|
-
status: result.response.status,
|
|
352
|
-
message: `Failed to get object: ${result.response.statusText} (${result.response.status})`,
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
const data = result.data;
|
|
357
|
-
if (!(data instanceof ArrayBuffer)) {
|
|
358
|
-
throw new ObjectStoreResponseInvalidError({
|
|
359
|
-
message: 'Expected ArrayBuffer response from object store',
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const contentType =
|
|
364
|
-
result.response.headers.get('content-type') || 'application/octet-stream';
|
|
365
|
-
|
|
366
|
-
return {
|
|
367
|
-
exists: true,
|
|
368
|
-
data: new Uint8Array(data),
|
|
369
|
-
contentType,
|
|
370
|
-
} as ObjectResultFound;
|
|
371
|
-
} catch (err) {
|
|
372
|
-
if (err instanceof Response) {
|
|
373
|
-
throw await toServiceException('GET', url, err);
|
|
374
|
-
}
|
|
375
|
-
throw err;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
async put(
|
|
380
|
-
bucket: string,
|
|
381
|
-
key: string,
|
|
382
|
-
data: Uint8Array | ArrayBuffer | ReadableStream,
|
|
383
|
-
params?: ObjectStorePutParams
|
|
384
|
-
): Promise<void> {
|
|
385
|
-
if (!bucket?.trim()) {
|
|
386
|
-
throw new ObjectStoreBucketMissingError();
|
|
387
|
-
}
|
|
388
|
-
if (!key?.trim()) {
|
|
389
|
-
throw new ObjectStoreKeyMissingError();
|
|
390
|
-
}
|
|
391
|
-
if (!data) {
|
|
392
|
-
throw new ObjectStoreDataMissingError();
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
const url = buildUrl(
|
|
396
|
-
this.#baseUrl,
|
|
397
|
-
`/object/2025-03-17/${encodeURIComponent(bucket)}/${encodeURIComponent(key)}`
|
|
398
|
-
);
|
|
399
|
-
|
|
400
|
-
const headers: Record<string, string> = {
|
|
401
|
-
'Content-Type': params?.contentType || 'application/octet-stream',
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
if (params?.contentEncoding) {
|
|
405
|
-
headers['Content-Encoding'] = params.contentEncoding;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
if (params?.cacheControl) {
|
|
409
|
-
headers['Cache-Control'] = params.cacheControl;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
if (params?.contentDisposition) {
|
|
413
|
-
headers['Content-Disposition'] = params.contentDisposition;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (params?.contentLanguage) {
|
|
417
|
-
headers['Content-Language'] = params.contentLanguage;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
if (params?.metadata) {
|
|
421
|
-
for (const [metaKey, metaValue] of Object.entries(params.metadata)) {
|
|
422
|
-
headers[`x-metadata-${metaKey}`] = metaValue;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
let body: Body;
|
|
427
|
-
if (data instanceof ArrayBuffer) {
|
|
428
|
-
body = data;
|
|
429
|
-
} else if (data instanceof Uint8Array) {
|
|
430
|
-
if (data.byteOffset !== 0 || data.byteLength !== data.buffer.byteLength) {
|
|
431
|
-
body = data.buffer.slice(
|
|
432
|
-
data.byteOffset,
|
|
433
|
-
data.byteOffset + data.byteLength
|
|
434
|
-
) as ArrayBuffer;
|
|
435
|
-
} else {
|
|
436
|
-
body = data.buffer as ArrayBuffer;
|
|
437
|
-
}
|
|
438
|
-
} else {
|
|
439
|
-
body = data;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
const signal = AbortSignal.timeout(30_000);
|
|
443
|
-
const options: FetchRequest = {
|
|
444
|
-
method: 'PUT',
|
|
445
|
-
headers,
|
|
446
|
-
body,
|
|
447
|
-
signal,
|
|
448
|
-
telemetry: {
|
|
449
|
-
name: 'agentuity.objectstore.put',
|
|
450
|
-
attributes: {
|
|
451
|
-
'objectstore.bucket': bucket,
|
|
452
|
-
'objectstore.key': key,
|
|
453
|
-
'objectstore.contentType': params?.contentType || 'application/octet-stream',
|
|
454
|
-
},
|
|
455
|
-
},
|
|
456
|
-
};
|
|
457
|
-
|
|
458
|
-
try {
|
|
459
|
-
const result = await this.#adapter.invoke(url, options);
|
|
460
|
-
|
|
461
|
-
if (!result.ok || (result.response.status !== 200 && result.response.status !== 201)) {
|
|
462
|
-
throw new ObjectStoreResponseError({
|
|
463
|
-
status: result.response.status,
|
|
464
|
-
message: `Failed to put object: ${result.response.statusText} (${result.response.status})`,
|
|
465
|
-
});
|
|
466
|
-
}
|
|
467
|
-
} catch (err) {
|
|
468
|
-
if (err instanceof Response) {
|
|
469
|
-
throw await toServiceException('PUT', url, err);
|
|
470
|
-
}
|
|
471
|
-
throw err;
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
async delete(bucket: string, key: string): Promise<boolean> {
|
|
476
|
-
if (!bucket?.trim()) {
|
|
477
|
-
throw new ObjectStoreBucketMissingError();
|
|
478
|
-
}
|
|
479
|
-
if (!key?.trim()) {
|
|
480
|
-
throw new ObjectStoreKeyMissingError();
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
const url = buildUrl(
|
|
484
|
-
this.#baseUrl,
|
|
485
|
-
`/object/2025-03-17/${encodeURIComponent(bucket)}/${encodeURIComponent(key)}`
|
|
486
|
-
);
|
|
487
|
-
|
|
488
|
-
const signal = AbortSignal.timeout(10_000);
|
|
489
|
-
const options: FetchRequest = {
|
|
490
|
-
method: 'DELETE',
|
|
491
|
-
signal,
|
|
492
|
-
telemetry: {
|
|
493
|
-
name: 'agentuity.objectstore.delete',
|
|
494
|
-
attributes: {
|
|
495
|
-
'objectstore.bucket': bucket,
|
|
496
|
-
'objectstore.key': key,
|
|
497
|
-
},
|
|
498
|
-
},
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
try {
|
|
502
|
-
const result = await this.#adapter.invoke(url, options);
|
|
503
|
-
|
|
504
|
-
if (result.response.status === 404) {
|
|
505
|
-
return false;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
if (result.response.status === 200) {
|
|
509
|
-
return true;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
throw new ObjectStoreResponseError({
|
|
513
|
-
status: result.response.status,
|
|
514
|
-
message: `Failed to delete object: ${result.response.statusText} (${result.response.status})`,
|
|
515
|
-
});
|
|
516
|
-
} catch (err) {
|
|
517
|
-
if (err instanceof Response) {
|
|
518
|
-
throw await toServiceException('DELETE', url, err);
|
|
519
|
-
}
|
|
520
|
-
throw err;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
async createPublicURL(
|
|
525
|
-
bucket: string,
|
|
526
|
-
key: string,
|
|
527
|
-
params?: CreatePublicURLParams
|
|
528
|
-
): Promise<string> {
|
|
529
|
-
if (!bucket?.trim()) {
|
|
530
|
-
throw new ObjectStoreBucketMissingError();
|
|
531
|
-
}
|
|
532
|
-
if (!key?.trim()) {
|
|
533
|
-
throw new ObjectStoreKeyMissingError();
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
const url = buildUrl(
|
|
537
|
-
this.#baseUrl,
|
|
538
|
-
`/object/2025-03-17/presigned/${encodeURIComponent(bucket)}/${encodeURIComponent(key)}`
|
|
539
|
-
);
|
|
540
|
-
|
|
541
|
-
const requestBody: { expires?: number } = {};
|
|
542
|
-
if (params?.expiresDuration) {
|
|
543
|
-
requestBody.expires = params.expiresDuration;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
const signal = AbortSignal.timeout(10_000);
|
|
547
|
-
const options: FetchRequest = {
|
|
548
|
-
method: 'POST',
|
|
549
|
-
contentType: 'application/json',
|
|
550
|
-
body: JSON.stringify(requestBody),
|
|
551
|
-
signal,
|
|
552
|
-
telemetry: {
|
|
553
|
-
name: 'agentuity.objectstore.createPublicURL',
|
|
554
|
-
attributes: {
|
|
555
|
-
'objectstore.bucket': bucket,
|
|
556
|
-
'objectstore.key': key,
|
|
557
|
-
'objectstore.expiresDuration': params?.expiresDuration?.toString() || '',
|
|
558
|
-
},
|
|
559
|
-
},
|
|
560
|
-
};
|
|
561
|
-
|
|
562
|
-
try {
|
|
563
|
-
const result = await this.#adapter.invoke<ObjectStoreCreatePublicURLResponse>(
|
|
564
|
-
url,
|
|
565
|
-
options
|
|
566
|
-
);
|
|
567
|
-
|
|
568
|
-
if (!result.ok) {
|
|
569
|
-
throw new ObjectStoreResponseError({
|
|
570
|
-
status: result.response.status,
|
|
571
|
-
message: `Failed to create public URL: ${result.response.statusText} (${result.response.status})`,
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
const data = result.data;
|
|
576
|
-
|
|
577
|
-
if (!data.success) {
|
|
578
|
-
throw new ObjectStoreResponseError({
|
|
579
|
-
status: result.response.status,
|
|
580
|
-
message: data.message || 'Failed to create public URL',
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
return data.url;
|
|
585
|
-
} catch (err) {
|
|
586
|
-
if (err instanceof Error && err.message.includes('Object not found')) {
|
|
587
|
-
throw err;
|
|
588
|
-
}
|
|
589
|
-
if (err instanceof Response) {
|
|
590
|
-
throw await toServiceException('POST', url, err);
|
|
591
|
-
}
|
|
592
|
-
throw err;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
async listBuckets(): Promise<BucketInfo[]> {
|
|
597
|
-
const url = buildUrl(this.#baseUrl, '/object/2025-03-17/buckets');
|
|
598
|
-
|
|
599
|
-
const signal = AbortSignal.timeout(10_000);
|
|
600
|
-
const options: FetchRequest = {
|
|
601
|
-
method: 'GET',
|
|
602
|
-
signal,
|
|
603
|
-
telemetry: {
|
|
604
|
-
name: 'agentuity.objectstore.listBuckets',
|
|
605
|
-
attributes: {},
|
|
606
|
-
},
|
|
607
|
-
};
|
|
608
|
-
|
|
609
|
-
try {
|
|
610
|
-
const result = await this.#adapter.invoke<{ buckets: BucketInfo[] }>(url, options);
|
|
611
|
-
|
|
612
|
-
if (!result.ok) {
|
|
613
|
-
throw new ObjectStoreResponseError({
|
|
614
|
-
status: result.response.status,
|
|
615
|
-
message: `Failed to list buckets: ${result.response.statusText} (${result.response.status})`,
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
return result.data.buckets;
|
|
620
|
-
} catch (err) {
|
|
621
|
-
if (err instanceof Response) {
|
|
622
|
-
throw await toServiceException('GET', url, err);
|
|
623
|
-
}
|
|
624
|
-
throw err;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
async listKeys(bucket: string): Promise<ObjectInfo[]> {
|
|
629
|
-
if (!bucket?.trim()) {
|
|
630
|
-
throw new ObjectStoreBucketMissingError();
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
const url = buildUrl(this.#baseUrl, `/object/2025-03-17/keys/${encodeURIComponent(bucket)}`);
|
|
634
|
-
|
|
635
|
-
const signal = AbortSignal.timeout(10_000);
|
|
636
|
-
const options: FetchRequest = {
|
|
637
|
-
method: 'GET',
|
|
638
|
-
signal,
|
|
639
|
-
telemetry: {
|
|
640
|
-
name: 'agentuity.objectstore.listKeys',
|
|
641
|
-
attributes: {
|
|
642
|
-
'objectstore.bucket': bucket,
|
|
643
|
-
},
|
|
644
|
-
},
|
|
645
|
-
};
|
|
646
|
-
|
|
647
|
-
try {
|
|
648
|
-
const result = await this.#adapter.invoke<{ bucket: string; objects: ObjectInfo[] }>(
|
|
649
|
-
url,
|
|
650
|
-
options
|
|
651
|
-
);
|
|
652
|
-
|
|
653
|
-
if (!result.ok) {
|
|
654
|
-
throw new ObjectStoreResponseError({
|
|
655
|
-
status: result.response.status,
|
|
656
|
-
message: `Failed to list keys: ${result.response.statusText} (${result.response.status})`,
|
|
657
|
-
});
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
return result.data.objects;
|
|
661
|
-
} catch (err) {
|
|
662
|
-
if (err instanceof Response) {
|
|
663
|
-
throw await toServiceException('GET', url, err);
|
|
664
|
-
}
|
|
665
|
-
throw err;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
async listObjects(
|
|
670
|
-
bucket: string,
|
|
671
|
-
options?: { prefix?: string; limit?: number }
|
|
672
|
-
): Promise<ObjectInfo[]> {
|
|
673
|
-
if (!bucket?.trim()) {
|
|
674
|
-
throw new ObjectStoreBucketMissingError();
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
const params = new URLSearchParams();
|
|
678
|
-
if (options?.prefix) {
|
|
679
|
-
params.set('prefix', options.prefix);
|
|
680
|
-
}
|
|
681
|
-
if (options?.limit) {
|
|
682
|
-
params.set('limit', options.limit.toString());
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
const queryString = params.toString();
|
|
686
|
-
const url = buildUrl(
|
|
687
|
-
this.#baseUrl,
|
|
688
|
-
`/object/2025-03-17/objects/${encodeURIComponent(bucket)}${queryString ? `?${queryString}` : ''}`
|
|
689
|
-
);
|
|
690
|
-
|
|
691
|
-
const signal = AbortSignal.timeout(10_000);
|
|
692
|
-
const fetchOptions: FetchRequest = {
|
|
693
|
-
method: 'GET',
|
|
694
|
-
signal,
|
|
695
|
-
telemetry: {
|
|
696
|
-
name: 'agentuity.objectstore.listObjects',
|
|
697
|
-
attributes: {
|
|
698
|
-
'objectstore.bucket': bucket,
|
|
699
|
-
'objectstore.prefix': options?.prefix || '',
|
|
700
|
-
'objectstore.limit': (options?.limit || 1000).toString(),
|
|
701
|
-
},
|
|
702
|
-
},
|
|
703
|
-
};
|
|
704
|
-
|
|
705
|
-
try {
|
|
706
|
-
const result = await this.#adapter.invoke<{ bucket: string; objects: ObjectInfo[] }>(
|
|
707
|
-
url,
|
|
708
|
-
fetchOptions
|
|
709
|
-
);
|
|
710
|
-
|
|
711
|
-
if (!result.ok) {
|
|
712
|
-
throw new ObjectStoreResponseError({
|
|
713
|
-
status: result.response.status,
|
|
714
|
-
message: `Failed to list objects: ${result.response.statusText} (${result.response.status})`,
|
|
715
|
-
});
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
return result.data.objects;
|
|
719
|
-
} catch (err) {
|
|
720
|
-
if (err instanceof Response) {
|
|
721
|
-
throw await toServiceException('GET', url, err);
|
|
722
|
-
}
|
|
723
|
-
throw err;
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
async headObject(bucket: string, key: string): Promise<ObjectInfo> {
|
|
728
|
-
if (!bucket?.trim()) {
|
|
729
|
-
throw new ObjectStoreBucketMissingError();
|
|
730
|
-
}
|
|
731
|
-
if (!key?.trim()) {
|
|
732
|
-
throw new ObjectStoreKeyMissingError();
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
const url = buildUrl(
|
|
736
|
-
this.#baseUrl,
|
|
737
|
-
`/object/2025-03-17/head/${encodeURIComponent(bucket)}/${encodeURIComponent(key)}`
|
|
738
|
-
);
|
|
739
|
-
|
|
740
|
-
const signal = AbortSignal.timeout(10_000);
|
|
741
|
-
const fetchOptions: FetchRequest = {
|
|
742
|
-
method: 'GET',
|
|
743
|
-
signal,
|
|
744
|
-
telemetry: {
|
|
745
|
-
name: 'agentuity.objectstore.headObject',
|
|
746
|
-
attributes: {
|
|
747
|
-
'objectstore.bucket': bucket,
|
|
748
|
-
'objectstore.key': key,
|
|
749
|
-
},
|
|
750
|
-
},
|
|
751
|
-
};
|
|
752
|
-
|
|
753
|
-
try {
|
|
754
|
-
const result = await this.#adapter.invoke<ObjectInfo>(url, fetchOptions);
|
|
755
|
-
|
|
756
|
-
if (!result.ok) {
|
|
757
|
-
if (result.response.status === 404) {
|
|
758
|
-
throw new ObjectStoreNotFoundError();
|
|
759
|
-
}
|
|
760
|
-
throw new ObjectStoreResponseError({
|
|
761
|
-
status: result.response.status,
|
|
762
|
-
message: `Failed to get object metadata: ${result.response.statusText} (${result.response.status})`,
|
|
763
|
-
});
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
return result.data;
|
|
767
|
-
} catch (err) {
|
|
768
|
-
if (err instanceof Response) {
|
|
769
|
-
throw await toServiceException('GET', url, err);
|
|
770
|
-
}
|
|
771
|
-
throw err;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
async deleteBucket(bucket: string): Promise<boolean> {
|
|
776
|
-
if (!bucket?.trim()) {
|
|
777
|
-
throw new ObjectStoreBucketMissingError();
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
const url = buildUrl(this.#baseUrl, `/object/2025-03-17/${encodeURIComponent(bucket)}`);
|
|
781
|
-
|
|
782
|
-
const signal = AbortSignal.timeout(30_000);
|
|
783
|
-
const options: FetchRequest = {
|
|
784
|
-
method: 'DELETE',
|
|
785
|
-
signal,
|
|
786
|
-
telemetry: {
|
|
787
|
-
name: 'agentuity.objectstore.deleteBucket',
|
|
788
|
-
attributes: {
|
|
789
|
-
'objectstore.bucket': bucket,
|
|
790
|
-
},
|
|
791
|
-
},
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
try {
|
|
795
|
-
const result = await this.#adapter.invoke(url, options);
|
|
796
|
-
|
|
797
|
-
if (result.response.status === 404) {
|
|
798
|
-
return false;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
if (result.response.status === 200) {
|
|
802
|
-
return true;
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
throw new ObjectStoreResponseError({
|
|
806
|
-
status: result.response.status,
|
|
807
|
-
message: `Failed to delete bucket: ${result.response.statusText} (${result.response.status})`,
|
|
808
|
-
});
|
|
809
|
-
} catch (err) {
|
|
810
|
-
if (err instanceof Response) {
|
|
811
|
-
throw await toServiceException('DELETE', url, err);
|
|
812
|
-
}
|
|
813
|
-
throw err;
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
}
|