From a7911ffaf054d7cba5d1061698339a7ef55915e8 Mon Sep 17 00:00:00 2001 From: yuanrengu Date: Fri, 15 May 2026 16:32:10 +0800 Subject: [PATCH] refactor: unify duplicate Logger interfaces into single canonical type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 23 files had local Logger/StoreLogger/PluginLogger/PipelineLogger/RunnerLogger/ExtractorLogger/TriggerLogger interface definitions with identical shapes ({debug?, info, warn, error}). Replace all with imports from the canonical `Logger` in `src/core/types.ts`: - 17 files: local `interface Logger` → `import type { Logger }` - 6 files: named variants (StoreLogger, PluginLogger, etc.) → `type X = Logger` alias Two intentionally different interfaces are preserved: - `CheckpointLogger` (only info + optional warn) — different contract - `ensure-hook-policy.ts` Logger (no error) — different contract Net: -120 lines, zero behavioral change. Signed-off-by: yuanrengu --- src/core/conversation/l0-recorder.ts | 8 +------- src/core/hooks/auto-capture.ts | 9 ++------- src/core/hooks/auto-recall.ts | 8 +------- src/core/persona/persona-generator.ts | 9 +-------- src/core/persona/persona-trigger.ts | 9 +++------ src/core/profile/profile-sync.ts | 8 +------- src/core/record/l1-dedup.ts | 9 +-------- src/core/record/l1-extractor.ts | 9 +-------- src/core/record/l1-reader.ts | 8 +------- src/core/record/l1-writer.ts | 8 +------- src/core/scene/scene-extractor.ts | 9 ++------- src/core/store/bm25-client.ts | 9 ++------- src/core/store/bm25-local.ts | 8 +------- src/core/store/embedding.ts | 13 ++----------- src/core/store/sqlite.ts | 8 +------- src/core/store/types.ts | 8 ++------ src/core/tools/conversation-search.ts | 8 +------- src/core/tools/memory-search.ts | 8 +------- src/offload/types.ts | 9 +++------ src/utils/clean-context-runner.ts | 8 ++------ src/utils/memory-cleaner.ts | 8 +------- src/utils/pipeline-factory.ts | 9 +++------ src/utils/pipeline-manager.ts | 8 +------- 23 files changed, 35 insertions(+), 163 deletions(-) diff --git a/src/core/conversation/l0-recorder.ts b/src/core/conversation/l0-recorder.ts index 026a876..c9a75c1 100644 --- a/src/core/conversation/l0-recorder.ts +++ b/src/core/conversation/l0-recorder.ts @@ -18,6 +18,7 @@ import fs from "node:fs/promises"; import path from "node:path"; import crypto from "node:crypto"; import { sanitizeText, stripCodeBlocks, shouldCaptureL0 } from "../../utils/sanitize.js"; +import type { Logger } from "../types.js"; // ============================ // Types @@ -63,13 +64,6 @@ export interface L0ConversationRecord { messages: ConversationMessage[]; } -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - const TAG = "[memory-tdai][l0]"; // ============================ diff --git a/src/core/hooks/auto-capture.ts b/src/core/hooks/auto-capture.ts index 18eaaee..0edee46 100644 --- a/src/core/hooks/auto-capture.ts +++ b/src/core/hooks/auto-capture.ts @@ -19,14 +19,9 @@ import type { ConversationMessage } from "../conversation/l0-recorder.js"; import type { IMemoryStore, L0Record } from "../store/types.js"; import type { EmbeddingService } from "../store/embedding.js"; -const TAG = "[memory-tdai] [capture]"; +import type { Logger } from "../types.js"; -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +const TAG = "[memory-tdai] [capture]"; export interface AutoCaptureResult { /** Whether the scheduler was notified (conversation count incremented) */ diff --git a/src/core/hooks/auto-recall.ts b/src/core/hooks/auto-recall.ts index cccb864..2eeec91 100644 --- a/src/core/hooks/auto-recall.ts +++ b/src/core/hooks/auto-recall.ts @@ -20,6 +20,7 @@ import type { IMemoryStore, L1SearchResult, L1FtsResult } from "../store/types.j import { buildFtsQuery } from "../store/sqlite.js"; import type { EmbeddingService, EmbeddingCallOptions } from "../store/embedding.js"; import { sanitizeText } from "../../utils/sanitize.js"; +import type { Logger } from "../types.js"; const TAG = "[memory-tdai] [recall]"; @@ -42,13 +43,6 @@ const MEMORY_TOOLS_GUIDE = ` - 若 3 次搜索后仍无结果,说明该信息不在记忆中,请直接根据已有信息回复用户,不要继续搜索。 ` -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - /** A single recalled L1 memory with its search score and type. */ export interface RecalledMemory { content: string; diff --git a/src/core/persona/persona-generator.ts b/src/core/persona/persona-generator.ts index 438b359..d0ae93c 100644 --- a/src/core/persona/persona-generator.ts +++ b/src/core/persona/persona-generator.ts @@ -13,17 +13,10 @@ import { buildPersonaPrompt } from "../prompts/persona-generation.js"; import { BackupManager } from "../../utils/backup.js"; import { escapeXmlTags } from "../../utils/sanitize.js"; import { report } from "../report/reporter.js"; -import type { LLMRunner } from "../types.js"; +import type { LLMRunner, Logger } from "../types.js"; const TAG = "[memory-tdai] [persona]"; -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - export class PersonaGenerator { private dataDir: string; private runner: LLMRunner; diff --git a/src/core/persona/persona-trigger.ts b/src/core/persona/persona-trigger.ts index 41c2abb..5c671e3 100644 --- a/src/core/persona/persona-trigger.ts +++ b/src/core/persona/persona-trigger.ts @@ -8,14 +8,11 @@ import path from "node:path"; import { CheckpointManager } from "../../utils/checkpoint.js"; import { stripSceneNavigation } from "../scene/scene-navigation.js"; +import type { Logger } from "../types.js"; + const TAG = "[memory-tdai] [trigger]"; -interface TriggerLogger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +type TriggerLogger = Logger; export interface TriggerResult { should: boolean; diff --git a/src/core/profile/profile-sync.ts b/src/core/profile/profile-sync.ts index c921265..3d931db 100644 --- a/src/core/profile/profile-sync.ts +++ b/src/core/profile/profile-sync.ts @@ -4,6 +4,7 @@ import path from "node:path"; import type { IMemoryStore, ProfileRecord, ProfileSyncRecord } from "../store/types.js"; import { readSceneIndex, syncSceneIndex } from "../scene/scene-index.js"; import { generateSceneNavigation, stripSceneNavigation } from "../scene/scene-navigation.js"; +import type { Logger } from "../types.js"; const PROFILE_SCOPE = "global"; @@ -13,13 +14,6 @@ function isRenameRaceError(err: unknown): boolean { return code === "ENOTEMPTY" || code === "EEXIST"; } -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - export interface ProfileBaseline { version: number; contentMd5: string; diff --git a/src/core/record/l1-dedup.ts b/src/core/record/l1-dedup.ts index 5d833e1..0fb6bf6 100644 --- a/src/core/record/l1-dedup.ts +++ b/src/core/record/l1-dedup.ts @@ -19,14 +19,7 @@ import { sanitizeJsonForParse } from "../../utils/sanitize.js"; import type { IMemoryStore } from "../store/types.js"; import { buildFtsQuery } from "../store/sqlite.js"; import type { EmbeddingService } from "../store/embedding.js"; -import type { LLMRunner } from "../types.js"; - -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +import type { LLMRunner, Logger } from "../types.js"; const TAG = "[memory-tdai][l1-dedup]"; diff --git a/src/core/record/l1-extractor.ts b/src/core/record/l1-extractor.ts index ad0a8f1..d38fd4b 100644 --- a/src/core/record/l1-extractor.ts +++ b/src/core/record/l1-extractor.ts @@ -22,14 +22,7 @@ import { sanitizeJsonForParse, shouldExtractL1 } from "../../utils/sanitize.js"; import type { IMemoryStore } from "../store/types.js"; import type { EmbeddingService } from "../store/embedding.js"; import { report } from "../report/reporter.js"; -import type { LLMRunner } from "../types.js"; - -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +import type { LLMRunner, Logger } from "../types.js"; const TAG = "[memory-tdai][l1-extractor]"; diff --git a/src/core/record/l1-reader.ts b/src/core/record/l1-reader.ts index 66e8d39..1561161 100644 --- a/src/core/record/l1-reader.ts +++ b/src/core/record/l1-reader.ts @@ -19,13 +19,7 @@ import type { IMemoryStore, L1RecordRow, L1QueryFilter } from "../store/types.js // Re-export types that readers need export type { MemoryRecord, MemoryType, EpisodicMetadata } from "./l1-writer.js"; export type { L1QueryFilter } from "../store/types.js"; - -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +import type { Logger } from "../types.js"; const TAG = "[memory-tdai] [l1-reader]"; diff --git a/src/core/record/l1-writer.ts b/src/core/record/l1-writer.ts index b5e618d..235c45a 100644 --- a/src/core/record/l1-writer.ts +++ b/src/core/record/l1-writer.ts @@ -21,6 +21,7 @@ import path from "node:path"; import crypto from "node:crypto"; import type { IMemoryStore } from "../store/types.js"; import type { EmbeddingService } from "../store/embedding.js"; +import type { Logger } from "../types.js"; // ============================ // Types @@ -110,13 +111,6 @@ export interface DedupDecision { merged_timestamps?: string[]; } -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - const TAG = "[memory-tdai][l1-writer]"; // ============================ diff --git a/src/core/scene/scene-extractor.ts b/src/core/scene/scene-extractor.ts index 71288f4..0d294c0 100644 --- a/src/core/scene/scene-extractor.ts +++ b/src/core/scene/scene-extractor.ts @@ -27,16 +27,11 @@ import { parseSceneBlock } from "../scene/scene-format.js"; import { generateSceneNavigation, stripSceneNavigation } from "../scene/scene-navigation.js"; import { buildSceneExtractionPrompt } from "../prompts/scene-extraction.js"; import { report } from "../report/reporter.js"; -import type { LLMRunner } from "../types.js"; +import type { LLMRunner, Logger } from "../types.js"; const TAG = "[memory-tdai] [extractor]"; -interface ExtractorLogger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +type ExtractorLogger = Logger; export interface ExtractionResult { memoriesProcessed: number; diff --git a/src/core/store/bm25-client.ts b/src/core/store/bm25-client.ts index 031c2d2..df39ad8 100644 --- a/src/core/store/bm25-client.ts +++ b/src/core/store/bm25-client.ts @@ -13,6 +13,8 @@ * check health to dynamically downgrade to pure semantic search. */ +import type { Logger } from "../types.js"; + // ============================ // Types // ============================ @@ -20,13 +22,6 @@ /** Sparse vector: array of [token_hash, weight] pairs. */ export type SparseVector = Array<[number, number]>; -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - export interface BM25ClientConfig { /** Sidecar service URL (default: "http://127.0.0.1:8084") */ serviceUrl: string; diff --git a/src/core/store/bm25-local.ts b/src/core/store/bm25-local.ts index 548db4f..b24acaa 100644 --- a/src/core/store/bm25-local.ts +++ b/src/core/store/bm25-local.ts @@ -11,16 +11,10 @@ import { BM25Encoder } from "@tencentdb-agent-memory/tcvdb-text"; import type { SparseVector } from "@tencentdb-agent-memory/tcvdb-text"; +import type { Logger } from "../types.js"; export type { SparseVector }; -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - export interface BM25LocalConfig { /** Whether BM25 sparse encoding is enabled (default: true) */ enabled: boolean; diff --git a/src/core/store/embedding.ts b/src/core/store/embedding.ts index 2850334..f37cf3b 100644 --- a/src/core/store/embedding.ts +++ b/src/core/store/embedding.ts @@ -13,6 +13,8 @@ * - Throws on failure; callers decide fallback strategy. */ +import type { Logger } from "../types.js"; + // ============================ // Types // ============================ @@ -97,17 +99,6 @@ export class EmbeddingNotReadyError extends Error { } } -// ============================ -// Logger interface -// ============================ - -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - const TAG = "[memory-tdai][embedding]"; // ============================ diff --git a/src/core/store/sqlite.ts b/src/core/store/sqlite.ts index 6252419..1dd8ffd 100644 --- a/src/core/store/sqlite.ts +++ b/src/core/store/sqlite.ts @@ -33,6 +33,7 @@ import type { L0SearchResult, L0FtsResult, } from "./types.js"; +import type { Logger } from "../types.js"; // ============================ // Types @@ -106,13 +107,6 @@ export interface L1QueryFilter { updatedAfter?: string; } -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - const TAG = "[memory-tdai][sqlite]"; /** Persisted metadata about the embedding provider used to generate stored vectors. */ diff --git a/src/core/store/types.ts b/src/core/store/types.ts index cfcb50a..7cf62ce 100644 --- a/src/core/store/types.ts +++ b/src/core/store/types.ts @@ -17,6 +17,7 @@ import type { MemoryRecord } from "../record/l1-writer.js"; import type { EmbeddingProviderInfo } from "./embedding.js"; +import type { Logger } from "../types.js"; // Re-export so consumers can import everything from types.ts export type { MemoryRecord, EmbeddingProviderInfo }; @@ -26,12 +27,7 @@ export type { MemoryRecord, EmbeddingProviderInfo }; // ============================ /** Minimal logger interface accepted by store implementations. */ -export interface StoreLogger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +export type StoreLogger = Logger; // ============================ // L1 Types (Structured Memories) diff --git a/src/core/tools/conversation-search.ts b/src/core/tools/conversation-search.ts index ac4f3b1..d25ae17 100644 --- a/src/core/tools/conversation-search.ts +++ b/src/core/tools/conversation-search.ts @@ -13,18 +13,12 @@ import type { IMemoryStore, L0SearchResult } from "../store/types.js"; import { buildFtsQuery } from "../store/sqlite.js"; import type { EmbeddingService } from "../store/embedding.js"; +import type { Logger } from "../types.js"; // ============================ // Types // ============================ -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - export interface ConversationSearchResultItem { id: string; session_key: string; diff --git a/src/core/tools/memory-search.ts b/src/core/tools/memory-search.ts index dc9d2c2..e1d5c05 100644 --- a/src/core/tools/memory-search.ts +++ b/src/core/tools/memory-search.ts @@ -13,18 +13,12 @@ import type { IMemoryStore, L1SearchResult } from "../store/types.js"; import { buildFtsQuery } from "../store/sqlite.js"; import type { EmbeddingService } from "../store/embedding.js"; +import type { Logger } from "../types.js"; // ============================ // Types // ============================ -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - export interface MemorySearchResultItem { id: string; content: string; diff --git a/src/offload/types.ts b/src/offload/types.ts index a8ca581..e36bb20 100644 --- a/src/offload/types.ts +++ b/src/offload/types.ts @@ -3,6 +3,8 @@ * Ported from context-offload-plugin with updated runtime defaults. */ +import type { Logger } from "../core/types.js"; + // ============================ // Data types // ============================ @@ -212,12 +214,7 @@ export interface PluginConfig { // ============================ /** Logger interface used by offload plugin components */ -export interface PluginLogger { - info: (msg: string) => void; - warn: (msg: string) => void; - error: (msg: string) => void; - debug?: (msg: string) => void; -} +export type PluginLogger = Logger; // ============================ // Plugin defaults diff --git a/src/utils/clean-context-runner.ts b/src/utils/clean-context-runner.ts index 868d787..525b996 100644 --- a/src/utils/clean-context-runner.ts +++ b/src/utils/clean-context-runner.ts @@ -17,6 +17,7 @@ import { fileURLToPath, pathToFileURL } from "node:url"; import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; import { getEnv } from "./env.js"; import { report } from "../core/report/reporter.js"; +import type { Logger } from "../core/types.js"; /** * Resolve a preferred temporary directory for memory-tdai operations. @@ -49,12 +50,7 @@ function resolveOpenClawTmpDir(): string { const TAG = "[memory-tdai] [runner]"; -interface RunnerLogger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +type RunnerLogger = Logger; // Dynamic import type — runEmbeddedPiAgent is an internal API // Prefer the public plugin runtime signature so host-injected runtimes stay assignable. diff --git a/src/utils/memory-cleaner.ts b/src/utils/memory-cleaner.ts index a6c641e..d0454f9 100644 --- a/src/utils/memory-cleaner.ts +++ b/src/utils/memory-cleaner.ts @@ -3,13 +3,7 @@ import path from "node:path"; import type { IMemoryStore } from "../core/store/types.js"; import { ManagedTimer } from "./managed-timer.js"; - -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +import type { Logger } from "../core/types.js"; export interface MemoryCleanerOptions { baseDir: string; diff --git a/src/utils/pipeline-factory.ts b/src/utils/pipeline-factory.ts index 4595753..9013878 100644 --- a/src/utils/pipeline-factory.ts +++ b/src/utils/pipeline-factory.ts @@ -36,6 +36,7 @@ import { SceneExtractor } from "../core/scene/scene-extractor.js"; import { PersonaTrigger } from "../core/persona/persona-trigger.js"; import { PersonaGenerator } from "../core/persona/persona-generator.js"; import { pullProfilesToLocal, syncLocalProfilesToStore } from "../core/profile/profile-sync.js"; +import type { Logger } from "../core/types.js"; const TAG = "[memory-tdai] [pipeline-factory]"; @@ -47,12 +48,8 @@ function supportsProfileSyncWrite(store?: IMemoryStore): boolean { // Logger interface // ============================ -export interface PipelineLogger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} +/** @deprecated Use `Logger` from `../core/types.js` directly. */ +export type PipelineLogger = Logger; // ============================ // Factory options diff --git a/src/utils/pipeline-manager.ts b/src/utils/pipeline-manager.ts index b56234c..1644616 100644 --- a/src/utils/pipeline-manager.ts +++ b/src/utils/pipeline-manager.ts @@ -81,18 +81,12 @@ import { SessionFilter } from "./session-filter.js"; import { ManagedTimer } from "./managed-timer.js"; import { SerialQueue } from "./serial-queue.js"; import { report } from "../core/report/reporter.js"; +import type { Logger } from "../core/types.js"; // ============================ // Types // ============================ -interface Logger { - debug?: (message: string) => void; - info: (message: string) => void; - warn: (message: string) => void; - error: (message: string) => void; -} - /** A single captured message ready for L1 processing. */ export interface CapturedMessage { role: "user" | "assistant" | "tool";