mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-20 21:23:23 +00:00
refactor: dedupe memory-core error formatting
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
|
||||
// ── Types ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -286,7 +287,7 @@ export async function generateAndAppendDreamNarrative(params: {
|
||||
} catch (err) {
|
||||
// Narrative generation is best-effort — never fail the parent phase.
|
||||
params.logger.warn(
|
||||
`memory-core: narrative generation failed for ${params.data.phase} phase: ${err instanceof Error ? err.message : String(err)}`,
|
||||
`memory-core: narrative generation failed for ${params.data.phase} phase: ${formatErrorMessage(err)}`,
|
||||
);
|
||||
} finally {
|
||||
// Clean up the transient session.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import fs from "node:fs/promises";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import {
|
||||
enforceEmbeddingMaxInputTokens,
|
||||
hasNonTextEmbeddingParts,
|
||||
@@ -414,7 +415,7 @@ export abstract class MemoryManagerEmbeddingOps extends MemoryManagerSyncOps {
|
||||
try {
|
||||
return await params.run();
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
if (this.isBatchTimeoutError(message)) {
|
||||
log.warn(`memory embeddings: ${params.provider} batch timed out; retrying once`);
|
||||
try {
|
||||
@@ -444,7 +445,7 @@ export abstract class MemoryManagerEmbeddingOps extends MemoryManagerSyncOps {
|
||||
await this.resetBatchFailureCount();
|
||||
return result;
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
const attempts = (err as { batchAttempts?: number }).batchAttempts ?? 1;
|
||||
const forceDisable = /asyncBatchEmbedContent not available/i.test(message);
|
||||
const failure = await this.recordBatchFailure({
|
||||
@@ -636,7 +637,7 @@ export abstract class MemoryManagerEmbeddingOps extends MemoryManagerSyncOps {
|
||||
? await this.embedChunksWithBatch(chunks, entry, options.source)
|
||||
: await this.embedChunksInBatches(chunks);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
if (
|
||||
"kind" in entry &&
|
||||
entry.kind === "multimodal" &&
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
|
||||
type MemoryEmbeddingTextPart = {
|
||||
type: "text";
|
||||
text: string;
|
||||
@@ -111,7 +113,7 @@ export async function runMemoryEmbeddingRetryLoop<T>(params: {
|
||||
try {
|
||||
return await params.run();
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
if (!params.isRetryable(message) || attempt >= params.maxAttempts) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { DatabaseSync } from "node:sqlite";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import {
|
||||
createSubsystemLogger,
|
||||
type OpenClawConfig,
|
||||
@@ -49,7 +50,7 @@ export function isMemoryReadonlyDbError(err: unknown): boolean {
|
||||
messages.add(normalized);
|
||||
};
|
||||
|
||||
pushValue(err instanceof Error ? err.message : String(err));
|
||||
pushValue(formatErrorMessage(err));
|
||||
if (err && typeof err === "object") {
|
||||
const record = err as Record<string, unknown>;
|
||||
pushValue(record.message);
|
||||
|
||||
@@ -4,6 +4,7 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type { DatabaseSync } from "node:sqlite";
|
||||
import chokidar, { FSWatcher } from "chokidar";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import {
|
||||
buildCaseInsensitiveExtensionGlob,
|
||||
classifyMemoryMultimodalPath,
|
||||
@@ -184,7 +185,7 @@ export abstract class MemoryManagerSyncOps {
|
||||
try {
|
||||
ready = (await this.vectorReady) || false;
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
this.vector.available = false;
|
||||
this.vector.loadError = message;
|
||||
this.vectorReady = null;
|
||||
@@ -217,7 +218,7 @@ export abstract class MemoryManagerSyncOps {
|
||||
this.vector.available = true;
|
||||
return true;
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
this.vector.available = false;
|
||||
this.vector.loadError = message;
|
||||
log.warn(`sqlite-vec unavailable: ${message}`);
|
||||
@@ -245,7 +246,7 @@ export abstract class MemoryManagerSyncOps {
|
||||
try {
|
||||
this.db.exec(`DROP TABLE IF EXISTS ${VECTOR_TABLE}`);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
log.debug(`Failed to drop ${VECTOR_TABLE}: ${message}`);
|
||||
}
|
||||
}
|
||||
@@ -1002,7 +1003,7 @@ export abstract class MemoryManagerSyncOps {
|
||||
this.sessionsDirty = false;
|
||||
}
|
||||
} catch (err) {
|
||||
const reason = err instanceof Error ? err.message : String(err);
|
||||
const reason = formatErrorMessage(err);
|
||||
const activated =
|
||||
this.shouldFallbackOnError(reason) && (await this.activateFallbackProvider(reason));
|
||||
if (activated) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import type { MemorySyncProgressUpdate } from "openclaw/plugin-sdk/memory-core-host-engine-storage";
|
||||
|
||||
type TargetedSyncProgress = {
|
||||
@@ -67,7 +68,7 @@ export async function runMemoryTargetedSessionSync(params: {
|
||||
}),
|
||||
};
|
||||
} catch (err) {
|
||||
const reason = err instanceof Error ? err.message : String(err);
|
||||
const reason = formatErrorMessage(err);
|
||||
const activated =
|
||||
params.shouldFallbackOnError(reason) && (await params.activateFallbackProvider(reason));
|
||||
if (!activated) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { DatabaseSync } from "node:sqlite";
|
||||
import { type FSWatcher } from "chokidar";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import {
|
||||
createSubsystemLogger,
|
||||
resolveAgentDir,
|
||||
@@ -776,7 +777,7 @@ export class MemoryIndexManager extends MemoryManagerEmbeddingOps implements Mem
|
||||
await this.embedBatchWithRetry(["ping"]);
|
||||
return { ok: true };
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
return { ok: false, error: message };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import readline from "node:readline";
|
||||
import chokidar, { type FSWatcher } from "chokidar";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { withFileLock } from "openclaw/plugin-sdk/file-lock";
|
||||
import {
|
||||
createSubsystemLogger,
|
||||
@@ -431,7 +432,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
try {
|
||||
await this.removeCollection(collection.name);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
if (!this.isCollectionMissingError(message)) {
|
||||
log.warn(`qmd collection remove failed for ${collection.name}: ${message}`);
|
||||
}
|
||||
@@ -445,7 +446,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
pattern: collection.pattern,
|
||||
});
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
if (this.isCollectionAlreadyExistsError(message)) {
|
||||
const rebound = await this.tryRebindConflictingCollection({
|
||||
collection,
|
||||
@@ -579,7 +580,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
await this.removeCollection(legacyName);
|
||||
existing.delete(legacyName);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
if (!this.isCollectionMissingError(message)) {
|
||||
log.warn(`qmd collection remove failed for ${legacyName}: ${message}`);
|
||||
}
|
||||
@@ -637,7 +638,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
}
|
||||
|
||||
private isMissingCollectionSearchError(err: unknown): boolean {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
return this.isCollectionMissingError(message) && message.toLowerCase().includes("collection");
|
||||
}
|
||||
|
||||
@@ -794,7 +795,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
}
|
||||
|
||||
private shouldRepairNullByteCollectionError(err: unknown): boolean {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
const lower = message.toLowerCase();
|
||||
return (
|
||||
(lower.includes("enotdir") ||
|
||||
@@ -806,7 +807,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
}
|
||||
|
||||
private shouldRepairDuplicateDocumentConstraint(err: unknown): boolean {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
const lower = message.toLowerCase();
|
||||
return (
|
||||
lower.includes("unique constraint failed") &&
|
||||
@@ -1155,7 +1156,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
: "QMD index has 0 vectors; semantic search is unavailable until embeddings finish";
|
||||
return this.vectorAvailable;
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
this.vectorAvailable = false;
|
||||
this.vectorStatusDetail = `QMD status probe failed: ${message}`;
|
||||
return false;
|
||||
@@ -1360,7 +1361,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
if (this.isSqliteBusyError(err)) {
|
||||
return true;
|
||||
}
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
const normalized = message.toLowerCase();
|
||||
return normalized.includes("timed out");
|
||||
}
|
||||
@@ -1614,7 +1615,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
}
|
||||
|
||||
private isQueryToolNotFoundError(err: unknown): boolean {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
const detail = message.match(/ failed \(code \d+\): ([\s\S]*)$/)?.[1];
|
||||
if (!detail) {
|
||||
return false;
|
||||
@@ -2518,13 +2519,13 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
}
|
||||
|
||||
private isSqliteBusyError(err: unknown): boolean {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
const normalized = message.toLowerCase();
|
||||
return normalized.includes("sqlite_busy") || normalized.includes("database is locked");
|
||||
}
|
||||
|
||||
private isUnsupportedQmdOptionError(err: unknown): boolean {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
const normalized = message.toLowerCase();
|
||||
return (
|
||||
normalized.includes("unknown flag") ||
|
||||
@@ -2536,7 +2537,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
||||
}
|
||||
|
||||
private createQmdBusyError(err: unknown): Error {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
return new Error(`qmd index busy while reading results: ${message}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import {
|
||||
createSubsystemLogger,
|
||||
resolveAgentWorkspaceDir,
|
||||
@@ -104,7 +105,7 @@ export async function getMemorySearchManager(params: {
|
||||
return { manager: wrapper };
|
||||
}
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
log.warn(`qmd memory unavailable; falling back to builtin: ${message}`);
|
||||
}
|
||||
}
|
||||
@@ -115,7 +116,7 @@ export async function getMemorySearchManager(params: {
|
||||
const manager = await MemoryIndexManager.get(params);
|
||||
return { manager };
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
return { manager: null, error: message };
|
||||
}
|
||||
}
|
||||
@@ -197,7 +198,7 @@ class FallbackMemoryManager implements MemorySearchManager {
|
||||
return await this.deps.primary.search(query, opts);
|
||||
} catch (err) {
|
||||
this.primaryFailed = true;
|
||||
this.lastError = err instanceof Error ? err.message : String(err);
|
||||
this.lastError = formatErrorMessage(err);
|
||||
log.warn(`qmd memory failed; switching to builtin index: ${this.lastError}`);
|
||||
await this.deps.primary.close?.().catch(() => {});
|
||||
// Evict the failed wrapper so the next request can retry QMD with a fresh manager.
|
||||
@@ -302,7 +303,7 @@ class FallbackMemoryManager implements MemorySearchManager {
|
||||
return null;
|
||||
}
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
log.warn(`memory fallback unavailable: ${message}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import {
|
||||
jsonResult,
|
||||
readNumberParam,
|
||||
@@ -239,7 +240,7 @@ export function createMemorySearchTool(options: {
|
||||
mode: searchMode,
|
||||
});
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
const message = formatErrorMessage(err);
|
||||
return jsonResult(buildMemorySearchUnavailableResult(message));
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user