chore: Lint extensions folder.

This commit is contained in:
cpojer
2026-01-31 22:13:48 +09:00
parent 4f2166c503
commit 230ca789e2
221 changed files with 4006 additions and 1583 deletions

View File

@@ -1,4 +1,3 @@
import { Type } from "@sinclair/typebox";
import fs from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
@@ -24,7 +23,9 @@ function resolveDefaultDbPath(): string {
const home = homedir();
const preferred = join(home, ".openclaw", "memory", "lancedb");
try {
if (fs.existsSync(preferred)) return preferred;
if (fs.existsSync(preferred)) {
return preferred;
}
} catch {
// best-effort
}
@@ -32,7 +33,9 @@ function resolveDefaultDbPath(): string {
for (const legacy of LEGACY_STATE_DIRS) {
const candidate = join(home, legacy, "memory", "lancedb");
try {
if (fs.existsSync(candidate)) return candidate;
if (fs.existsSync(candidate)) {
return candidate;
}
} catch {
// best-effort
}
@@ -50,7 +53,9 @@ const EMBEDDING_DIMENSIONS: Record<string, number> = {
function assertAllowedKeys(value: Record<string, unknown>, allowed: string[], label: string) {
const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
if (unknown.length === 0) return;
if (unknown.length === 0) {
return;
}
throw new Error(`${label} has unknown keys: ${unknown.join(", ")}`);
}

View File

@@ -9,7 +9,6 @@
*/
import { describe, test, expect, beforeEach, afterEach } from "vitest";
import { randomUUID } from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import os from "node:os";
@@ -42,6 +41,7 @@ describe("memory plugin e2e", () => {
expect(memoryPlugin.name).toBe("Memory (LanceDB)");
expect(memoryPlugin.kind).toBe("memory");
expect(memoryPlugin.configSchema).toBeDefined();
// oxlint-disable-next-line typescript/unbound-method
expect(memoryPlugin.register).toBeInstanceOf(Function);
});
@@ -217,14 +217,16 @@ describeLive("memory plugin live tests", () => {
registeredServices.push(service);
},
on: (hookName: string, handler: any) => {
if (!registeredHooks[hookName]) registeredHooks[hookName] = [];
if (!registeredHooks[hookName]) {
registeredHooks[hookName] = [];
}
registeredHooks[hookName].push(handler);
},
resolvePath: (p: string) => p,
};
// Register plugin
await memoryPlugin.register(mockApi as any);
memoryPlugin.register(mockApi as any);
// Check registration
expect(registeredTools.length).toBe(3);

View File

@@ -55,8 +55,12 @@ class MemoryDB {
) {}
private async ensureInitialized(): Promise<void> {
if (this.table) return;
if (this.initPromise) return this.initPromise;
if (this.table) {
return;
}
if (this.initPromise) {
return this.initPromise;
}
this.initPromise = this.doInitialize();
return this.initPromise;
@@ -73,7 +77,7 @@ class MemoryDB {
{
id: "__schema__",
text: "",
vector: new Array(this.vectorDim).fill(0),
vector: Array.from({ length: this.vectorDim }).fill(0),
importance: 0,
category: "other",
createdAt: 0,
@@ -179,25 +183,43 @@ const MEMORY_TRIGGERS = [
];
function shouldCapture(text: string): boolean {
if (text.length < 10 || text.length > 500) return false;
if (text.length < 10 || text.length > 500) {
return false;
}
// Skip injected context from memory recall
if (text.includes("<relevant-memories>")) return false;
if (text.includes("<relevant-memories>")) {
return false;
}
// Skip system-generated content
if (text.startsWith("<") && text.includes("</")) return false;
if (text.startsWith("<") && text.includes("</")) {
return false;
}
// Skip agent summary responses (contain markdown formatting)
if (text.includes("**") && text.includes("\n-")) return false;
if (text.includes("**") && text.includes("\n-")) {
return false;
}
// Skip emoji-heavy responses (likely agent output)
const emojiCount = (text.match(/[\u{1F300}-\u{1F9FF}]/gu) || []).length;
if (emojiCount > 3) return false;
if (emojiCount > 3) {
return false;
}
return MEMORY_TRIGGERS.some((r) => r.test(text));
}
function detectCategory(text: string): MemoryCategory {
const lower = text.toLowerCase();
if (/prefer|radši|like|love|hate|want/i.test(lower)) return "preference";
if (/rozhodli|decided|will use|budeme/i.test(lower)) return "decision";
if (/\+\d{10,}|@[\w.-]+\.\w+|is called|jmenuje se/i.test(lower)) return "entity";
if (/is|are|has|have|je|má|jsou/i.test(lower)) return "fact";
if (/prefer|radši|like|love|hate|want/i.test(lower)) {
return "preference";
}
if (/rozhodli|decided|will use|budeme/i.test(lower)) {
return "decision";
}
if (/\+\d{10,}|@[\w.-]+\.\w+|is called|jmenuje se/i.test(lower)) {
return "entity";
}
if (/is|are|has|have|je|má|jsou/i.test(lower)) {
return "fact";
}
return "other";
}
@@ -455,13 +477,17 @@ const memoryPlugin = {
// Auto-recall: inject relevant memories before agent starts
if (cfg.autoRecall) {
api.on("before_agent_start", async (event) => {
if (!event.prompt || event.prompt.length < 5) return;
if (!event.prompt || event.prompt.length < 5) {
return;
}
try {
const vector = await embeddings.embed(event.prompt);
const results = await db.search(vector, 3, 0.3);
if (results.length === 0) return;
if (results.length === 0) {
return;
}
const memoryContext = results
.map((r) => `- [${r.entry.category}] ${r.entry.text}`)
@@ -490,12 +516,16 @@ const memoryPlugin = {
const texts: string[] = [];
for (const msg of event.messages) {
// Type guard for message object
if (!msg || typeof msg !== "object") continue;
if (!msg || typeof msg !== "object") {
continue;
}
const msgObj = msg as Record<string, unknown>;
// Only process user and assistant messages
const role = msgObj.role;
if (role !== "user" && role !== "assistant") continue;
if (role !== "user" && role !== "assistant") {
continue;
}
const content = msgObj.content;
@@ -524,7 +554,9 @@ const memoryPlugin = {
// Filter for capturable content
const toCapture = texts.filter((text) => text && shouldCapture(text));
if (toCapture.length === 0) return;
if (toCapture.length === 0) {
return;
}
// Store each capturable piece (limit to 3 per conversation)
let stored = 0;
@@ -534,7 +566,9 @@ const memoryPlugin = {
// Check for duplicates (high similarity threshold)
const existing = await db.search(vector, 1, 0.95);
if (existing.length > 0) continue;
if (existing.length > 0) {
continue;
}
await db.store({
text,