memory-lancedb-pro 1.0.23 → 1.0.25
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/README.md +47 -0
- package/README_CN.md +47 -0
- package/index.ts +19 -5
- package/openclaw.plugin.json +19 -5
- package/package.json +1 -1
- package/src/embedder.ts +101 -11
package/README.md
CHANGED
|
@@ -710,6 +710,51 @@ On LanceDB 0.26+ (via Apache Arrow), some numeric columns may be returned as `Bi
|
|
|
710
710
|
|
|
711
711
|
upgrade to **memory-lancedb-pro >= 1.0.14**. This plugin now coerces these values using `Number(...)` before doing arithmetic (for example, when computing scores or sorting by timestamp).
|
|
712
712
|
|
|
713
|
+
## Iron Rules for AI Agents (铁律)
|
|
714
|
+
|
|
715
|
+
> **For OpenClaw users**: copy the code block below into your `AGENTS.md` so your agent enforces these rules automatically.
|
|
716
|
+
|
|
717
|
+
```markdown
|
|
718
|
+
## Rule 1 — 双层记忆存储(铁律)
|
|
719
|
+
|
|
720
|
+
Every pitfall/lesson learned → IMMEDIATELY store TWO memories to LanceDB before moving on:
|
|
721
|
+
|
|
722
|
+
- **Technical layer**: Pitfall: [symptom]. Cause: [root cause]. Fix: [solution]. Prevention: [how to avoid]
|
|
723
|
+
(category: fact, importance ≥ 0.8)
|
|
724
|
+
- **Principle layer**: Decision principle ([tag]): [behavioral rule]. Trigger: [when it applies]. Action: [what to do]
|
|
725
|
+
(category: decision, importance ≥ 0.85)
|
|
726
|
+
- After each store, immediately `memory_recall` with anchor keywords to verify retrieval.
|
|
727
|
+
If not found, rewrite and re-store.
|
|
728
|
+
- Missing either layer = incomplete.
|
|
729
|
+
Do NOT proceed to next topic until both are stored and verified.
|
|
730
|
+
- Also update relevant SKILL.md files to prevent recurrence.
|
|
731
|
+
|
|
732
|
+
## Rule 2 — LanceDB 卫生
|
|
733
|
+
|
|
734
|
+
Entries must be short and atomic (< 500 chars). Never store raw conversation summaries, large blobs, or duplicates.
|
|
735
|
+
Prefer structured format with keywords for retrieval.
|
|
736
|
+
|
|
737
|
+
## Rule 3 — Recall before retry
|
|
738
|
+
|
|
739
|
+
On ANY tool failure, repeated error, or unexpected behavior, ALWAYS `memory_recall` with relevant keywords
|
|
740
|
+
(error message, tool name, symptom) BEFORE retrying. LanceDB likely already has the fix.
|
|
741
|
+
Blind retries waste time and repeat known mistakes.
|
|
742
|
+
|
|
743
|
+
## Rule 4 — 编辑前确认目标代码库
|
|
744
|
+
|
|
745
|
+
When working on memory plugins, confirm you are editing the intended package
|
|
746
|
+
(e.g., `memory-lancedb-pro` vs built-in `memory-lancedb`) before making changes;
|
|
747
|
+
use `memory_recall` + filesystem search to avoid patching the wrong repo.
|
|
748
|
+
|
|
749
|
+
## Rule 5 — 插件代码变更必须清 jiti 缓存(MANDATORY)
|
|
750
|
+
|
|
751
|
+
After modifying ANY `.ts` file under `plugins/`, MUST run `rm -rf /tmp/jiti/` BEFORE `openclaw gateway restart`.
|
|
752
|
+
jiti caches compiled TS; restart alone loads STALE code. This has caused silent bugs multiple times.
|
|
753
|
+
Config-only changes do NOT need cache clearing.
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
|
|
713
758
|
## Dependencies
|
|
714
759
|
|
|
715
760
|
| Package | Purpose |
|
|
@@ -733,12 +778,14 @@ Top contributors (from GitHub’s contributors list, sorted by commit contributi
|
|
|
733
778
|
<a href="https://github.com/furedericca-lab"><img src="https://avatars.githubusercontent.com/u/263020793?v=4" width="48" height="48" alt="@furedericca-lab" /></a>
|
|
734
779
|
<a href="https://github.com/joe2643"><img src="https://avatars.githubusercontent.com/u/19421931?v=4" width="48" height="48" alt="@joe2643" /></a>
|
|
735
780
|
<a href="https://github.com/AliceLJY"><img src="https://avatars.githubusercontent.com/u/136287420?v=4" width="48" height="48" alt="@AliceLJY" /></a>
|
|
781
|
+
<a href="https://github.com/chenjiyong"><img src="https://avatars.githubusercontent.com/u/8199522?v=4" width="48" height="48" alt="@chenjiyong" /></a>
|
|
736
782
|
</p>
|
|
737
783
|
|
|
738
784
|
- [@win4r](https://github.com/win4r) (3 commits)
|
|
739
785
|
- [@kctony](https://github.com/kctony) (2 commits)
|
|
740
786
|
- [@Akatsuki-Ryu](https://github.com/Akatsuki-Ryu) (1 commit)
|
|
741
787
|
- [@AliceLJY](https://github.com/AliceLJY) (1 commit)
|
|
788
|
+
- [@chenjiyong](https://github.com/chenjiyong) (1 commit)
|
|
742
789
|
- [@JasonSuz](https://github.com/JasonSuz) (1 commit)
|
|
743
790
|
- [@Minidoracat](https://github.com/Minidoracat) (1 commit)
|
|
744
791
|
- [@furedericca-lab](https://github.com/furedericca-lab) (1 commit)
|
package/README_CN.md
CHANGED
|
@@ -584,6 +584,51 @@ LanceDB 表 `memories`:
|
|
|
584
584
|
|
|
585
585
|
请升级到 **memory-lancedb-pro >= 1.0.14**。插件已对这些字段统一做 `Number(...)` 转换后再参与运算(例如:计算分数、按时间排序)。
|
|
586
586
|
|
|
587
|
+
## AI Agent 铁律(Iron Rules)
|
|
588
|
+
|
|
589
|
+
> **OpenClaw 用户**:将下方代码块复制到你的 `AGENTS.md` 中,让 Agent 自动遵守这些规则。
|
|
590
|
+
|
|
591
|
+
```markdown
|
|
592
|
+
## Rule 1 — 双层记忆存储(铁律)
|
|
593
|
+
|
|
594
|
+
Every pitfall/lesson learned → IMMEDIATELY store TWO memories to LanceDB before moving on:
|
|
595
|
+
|
|
596
|
+
- **Technical layer**: Pitfall: [symptom]. Cause: [root cause]. Fix: [solution]. Prevention: [how to avoid]
|
|
597
|
+
(category: fact, importance ≥ 0.8)
|
|
598
|
+
- **Principle layer**: Decision principle ([tag]): [behavioral rule]. Trigger: [when it applies]. Action: [what to do]
|
|
599
|
+
(category: decision, importance ≥ 0.85)
|
|
600
|
+
- After each store, immediately `memory_recall` with anchor keywords to verify retrieval.
|
|
601
|
+
If not found, rewrite and re-store.
|
|
602
|
+
- Missing either layer = incomplete.
|
|
603
|
+
Do NOT proceed to next topic until both are stored and verified.
|
|
604
|
+
- Also update relevant SKILL.md files to prevent recurrence.
|
|
605
|
+
|
|
606
|
+
## Rule 2 — LanceDB 卫生
|
|
607
|
+
|
|
608
|
+
Entries must be short and atomic (< 500 chars). Never store raw conversation summaries, large blobs, or duplicates.
|
|
609
|
+
Prefer structured format with keywords for retrieval.
|
|
610
|
+
|
|
611
|
+
## Rule 3 — Recall before retry
|
|
612
|
+
|
|
613
|
+
On ANY tool failure, repeated error, or unexpected behavior, ALWAYS `memory_recall` with relevant keywords
|
|
614
|
+
(error message, tool name, symptom) BEFORE retrying. LanceDB likely already has the fix.
|
|
615
|
+
Blind retries waste time and repeat known mistakes.
|
|
616
|
+
|
|
617
|
+
## Rule 4 — 编辑前确认目标代码库
|
|
618
|
+
|
|
619
|
+
When working on memory plugins, confirm you are editing the intended package
|
|
620
|
+
(e.g., `memory-lancedb-pro` vs built-in `memory-lancedb`) before making changes;
|
|
621
|
+
use `memory_recall` + filesystem search to avoid patching the wrong repo.
|
|
622
|
+
|
|
623
|
+
## Rule 5 — 插件代码变更必须清 jiti 缓存(MANDATORY)
|
|
624
|
+
|
|
625
|
+
After modifying ANY `.ts` file under `plugins/`, MUST run `rm -rf /tmp/jiti/` BEFORE `openclaw gateway restart`.
|
|
626
|
+
jiti caches compiled TS; restart alone loads STALE code. This has caused silent bugs multiple times.
|
|
627
|
+
Config-only changes do NOT need cache clearing.
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
587
632
|
## 依赖
|
|
588
633
|
|
|
589
634
|
| 包 | 用途 |
|
|
@@ -607,12 +652,14 @@ LanceDB 表 `memories`:
|
|
|
607
652
|
<a href="https://github.com/furedericca-lab"><img src="https://avatars.githubusercontent.com/u/263020793?v=4" width="48" height="48" alt="@furedericca-lab" /></a>
|
|
608
653
|
<a href="https://github.com/joe2643"><img src="https://avatars.githubusercontent.com/u/19421931?v=4" width="48" height="48" alt="@joe2643" /></a>
|
|
609
654
|
<a href="https://github.com/AliceLJY"><img src="https://avatars.githubusercontent.com/u/136287420?v=4" width="48" height="48" alt="@AliceLJY" /></a>
|
|
655
|
+
<a href="https://github.com/chenjiyong"><img src="https://avatars.githubusercontent.com/u/8199522?v=4" width="48" height="48" alt="@chenjiyong" /></a>
|
|
610
656
|
</p>
|
|
611
657
|
|
|
612
658
|
- [@win4r](https://github.com/win4r)(3 次提交)
|
|
613
659
|
- [@kctony](https://github.com/kctony)(2 次提交)
|
|
614
660
|
- [@Akatsuki-Ryu](https://github.com/Akatsuki-Ryu)(1 次提交)
|
|
615
661
|
- [@AliceLJY](https://github.com/AliceLJY)(1 次提交)
|
|
662
|
+
- [@chenjiyong](https://github.com/chenjiyong)(1 次提交)
|
|
616
663
|
- [@JasonSuz](https://github.com/JasonSuz)(1 次提交)
|
|
617
664
|
- [@Minidoracat](https://github.com/Minidoracat)(1 次提交)
|
|
618
665
|
- [@furedericca-lab](https://github.com/furedericca-lab)(1 次提交)
|
package/index.ts
CHANGED
|
@@ -336,7 +336,7 @@ const memoryLanceDBProPlugin = {
|
|
|
336
336
|
const store = new MemoryStore({ dbPath: resolvedDbPath, vectorDim });
|
|
337
337
|
const embedder = createEmbedder({
|
|
338
338
|
provider: "openai-compatible",
|
|
339
|
-
apiKey:
|
|
339
|
+
apiKey: config.embedding.apiKey,
|
|
340
340
|
model: config.embedding.model || "text-embedding-3-small",
|
|
341
341
|
baseURL: config.embedding.baseURL,
|
|
342
342
|
dimensions: config.embedding.dimensions,
|
|
@@ -742,11 +742,25 @@ function parsePluginConfig(value: unknown): PluginConfig {
|
|
|
742
742
|
throw new Error("embedding config is required");
|
|
743
743
|
}
|
|
744
744
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
745
|
+
// Accept single key (string) or array of keys for round-robin rotation
|
|
746
|
+
let apiKey: string | string[];
|
|
747
|
+
if (typeof embedding.apiKey === "string") {
|
|
748
|
+
apiKey = embedding.apiKey;
|
|
749
|
+
} else if (Array.isArray(embedding.apiKey) && embedding.apiKey.length > 0) {
|
|
750
|
+
// Validate every element is a non-empty string
|
|
751
|
+
const invalid = embedding.apiKey.findIndex((k: unknown) => typeof k !== "string" || (k as string).trim().length === 0);
|
|
752
|
+
if (invalid !== -1) {
|
|
753
|
+
throw new Error(`embedding.apiKey[${invalid}] is invalid: expected non-empty string`);
|
|
754
|
+
}
|
|
755
|
+
apiKey = embedding.apiKey as string[];
|
|
756
|
+
} else if (embedding.apiKey !== undefined) {
|
|
757
|
+
// apiKey is present but wrong type — throw, don't silently fall back
|
|
758
|
+
throw new Error("embedding.apiKey must be a string or non-empty array of strings");
|
|
759
|
+
} else {
|
|
760
|
+
apiKey = process.env.OPENAI_API_KEY || "";
|
|
761
|
+
}
|
|
748
762
|
|
|
749
|
-
if (!apiKey) {
|
|
763
|
+
if (!apiKey || (Array.isArray(apiKey) && apiKey.length === 0)) {
|
|
750
764
|
throw new Error("embedding.apiKey is required (set directly or via OPENAI_API_KEY env var)");
|
|
751
765
|
}
|
|
752
766
|
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "memory-lancedb-pro",
|
|
3
3
|
"name": "Memory (LanceDB Pro)",
|
|
4
4
|
"description": "Enhanced LanceDB-backed long-term memory with hybrid retrieval, multi-scope isolation, long-context chunking, and management CLI",
|
|
5
|
-
"version": "1.0.
|
|
5
|
+
"version": "1.0.24",
|
|
6
6
|
"kind": "memory",
|
|
7
7
|
"configSchema": {
|
|
8
8
|
"type": "object",
|
|
@@ -17,7 +17,21 @@
|
|
|
17
17
|
"const": "openai-compatible"
|
|
18
18
|
},
|
|
19
19
|
"apiKey": {
|
|
20
|
-
"
|
|
20
|
+
"oneOf": [
|
|
21
|
+
{
|
|
22
|
+
"type": "string",
|
|
23
|
+
"minLength": 1
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"type": "array",
|
|
27
|
+
"items": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"minLength": 1
|
|
30
|
+
},
|
|
31
|
+
"minItems": 1
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"description": "Single API key or array of keys for round-robin rotation"
|
|
21
35
|
},
|
|
22
36
|
"model": {
|
|
23
37
|
"type": "string"
|
|
@@ -243,10 +257,10 @@
|
|
|
243
257
|
},
|
|
244
258
|
"uiHints": {
|
|
245
259
|
"embedding.apiKey": {
|
|
246
|
-
"label": "API Key",
|
|
260
|
+
"label": "API Key(s)",
|
|
247
261
|
"sensitive": true,
|
|
248
|
-
"placeholder": "sk-proj-... or
|
|
249
|
-
"help": "API key for
|
|
262
|
+
"placeholder": "sk-proj-... or [\"key1\", \"key2\"] for rotation",
|
|
263
|
+
"help": "Single API key or array of keys for round-robin rotation with automatic failover on rate limits (or use ${OPENAI_API_KEY}; use a dummy value for keyless local endpoints)"
|
|
250
264
|
},
|
|
251
265
|
"embedding.model": {
|
|
252
266
|
"label": "Embedding Model",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memory-lancedb-pro",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.25",
|
|
4
4
|
"description": "OpenClaw enhanced LanceDB memory plugin with hybrid retrieval (Vector + BM25), cross-encoder rerank, multi-scope isolation, long-context chunking, and management CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
package/src/embedder.ts
CHANGED
|
@@ -85,7 +85,8 @@ class EmbeddingCache {
|
|
|
85
85
|
|
|
86
86
|
export interface EmbeddingConfig {
|
|
87
87
|
provider: "openai-compatible";
|
|
88
|
-
|
|
88
|
+
/** Single API key or array of keys for round-robin rotation with failover. */
|
|
89
|
+
apiKey: string | string[];
|
|
89
90
|
model: string;
|
|
90
91
|
baseURL?: string;
|
|
91
92
|
dimensions?: number;
|
|
@@ -151,7 +152,11 @@ export function getVectorDimensions(model: string, overrideDims?: number): numbe
|
|
|
151
152
|
// ============================================================================
|
|
152
153
|
|
|
153
154
|
export class Embedder {
|
|
154
|
-
|
|
155
|
+
/** Pool of OpenAI clients — one per API key for round-robin rotation. */
|
|
156
|
+
private clients: OpenAI[];
|
|
157
|
+
/** Round-robin index for client rotation. */
|
|
158
|
+
private _clientIndex: number = 0;
|
|
159
|
+
|
|
155
160
|
public readonly dimensions: number;
|
|
156
161
|
private readonly _cache: EmbeddingCache;
|
|
157
162
|
|
|
@@ -166,8 +171,9 @@ export class Embedder {
|
|
|
166
171
|
private readonly _autoChunk: boolean;
|
|
167
172
|
|
|
168
173
|
constructor(config: EmbeddingConfig & { chunking?: boolean }) {
|
|
169
|
-
//
|
|
170
|
-
const
|
|
174
|
+
// Normalize apiKey to array and resolve environment variables
|
|
175
|
+
const apiKeys = Array.isArray(config.apiKey) ? config.apiKey : [config.apiKey];
|
|
176
|
+
const resolvedKeys = apiKeys.map(k => resolveEnvVars(k));
|
|
171
177
|
|
|
172
178
|
this._model = config.model;
|
|
173
179
|
this._taskQuery = config.taskQuery;
|
|
@@ -177,15 +183,96 @@ export class Embedder {
|
|
|
177
183
|
// Enable auto-chunking by default for better handling of long documents
|
|
178
184
|
this._autoChunk = config.chunking !== false;
|
|
179
185
|
|
|
180
|
-
|
|
181
|
-
|
|
186
|
+
// Create a client pool — one OpenAI client per key
|
|
187
|
+
this.clients = resolvedKeys.map(key => new OpenAI({
|
|
188
|
+
apiKey: key,
|
|
182
189
|
...(config.baseURL ? { baseURL: config.baseURL } : {}),
|
|
183
|
-
});
|
|
190
|
+
}));
|
|
191
|
+
|
|
192
|
+
if (this.clients.length > 1) {
|
|
193
|
+
console.log(`[memory-lancedb-pro] Initialized ${this.clients.length} API keys for round-robin rotation`);
|
|
194
|
+
}
|
|
184
195
|
|
|
185
196
|
this.dimensions = getVectorDimensions(config.model, config.dimensions);
|
|
186
197
|
this._cache = new EmbeddingCache(256, 30); // 256 entries, 30 min TTL
|
|
187
198
|
}
|
|
188
199
|
|
|
200
|
+
// --------------------------------------------------------------------------
|
|
201
|
+
// Multi-key rotation helpers
|
|
202
|
+
// --------------------------------------------------------------------------
|
|
203
|
+
|
|
204
|
+
/** Return the next client in round-robin order. */
|
|
205
|
+
private nextClient(): OpenAI {
|
|
206
|
+
const client = this.clients[this._clientIndex % this.clients.length];
|
|
207
|
+
this._clientIndex = (this._clientIndex + 1) % this.clients.length;
|
|
208
|
+
return client;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Check whether an error is a rate-limit / quota-exceeded / overload error. */
|
|
212
|
+
private isRateLimitError(error: unknown): boolean {
|
|
213
|
+
if (!error || typeof error !== "object") return false;
|
|
214
|
+
|
|
215
|
+
const err = error as Record<string, any>;
|
|
216
|
+
|
|
217
|
+
// HTTP status: 429 (rate limit) or 503 (service overload)
|
|
218
|
+
if (err.status === 429 || err.status === 503) return true;
|
|
219
|
+
|
|
220
|
+
// OpenAI SDK structured error code
|
|
221
|
+
if (err.code === "rate_limit_exceeded" || err.code === "insufficient_quota") return true;
|
|
222
|
+
|
|
223
|
+
// Nested error object (some providers)
|
|
224
|
+
const nested = err.error;
|
|
225
|
+
if (nested && typeof nested === "object") {
|
|
226
|
+
if (nested.type === "rate_limit_exceeded" || nested.type === "insufficient_quota") return true;
|
|
227
|
+
if (nested.code === "rate_limit_exceeded" || nested.code === "insufficient_quota") return true;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Fallback: message text matching
|
|
231
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
232
|
+
return /rate.limit|quota|too many requests|insufficient.*credit|429|503.*overload/i.test(msg);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Call embeddings.create with automatic key rotation on rate-limit errors.
|
|
237
|
+
* Tries each key in the pool at most once before giving up.
|
|
238
|
+
*/
|
|
239
|
+
private async embedWithRetry(payload: any): Promise<any> {
|
|
240
|
+
const maxAttempts = this.clients.length;
|
|
241
|
+
let lastError: Error | undefined;
|
|
242
|
+
|
|
243
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
244
|
+
const client = this.nextClient();
|
|
245
|
+
try {
|
|
246
|
+
return await client.embeddings.create(payload);
|
|
247
|
+
} catch (error) {
|
|
248
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
249
|
+
|
|
250
|
+
if (this.isRateLimitError(error) && attempt < maxAttempts - 1) {
|
|
251
|
+
console.log(
|
|
252
|
+
`[memory-lancedb-pro] Attempt ${attempt + 1}/${maxAttempts} hit rate limit, rotating to next key...`
|
|
253
|
+
);
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Non-rate-limit error → don't retry, let caller handle (e.g. chunking)
|
|
258
|
+
if (!this.isRateLimitError(error)) {
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// All keys exhausted with rate-limit errors
|
|
265
|
+
throw new Error(
|
|
266
|
+
`All ${maxAttempts} API keys exhausted (rate limited). Last error: ${lastError?.message || "unknown"}`,
|
|
267
|
+
{ cause: lastError }
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** Number of API keys in the rotation pool. */
|
|
272
|
+
get keyCount(): number {
|
|
273
|
+
return this.clients.length;
|
|
274
|
+
}
|
|
275
|
+
|
|
189
276
|
// --------------------------------------------------------------------------
|
|
190
277
|
// Backward-compatible API
|
|
191
278
|
// --------------------------------------------------------------------------
|
|
@@ -271,7 +358,7 @@ export class Embedder {
|
|
|
271
358
|
if (cached) return cached;
|
|
272
359
|
|
|
273
360
|
try {
|
|
274
|
-
const response = await this.
|
|
361
|
+
const response = await this.embedWithRetry(this.buildPayload(text, task));
|
|
275
362
|
const embedding = response.data[0]?.embedding as number[] | undefined;
|
|
276
363
|
if (!embedding) {
|
|
277
364
|
throw new Error("No embedding returned from provider");
|
|
@@ -361,8 +448,8 @@ export class Embedder {
|
|
|
361
448
|
}
|
|
362
449
|
|
|
363
450
|
try {
|
|
364
|
-
const response = await this.
|
|
365
|
-
this.buildPayload(validTexts, task)
|
|
451
|
+
const response = await this.embedWithRetry(
|
|
452
|
+
this.buildPayload(validTexts, task)
|
|
366
453
|
);
|
|
367
454
|
|
|
368
455
|
// Create result array with proper length
|
|
@@ -479,7 +566,10 @@ export class Embedder {
|
|
|
479
566
|
}
|
|
480
567
|
|
|
481
568
|
get cacheStats() {
|
|
482
|
-
return
|
|
569
|
+
return {
|
|
570
|
+
...this._cache.stats,
|
|
571
|
+
keyCount: this.clients.length,
|
|
572
|
+
};
|
|
483
573
|
}
|
|
484
574
|
}
|
|
485
575
|
|