metainsight-context-engine 0.0.1

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.
@@ -0,0 +1,583 @@
1
+ /**
2
+ * COS Operations — Unified CRUD Operations Layer
3
+ *
4
+ * Provides all data operations (upload / search / download / delete) for the
5
+ * Cloud Context Engine. Built on top of the bootstrap layer (`cos-bootstrap.ts`)
6
+ * and routes requests to the correct dataset / COS prefix based on `category`.
7
+ *
8
+ * Architecture:
9
+ * cos-bootstrap.ts → cos-operations.ts → engine.ts / index.ts
10
+ * (init + low-level) (CRUD operations) (business logic)
11
+ *
12
+ * The constructor accepts a `BootstrapOutcome`, so consumers only need to call
13
+ * `bootstrap()` once and pass the result here — no duplicate initialization.
14
+ *
15
+ * Multimodal retrieval:
16
+ * - Text/memory queries route to DocSearch datasets (category="memory")
17
+ * - Image queries route to ImageSearch datasets (category="image")
18
+ * - The search template is automatically selected per-dataset based on
19
+ * the dataset's `templateId` (Official:ImageSearch → "ImageSearch").
20
+ *
21
+ * Key improvements over the old `cloud-client.ts`:
22
+ * - Upload path uses the dataset's `cosPrefix` (not hardcoded `uploads/`)
23
+ * - Search routes to the correct dataset name based on category
24
+ * - Automatic template selection for multimodal (DocSearch / ImageSearch)
25
+ * - Download support (getObject from COS)
26
+ * - Delete support (deleteObject from COS)
27
+ */
28
+ import { sendCIRequest } from './cos-bootstrap.js';
29
+ // ============================================================================
30
+ // Helpers — docId sanitization
31
+ // ============================================================================
32
+ /**
33
+ * Sanitize a docId so that it is safe to use as a COS object-key segment.
34
+ *
35
+ * COS (S3-compatible) interprets `/` as a directory separator, so names like
36
+ * `IMAP/SMTP Email Tool` would be split across folders.
37
+ *
38
+ * Strategy:
39
+ * 1. Prefixed docIds (containing `:`) are split at the **first** colon.
40
+ * Everything after the colon is the "name" part — ALL `/` in the name
41
+ * are replaced with `__`. The prefix itself never contains `/` so it
42
+ * is kept as-is.
43
+ *
44
+ * 2. For non-prefixed docIds, the **first** `/` is assumed to be an
45
+ * intentional directory boundary (e.g. `memory/2026-03-15`).
46
+ * Only the portion after the first `/` has its `/` replaced.
47
+ * If there is no `/` at all, the string is returned unchanged
48
+ * (nothing to sanitize).
49
+ *
50
+ * Note: DocIds should avoid `/` characters. Use `__` as a substitute
51
+ * when `/` appears in names. The `unsanitizeDocId()` function reverses
52
+ * this transformation when parsing COS URIs from search results.
53
+ *
54
+ * Examples:
55
+ * "IMAP__SMTP Email Tool" → "IMAP__SMTP Email Tool" (pre-sanitized)
56
+ * "memory/2026-03-15" → "memory/2026-03-15" (dir preserved)
57
+ * "memory/IMAP/SMTP Tool" → "memory/IMAP__SMTP Tool" (dir preserved, name sanitized)
58
+ */
59
+ function sanitizeDocId(docId) {
60
+ // Prefixed docIds (e.g. "category:name")
61
+ // The colon separates a category tag from the human-readable name.
62
+ // ALL slashes after the colon belong to the name and must be escaped.
63
+ const colonIdx = docId.indexOf(':');
64
+ if (colonIdx !== -1) {
65
+ const prefix = docId.slice(0, colonIdx + 1);
66
+ const namePart = docId.slice(colonIdx + 1).replace(/\//g, '__');
67
+ return `${prefix}${namePart}`;
68
+ }
69
+ // Non-prefixed: preserve the FIRST `/` as a directory boundary,
70
+ // but replace any further `/` in the filename segment.
71
+ const firstSlash = docId.indexOf('/');
72
+ if (firstSlash === -1) {
73
+ // No slash at all — nothing to sanitize
74
+ return docId;
75
+ }
76
+ const dirPart = docId.slice(0, firstSlash);
77
+ const namePart = docId.slice(firstSlash + 1).replace(/\//g, '__');
78
+ return `${dirPart}/${namePart}`;
79
+ }
80
+ /**
81
+ * Reverse `sanitizeDocId` — restores the original docId from a COS key
82
+ * segment. Used when parsing COS URIs returned by CI search.
83
+ */
84
+ function unsanitizeDocId(sanitized) {
85
+ return sanitized.replace(/__/g, '/');
86
+ }
87
+ // ============================================================================
88
+ // CosOperations — Unified CRUD
89
+ // ============================================================================
90
+ export class CosOperations {
91
+ cos;
92
+ config;
93
+ /** Search template — DocSearch or ImageSearch. Default: DocSearch. */
94
+ template;
95
+ /** Default match threshold (0-100). CI recommends 80, we default to 60. */
96
+ matchThreshold;
97
+ /**
98
+ * Create a CosOperations instance from a successful bootstrap outcome.
99
+ *
100
+ * @throws if the bootstrap outcome indicates failure
101
+ */
102
+ constructor(outcome, opts) {
103
+ if (!outcome.success) {
104
+ throw new Error(`CosOperations: cannot initialize from failed bootstrap: ${outcome.error}`);
105
+ }
106
+ this.cos = outcome.cos;
107
+ this.config = outcome.config;
108
+ this.template = opts?.template ?? 'DocSearch';
109
+ this.matchThreshold = opts?.matchThreshold ?? 60;
110
+ }
111
+ // ==========================================================================
112
+ // Dataset routing
113
+ // ==========================================================================
114
+ /**
115
+ * Resolve the dataset definition for a given category.
116
+ *
117
+ * Routing rules:
118
+ * 1. If a dataset's `cosPrefix` starts with `{category}/`, use it.
119
+ * (legacy layout: cosPrefix="memory/" matches category="memory")
120
+ * 2. If a dataset's `cosPrefix` contains `/{category}/`, use it.
121
+ * (multi-agent layout: cosPrefix="openclaw-xxx/workspace/memory/" matches category="memory")
122
+ * 3. If a dataset's `name` contains the category, use it.
123
+ * 4. Otherwise, fall back to the first dataset in config.
124
+ */
125
+ resolveDataset(category) {
126
+ if (!category || this.config.datasets.length === 1) {
127
+ return this.config.datasets[0];
128
+ }
129
+ const lowerCat = category.toLowerCase();
130
+ // Priority 1: cosPrefix starts with category (legacy: cosPrefix="memory/")
131
+ const byPrefix = this.config.datasets.find((ds) => ds.cosPrefix.toLowerCase().startsWith(`${lowerCat}/`));
132
+ if (byPrefix) {
133
+ return byPrefix;
134
+ }
135
+ // Priority 2: cosPrefix contains category as a path segment
136
+ // (multi-agent: cosPrefix="openclaw-xxx/workspace/memory/")
137
+ const byContains = this.config.datasets.find((ds) => ds.cosPrefix.toLowerCase().includes(`/${lowerCat}/`));
138
+ if (byContains) {
139
+ return byContains;
140
+ }
141
+ // Priority 3: name contains category (e.g. category="memory" → name="openclaw-memory-xxx")
142
+ const byName = this.config.datasets.find((ds) => ds.name.toLowerCase().includes(lowerCat));
143
+ if (byName) {
144
+ return byName;
145
+ }
146
+ // Fallback: first dataset
147
+ return this.config.datasets[0];
148
+ }
149
+ // ==========================================================================
150
+ // Search — CI hybridsearch API
151
+ // ==========================================================================
152
+ /**
153
+ * Semantic / hybrid search against the CI dataset.
154
+ *
155
+ * Routing:
156
+ * - Image datasets (Official:ImageSearch) → `POST /datasetquery/imagesearch`
157
+ * with only `DatasetName` + `Mode: "text"` (simplified temporary API).
158
+ * - All other datasets → `POST /datasetquery/hybridsearch` with full params.
159
+ *
160
+ * DocSearch: SearchText is truncated to 60 UTF-8 chars (CI API limit).
161
+ */
162
+ async search(query, opts) {
163
+ const { maxResults = 10, minScore, category } = opts ?? {};
164
+ const dataset = this.resolveDataset(category);
165
+ const isImageDataset = dataset.templateId.includes('ImageSearch');
166
+ // ── Image dataset → simplified imagesearch endpoint ──
167
+ if (isImageDataset) {
168
+ const body = {
169
+ DatasetName: dataset.name,
170
+ Mode: 'text',
171
+ Text: query || '-',
172
+ Limit: 10,
173
+ MatchThreshold: 60,
174
+ };
175
+ const result = await sendCIRequest(this.cos, this.config.bucket, this.config.region, 'POST', 'datasetquery/imagesearch', body);
176
+ const res = result;
177
+ const response = res.Response;
178
+ const imageResult = (response?.ImageResult ?? res.ImageResult);
179
+ return this.mapImageResults(imageResult, category);
180
+ }
181
+ // ── Doc dataset → hybridsearch endpoint (full params) ──
182
+ // CI API: SearchText max 60 UTF-8 characters
183
+ const searchText = query.length > 60 ? query.slice(0, 60) : query;
184
+ // Convert 0-1 minScore to 0-100 MatchThreshold, floor to configured minimum
185
+ const threshold = minScore !== undefined
186
+ ? Math.max(Math.floor(minScore * 100), this.matchThreshold)
187
+ : this.matchThreshold;
188
+ const body = {
189
+ DatasetName: dataset.name,
190
+ Mode: 'text',
191
+ Templates: this.template,
192
+ SearchText: searchText,
193
+ Limit: 30,
194
+ MatchThreshold: threshold,
195
+ Offset: 0,
196
+ };
197
+ const result = await sendCIRequest(this.cos, this.config.bucket, this.config.region, 'POST', 'datasetquery/hybridsearch', body);
198
+ const res = result;
199
+ const response = res.Response;
200
+ const docResult = (response?.DocResult ?? res.DocResult);
201
+ return this.mapDocResults(docResult, category);
202
+ }
203
+ // ==========================================================================
204
+ // Upload — COS putObject (content stored as Markdown for CI indexing)
205
+ // ==========================================================================
206
+ /**
207
+ * Upload content to the COS bucket for CI indexing.
208
+ *
209
+ * Content is stored as a Markdown file under `{cosPrefix}{docId}.md`.
210
+ * CI will pick it up via the dataset binding and index it automatically.
211
+ * Metadata is stored in COS custom headers (`x-cos-meta-*`).
212
+ *
213
+ * The upload path is derived from the dataset's `cosPrefix` — not hardcoded.
214
+ * Category routing is handled by `resolveDataset()` which selects the
215
+ * correct dataset (and thus the correct cosPrefix). We do NOT append
216
+ * `{category}/` again — that would create nested directories like
217
+ * `memory/memory/`.
218
+ */
219
+ async upload(content, opts) {
220
+ const category = opts?.category ?? 'general';
221
+ const docId = opts?.docId ?? `${category}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
222
+ const dataset = this.resolveDataset(category);
223
+ // Sanitize docId: replace `/` with `__` so COS doesn't treat it as a
224
+ // directory boundary. e.g. "memory:IMAP/SMTP Email Tool"
225
+ // → "memory:IMAP__SMTP Email Tool"
226
+ const safeDocId = sanitizeDocId(docId);
227
+ // Route to the correct COS path via dataset cosPrefix.
228
+ // cosPrefix already encodes the category boundary (e.g. "memory/"),
229
+ // so we only append the docId — no extra `{category}/` layer.
230
+ //
231
+ // When `customKey` is provided, it overrides the default key construction.
232
+ // This is used for files that should live outside the dataset's cosPrefix,
233
+ // e.g. workspace identity files at `openclaw-{agentId}/agents.md`.
234
+ const key = opts?.customKey ?? `${dataset.cosPrefix}${safeDocId}.md`;
235
+ // Build COS custom headers for metadata (x-cos-meta-* headers).
236
+ // Values must be strings; non-string values are JSON-serialized.
237
+ const headers = {
238
+ 'x-cos-meta-category': category,
239
+ 'x-cos-meta-created-at': new Date().toISOString(),
240
+ };
241
+ const metadata = opts?.metadata ?? {};
242
+ for (const [k, v] of Object.entries(metadata)) {
243
+ const headerKey = `x-cos-meta-${k.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`;
244
+ headers[headerKey] = typeof v === 'string' ? v : JSON.stringify(v);
245
+ }
246
+ return new Promise((resolve, reject) => {
247
+ this.cos.putObject({
248
+ Bucket: this.config.bucket,
249
+ Region: this.config.region,
250
+ Key: key,
251
+ Body: content,
252
+ Headers: headers,
253
+ }, (err) => {
254
+ if (err) {
255
+ const detail = err instanceof Error
256
+ ? err.message
257
+ : (typeof err === 'object' && err !== null
258
+ ? JSON.stringify(err, null, 2)
259
+ : String(err));
260
+ reject(new Error(`COS upload failed: ${detail}`));
261
+ return;
262
+ }
263
+ resolve({ docId, key, status: 'uploaded' });
264
+ });
265
+ });
266
+ }
267
+ /**
268
+ * Batch upload multiple items in parallel (with concurrency limit).
269
+ *
270
+ * Individual upload failures are captured per-item (status='error')
271
+ * instead of aborting the entire batch — this prevents one bad item
272
+ * from causing all remaining items to be dropped.
273
+ */
274
+ async uploadBatch(items, concurrency = 5) {
275
+ const results = [];
276
+ const queue = [...items];
277
+ const worker = async () => {
278
+ while (queue.length > 0) {
279
+ const item = queue.shift();
280
+ if (!item) {
281
+ break;
282
+ }
283
+ try {
284
+ const result = await this.upload(item.content, item.opts);
285
+ results.push(result);
286
+ }
287
+ catch (err) {
288
+ // Record the failure but continue processing remaining items
289
+ results.push({
290
+ docId: item.opts?.docId ?? 'unknown',
291
+ key: '',
292
+ status: 'error',
293
+ error: err instanceof Error ? err.message : String(err),
294
+ });
295
+ }
296
+ }
297
+ };
298
+ const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
299
+ await Promise.all(workers);
300
+ return results;
301
+ }
302
+ // ==========================================================================
303
+ // Upload Binary — COS putObject for images and binary files
304
+ // ==========================================================================
305
+ /**
306
+ * Upload a binary file (e.g. image) to the COS bucket.
307
+ *
308
+ * Unlike `upload()` which stores text content as Markdown, this method
309
+ * accepts a Buffer and stores the file with its original content type.
310
+ * The file is placed under the provided COS key path.
311
+ *
312
+ * @param buffer Raw file content as a Buffer.
313
+ * @param key Full COS key (e.g. "openclaw-main/asset/photo.png").
314
+ * @param contentType MIME type (e.g. "image/png"). Default: "application/octet-stream".
315
+ * @param metadata Optional metadata to attach as COS custom headers.
316
+ * @returns Upload result with the COS key.
317
+ */
318
+ async uploadBinary(buffer, key, contentType = 'application/octet-stream', metadata) {
319
+ const headers = {
320
+ 'Content-Type': contentType,
321
+ 'x-cos-meta-category': 'image',
322
+ 'x-cos-meta-created-at': new Date().toISOString(),
323
+ };
324
+ if (metadata) {
325
+ for (const [k, v] of Object.entries(metadata)) {
326
+ const headerKey = `x-cos-meta-${k.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`;
327
+ headers[headerKey] = typeof v === 'string' ? v : JSON.stringify(v);
328
+ }
329
+ }
330
+ return new Promise((resolve, reject) => {
331
+ this.cos.putObject({
332
+ Bucket: this.config.bucket,
333
+ Region: this.config.region,
334
+ Key: key,
335
+ Body: buffer,
336
+ Headers: headers,
337
+ }, (err) => {
338
+ if (err) {
339
+ const detail = err instanceof Error
340
+ ? err.message
341
+ : (typeof err === 'object' && err !== null
342
+ ? JSON.stringify(err, null, 2)
343
+ : String(err));
344
+ reject(new Error(`COS binary upload failed for "${key}": ${detail}`));
345
+ return;
346
+ }
347
+ resolve({ docId: key, key, status: 'uploaded' });
348
+ });
349
+ });
350
+ }
351
+ /**
352
+ * Check whether a COS object exists at the given key.
353
+ *
354
+ * Uses `headObject` which returns metadata without downloading the body.
355
+ * Returns true if the object exists, false otherwise.
356
+ */
357
+ async objectExists(key) {
358
+ return new Promise((resolve) => {
359
+ this.cos.headObject({
360
+ Bucket: this.config.bucket,
361
+ Region: this.config.region,
362
+ Key: key,
363
+ }, (err) => {
364
+ if (err) {
365
+ resolve(false);
366
+ return;
367
+ }
368
+ resolve(true);
369
+ });
370
+ });
371
+ }
372
+ // ==========================================================================
373
+ // Download — COS getObject
374
+ // ==========================================================================
375
+ /**
376
+ * Download a document from the COS bucket by its key.
377
+ *
378
+ * @param docKey Full COS key (e.g. "memory/memory/abc.md") or a short docId.
379
+ * If a short docId is provided, it will be resolved via the dataset cosPrefix.
380
+ */
381
+ async download(docKey, opts) {
382
+ const dataset = this.resolveDataset(opts?.category);
383
+ // Determine if docKey is a full COS key or a short docId.
384
+ // A full key starts with one of the known dataset cosPrefixes.
385
+ // Short docIds are resolved via `{cosPrefix}{sanitizedDocId}.md`.
386
+ // We do NOT use `includes('/')` because docIds can contain `/`
387
+ // (e.g. "category:IMAP/SMTP Email Tool").
388
+ const isFullKey = this.config.datasets.some((ds) => docKey.startsWith(ds.cosPrefix));
389
+ const key = isFullKey
390
+ ? docKey
391
+ : `${dataset.cosPrefix}${sanitizeDocId(docKey)}.md`;
392
+ return new Promise((resolve, reject) => {
393
+ this.cos.getObject({
394
+ Bucket: this.config.bucket,
395
+ Region: this.config.region,
396
+ Key: key,
397
+ }, (err, data) => {
398
+ if (err) {
399
+ reject(new Error(`COS download failed for "${key}": ${String(err)}`));
400
+ return;
401
+ }
402
+ const raw = data;
403
+ const body = typeof raw.Body === 'string'
404
+ ? raw.Body
405
+ : raw.Body instanceof Buffer
406
+ ? raw.Body.toString('utf-8')
407
+ : String(raw.Body ?? '');
408
+ // Extract metadata from COS custom headers (x-cos-meta-*)
409
+ const headers = (raw.headers ?? {});
410
+ const metadata = {};
411
+ for (const [hk, hv] of Object.entries(headers)) {
412
+ if (hk.startsWith('x-cos-meta-')) {
413
+ const metaKey = hk.slice('x-cos-meta-'.length);
414
+ metadata[metaKey] = hv;
415
+ }
416
+ }
417
+ // Backward compatibility: try to parse as old JSON wrapper format
418
+ try {
419
+ const parsed = JSON.parse(body);
420
+ if (typeof parsed.content === 'string') {
421
+ resolve({
422
+ content: parsed.content,
423
+ key,
424
+ metadata: (parsed.metadata ?? metadata),
425
+ });
426
+ return;
427
+ }
428
+ }
429
+ catch {
430
+ // Not JSON — this is the expected path for .md files
431
+ }
432
+ resolve({ content: body, key, metadata });
433
+ });
434
+ });
435
+ }
436
+ // ==========================================================================
437
+ // Delete — COS deleteObject
438
+ // ==========================================================================
439
+ /**
440
+ * Delete a document from the COS bucket.
441
+ *
442
+ * @param docKey Full COS key or short docId (resolved via dataset cosPrefix).
443
+ */
444
+ async deleteDoc(docKey, opts) {
445
+ const dataset = this.resolveDataset(opts?.category);
446
+ // Same logic as download: detect full key by cosPrefix, not by `/`.
447
+ const isFullKey = this.config.datasets.some((ds) => docKey.startsWith(ds.cosPrefix));
448
+ const key = isFullKey
449
+ ? docKey
450
+ : `${dataset.cosPrefix}${sanitizeDocId(docKey)}.md`;
451
+ return new Promise((resolve, reject) => {
452
+ this.cos.deleteObject({
453
+ Bucket: this.config.bucket,
454
+ Region: this.config.region,
455
+ Key: key,
456
+ }, (err) => {
457
+ if (err) {
458
+ reject(new Error(`COS delete failed for "${key}": ${String(err)}`));
459
+ return;
460
+ }
461
+ resolve({ deleted: true, key });
462
+ });
463
+ });
464
+ }
465
+ // ==========================================================================
466
+ // Accessors
467
+ // ==========================================================================
468
+ /** Get the resolved COS config (useful for diagnostics). */
469
+ getConfig() {
470
+ return this.config;
471
+ }
472
+ /** Get all available dataset names. */
473
+ getDatasetNames() {
474
+ return this.config.datasets.map((ds) => ds.name);
475
+ }
476
+ /**
477
+ * Get the agent-level COS key prefix (without trailing "/workspace/").
478
+ *
479
+ * For multi-agent setups (agentId set), this returns `openclaw-{agentId}/`.
480
+ * For legacy setups (no agentId), this returns an empty string.
481
+ *
482
+ * Useful for placing files alongside the workspace directory rather than
483
+ * inside it. E.g. workspace files like AGENTS.md should go to
484
+ * `openclaw-{agentId}/agents.md` (agent root) instead of
485
+ * `openclaw-{agentId}/workspace/agents.md` (inside workspace).
486
+ */
487
+ getAgentPrefix() {
488
+ if (this.config.agentId) {
489
+ return `openclaw-${this.config.agentId}/`;
490
+ }
491
+ return '';
492
+ }
493
+ // ==========================================================================
494
+ // Signed URL — generate a temporary access URL for a COS object
495
+ // ==========================================================================
496
+ /**
497
+ * Generate a signed (temporary) download URL for a COS object.
498
+ *
499
+ * @param cosUri Full COS URI (e.g. `cos://bucket-123/image/photo.jpg`)
500
+ * or a plain COS key (e.g. `image/photo.jpg`).
501
+ * @param expiresInSeconds URL validity duration. Default: 3600 (1 hour).
502
+ * @returns A signed HTTPS URL that can be used to access the object.
503
+ */
504
+ getSignedUrl(cosUri, expiresInSeconds = 3600) {
505
+ // Extract the COS key from a `cos://bucket/key` URI
506
+ const key = cosUri.startsWith('cos://')
507
+ ? cosUri.replace(/^cos:\/\/[^/]+\//, '')
508
+ : cosUri;
509
+ return this.cos.getObjectUrl({
510
+ Bucket: this.config.bucket,
511
+ Region: this.config.region,
512
+ Key: key,
513
+ Sign: true,
514
+ Expires: expiresInSeconds,
515
+ });
516
+ }
517
+ // ==========================================================================
518
+ // Private: result mapping helpers
519
+ // ==========================================================================
520
+ /**
521
+ * Map CI DocSearch results to CloudSearchResult[].
522
+ */
523
+ mapDocResults(items, category) {
524
+ if (!items || items.length === 0) {
525
+ return [];
526
+ }
527
+ return items.map((item) => ({
528
+ snippet: item.Text ?? '',
529
+ score: (item.Score ?? 0) / 100, // Normalize 0-100 → 0-1
530
+ docId: item.URI ? this.cosUriToDocId(item.URI) : undefined,
531
+ category: category ?? 'document',
532
+ metadata: {
533
+ uri: item.URI,
534
+ textPage: item.TextPage,
535
+ imageUrls: item.ImageUrls,
536
+ },
537
+ }));
538
+ }
539
+ /**
540
+ * Map CI ImageSearch results to CloudSearchResult[].
541
+ * Each result includes a signed URL for direct image access.
542
+ */
543
+ mapImageResults(items, category) {
544
+ if (!items || items.length === 0) {
545
+ return [];
546
+ }
547
+ return items.map((item) => {
548
+ const uri = item.URI ?? '';
549
+ const signedUrl = uri ? this.getSignedUrl(uri) : undefined;
550
+ return {
551
+ snippet: `[image] ${uri || 'unknown'}`,
552
+ score: (item.Score ?? 0) / 100, // Normalize 0-100 → 0-1
553
+ docId: uri ? this.cosUriToDocId(uri) : undefined,
554
+ category: category ?? 'document',
555
+ imageUrl: signedUrl,
556
+ metadata: {
557
+ uri,
558
+ },
559
+ };
560
+ });
561
+ }
562
+ /**
563
+ * Extract a short doc ID from a COS URI.
564
+ * e.g. `cos://bucket-123/memory/abc.md` → `abc.md`
565
+ * e.g. `cos://bucket-123/memory/IMAP__SMTP Email Tool.md`
566
+ * → `IMAP/SMTP Email Tool.md`
567
+ *
568
+ * Note: docIds stored on COS have `/` replaced with `__` (see `sanitizeDocId`).
569
+ * This method reverses that transformation so callers see the original name.
570
+ */
571
+ cosUriToDocId(uri) {
572
+ // Remove cos:// scheme and bucket name
573
+ const withoutScheme = uri.replace(/^cos:\/\/[^/]+\//, '');
574
+ // Remove known dataset prefixes
575
+ for (const ds of this.config.datasets) {
576
+ if (withoutScheme.startsWith(ds.cosPrefix)) {
577
+ return unsanitizeDocId(withoutScheme.slice(ds.cosPrefix.length));
578
+ }
579
+ }
580
+ return unsanitizeDocId(withoutScheme);
581
+ }
582
+ }
583
+ //# sourceMappingURL=cos-operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cos-operations.js","sourceRoot":"","sources":["../cos-operations.ts"],"names":[],"mappings":"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"}