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.
- package/BOOTSTRAP.md +341 -0
- package/README.md +230 -0
- package/dist/cos-bootstrap.d.ts +221 -0
- package/dist/cos-bootstrap.d.ts.map +1 -0
- package/dist/cos-bootstrap.js +598 -0
- package/dist/cos-bootstrap.js.map +1 -0
- package/dist/cos-operations.d.ts +219 -0
- package/dist/cos-operations.d.ts.map +1 -0
- package/dist/cos-operations.js +583 -0
- package/dist/cos-operations.js.map +1 -0
- package/dist/engine.d.ts +101 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +157 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +993 -0
- package/dist/index.js.map +1 -0
- package/dist/local-memory-sync.d.ts +204 -0
- package/dist/local-memory-sync.d.ts.map +1 -0
- package/dist/local-memory-sync.js +1126 -0
- package/dist/local-memory-sync.js.map +1 -0
- package/openclaw.plugin.json +225 -0
- package/package.json +78 -0
|
@@ -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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"}
|