memorylake-openclaw 1.1.3 → 1.1.4

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/lib/types.ts DELETED
@@ -1,273 +0,0 @@
1
- export const DEFAULT_USER_ID = "default";
2
-
3
- export type MemoryLakeConfig = {
4
- host: string;
5
- apiKey: string;
6
- projectId: string;
7
- userId: string;
8
- autoCapture: boolean;
9
- autoRecall: boolean;
10
- autoUpload: boolean;
11
- searchThreshold: number;
12
- topK: number;
13
- rerank: boolean;
14
- webSearchIncludeDomains?: string[];
15
- webSearchExcludeDomains?: string[];
16
- webSearchCountry?: string;
17
- webSearchTimezone?: string;
18
- };
19
-
20
- // V2 API option types
21
- export interface AddOptions {
22
- user_id: string;
23
- chat_session_id?: string;
24
- metadata?: Record<string, unknown>;
25
- infer?: boolean;
26
- }
27
-
28
- export interface SearchOptions {
29
- user_id: string;
30
- top_k?: number;
31
- threshold?: number;
32
- rerank?: boolean;
33
- }
34
-
35
- export interface ListOptions {
36
- user_id?: string;
37
- page?: number;
38
- size?: number;
39
- }
40
-
41
- export interface MemoryItem {
42
- id: string;
43
- content: string;
44
- user_id?: string;
45
- created_at?: string;
46
- updated_at?: string;
47
- has_unresolved_conflict?: boolean;
48
- }
49
-
50
- export interface ConflictMemorySnapshot {
51
- memory_id: string;
52
- memory_history_id?: string;
53
- memory_text: string;
54
- }
55
-
56
- export interface ConflictFileChunk {
57
- chunk: { type?: string; text: string; range?: string };
58
- document_id?: string;
59
- document_name?: string;
60
- }
61
-
62
- export interface ConflictResolve {
63
- id: string;
64
- strategy: string;
65
- keep_memory_id?: string;
66
- forgotten_memory_ids?: string[];
67
- resolved_by?: string;
68
- created_at?: string;
69
- }
70
-
71
- export interface ConflictItem {
72
- id: string;
73
- name: string;
74
- description: string;
75
- category: "m2m" | "m2d";
76
- conflict_type: "logical" | "knowledge";
77
- memory_ids: string[];
78
- memory_snapshots: ConflictMemorySnapshot[];
79
- file_chunks: ConflictFileChunk[];
80
- resolved: boolean;
81
- resolve?: ConflictResolve;
82
- stale?: boolean;
83
- event_id?: string;
84
- created_at?: string;
85
- updated_at?: string;
86
- }
87
-
88
- export interface ConflictListResponse {
89
- items: ConflictItem[];
90
- page: number;
91
- total: number;
92
- page_size: number;
93
- }
94
-
95
- export interface AddResultItem {
96
- event_id: string;
97
- status: string;
98
- message: string;
99
- }
100
-
101
- export interface AddResult {
102
- results: AddResultItem[];
103
- }
104
-
105
- export interface DocumentSearchResult {
106
- type: "table" | "paragraph" | "figure";
107
- document_id?: string;
108
- document_name?: string;
109
- source_document?: { file_name?: string };
110
- highlight?: {
111
- chunks?: Array<{ text?: string; range?: string }>;
112
- inner_tables?: Array<{
113
- id?: string;
114
- columns?: Array<{ name?: string; data_type?: string }>;
115
- num_rows?: number;
116
- }>;
117
- figure?: {
118
- text?: string;
119
- caption?: string;
120
- summary_text?: string;
121
- };
122
- };
123
- title?: string;
124
- footnote?: string;
125
- sheet_name?: string;
126
- semantic_sheet_name?: string;
127
- figure_id?: number;
128
- }
129
-
130
- export interface DocumentSearchResponse {
131
- count: number;
132
- results: DocumentSearchResult[];
133
- }
134
-
135
- /**
136
- * Allowed values for web search domain (aligned with zootopia unified_search Domain).
137
- * Declared as enum in schema; at runtime accept string and fall back to "auto" if invalid.
138
- */
139
- export const WebSearchDomainValues = [
140
- "web",
141
- "academic",
142
- "news",
143
- "people",
144
- "company",
145
- "financial",
146
- "markets",
147
- "code",
148
- "legal",
149
- "government",
150
- "poi",
151
- "auto",
152
- ] as const;
153
- export type WebSearchDomain = (typeof WebSearchDomainValues)[number];
154
-
155
- export const WEB_SEARCH_DOMAIN_SET = new Set<string>(WebSearchDomainValues);
156
-
157
- export interface WebSearchUserLocation {
158
- country?: string;
159
- timezone?: string;
160
- }
161
-
162
- export interface WebSearchOptions {
163
- /** Declared as enum in schema; at runtime accept string, normalized with fallback to "auto". */
164
- domain?: WebSearchDomain | string;
165
- max_results?: number;
166
- start_date?: string;
167
- end_date?: string;
168
- include_domains?: string[];
169
- exclude_domains?: string[];
170
- user_location?: WebSearchUserLocation;
171
- }
172
-
173
- export interface WebSearchResult {
174
- url?: string;
175
- title?: string;
176
- summary?: string;
177
- content?: string;
178
- source?: string;
179
- published_date?: string;
180
- author?: string;
181
- score?: number;
182
- highlights?: string[];
183
- }
184
-
185
- export interface WebSearchResponse {
186
- results: WebSearchResult[];
187
- total_results: number;
188
- }
189
-
190
- /**
191
- * Allowed values for open data search category (aligned with opendata endpoint).
192
- * Maps to proprietary data sources per category.
193
- */
194
- export const OpenDataCategoryValues = [
195
- "research/academic",
196
- "clinical/trials",
197
- "drug/database",
198
- "financial/markets",
199
- "company/fundamentals",
200
- "economic/data",
201
- "patents/ip",
202
- ] as const;
203
- export type OpenDataCategory = (typeof OpenDataCategoryValues)[number];
204
-
205
- export const OPEN_DATA_CATEGORY_SET = new Set<string>(OpenDataCategoryValues);
206
-
207
- export interface OpenDataIndustry {
208
- id: string;
209
- name: string;
210
- description?: string;
211
- }
212
-
213
- export interface ProjectInfo {
214
- id: string;
215
- name: string;
216
- description?: string;
217
- industries: OpenDataIndustry[];
218
- }
219
-
220
- export interface OpenDataSearchOptions {
221
- dataset?: OpenDataCategory | string;
222
- max_results?: number;
223
- start_date?: string;
224
- end_date?: string;
225
- }
226
-
227
- export interface OpenDataSearchResult {
228
- title?: string;
229
- url?: string;
230
- summary?: string;
231
- content?: string;
232
- source?: string;
233
- category?: string;
234
- published_date?: string;
235
- author?: string;
236
- score?: number;
237
- metadata?: Record<string, unknown>;
238
- }
239
-
240
- export interface OpenDataSearchResponse {
241
- results: OpenDataSearchResult[];
242
- total_results: number;
243
- }
244
-
245
- // ============================================================================
246
- // Unified Provider Interface
247
- // ============================================================================
248
-
249
- export interface MemoryLakeProvider {
250
- add(
251
- messages: Array<{ role: string; content: string }>,
252
- options: AddOptions,
253
- ): Promise<AddResult>;
254
- search(query: string, options: SearchOptions): Promise<MemoryItem[]>;
255
- get(memoryId: string): Promise<MemoryItem>;
256
- getAll(options: ListOptions): Promise<MemoryItem[]>;
257
- delete(memoryId: string): Promise<void>;
258
- searchDocuments(query: string, topN: number): Promise<DocumentSearchResponse>;
259
- getDocumentDownloadUrl(documentId: string): Promise<string>;
260
- searchWeb(query: string, options: WebSearchOptions): Promise<WebSearchResponse>;
261
- searchOpenData(query: string, options: OpenDataSearchOptions): Promise<OpenDataSearchResponse>;
262
- getProject(): Promise<ProjectInfo>;
263
- listConflicts(memoryIds: string[], userId: string): Promise<ConflictItem[]>;
264
- }
265
-
266
- /** Shared type for the upload / uploadAuto function signature */
267
- export type UploadFn = (opts: {
268
- host: string;
269
- apiKey: string;
270
- projectId: string;
271
- filePath: string;
272
- fileName: string;
273
- }) => Promise<unknown>;
@@ -1,127 +0,0 @@
1
- import { createRequire } from "node:module";
2
- import type { MemoryLakeConfig, AddOptions, SearchOptions, DocumentSearchResult, WebSearchResult, ConflictItem, OpenDataSearchResult } from "../types";
3
-
4
- const require = createRequire(import.meta.url);
5
- const { version: PLUGIN_VERSION } = require("../../package.json") as { version: string };
6
-
7
- // ============================================================================
8
- // Context Builders
9
- // ============================================================================
10
-
11
- export function buildDocumentContext(
12
- results: DocumentSearchResult[],
13
- maxChunkLength = 10000,
14
- ): string {
15
- const parts: string[] = [];
16
-
17
- for (const result of results) {
18
- const source = result.document_name ?? result.source_document?.file_name ?? "unknown";
19
- const docId = result.document_id ?? "unknown";
20
- const highlight = result.highlight;
21
-
22
- if (result.type === "table") {
23
- const title = result.title || "Untitled Table";
24
- const sheetLabel = result.semantic_sheet_name || result.sheet_name;
25
- const sheetPart = sheetLabel ? `, sheet: ${sheetLabel}` : "";
26
- parts.push(`### Table: ${title} (from ${source}${sheetPart}, doc_id: ${docId})`);
27
- if (result.footnote) parts.push(`Note: ${result.footnote}`);
28
-
29
- for (const innerTable of highlight?.inner_tables ?? []) {
30
- const colDesc = (innerTable.columns ?? [])
31
- .map((c) => `${c.name}(${c.data_type})`)
32
- .join(", ");
33
- if (colDesc) parts.push(`Columns: ${colDesc}`);
34
- if (innerTable.num_rows != null) parts.push(`Rows: ${innerTable.num_rows}`);
35
- }
36
- for (const chunk of highlight?.chunks ?? []) {
37
- if (chunk.text) parts.push(chunk.text.slice(0, maxChunkLength));
38
- }
39
- } else if (result.type === "paragraph") {
40
- parts.push(`### Paragraph (from ${source}, doc_id: ${docId}):`);
41
- for (const chunk of highlight?.chunks ?? []) {
42
- if (chunk.text) parts.push(chunk.text.slice(0, maxChunkLength));
43
- }
44
- } else if (result.type === "figure") {
45
- const figure = highlight?.figure;
46
- if (figure) {
47
- parts.push(`### Figure (from ${source}, doc_id: ${docId}):`);
48
- if (figure.caption) parts.push(`Caption: ${figure.caption}`);
49
- const text = figure.text || figure.summary_text || "";
50
- if (text) parts.push(text);
51
- }
52
- }
53
- }
54
-
55
- return parts.join("\n\n");
56
- }
57
-
58
- export function buildWebSearchContext(results: WebSearchResult[]): string {
59
- return results
60
- .map((result, index) => {
61
- const parts = [`${index + 1}. ${result.title ?? result.url ?? "Untitled result"}`];
62
- if (result.url) parts.push(`URL: ${result.url}`);
63
- if (result.summary) parts.push(`Summary: ${result.summary}`);
64
- if (result.source) parts.push(`Source: ${result.source}`);
65
- if (result.published_date) parts.push(`Published: ${result.published_date}`);
66
- return parts.join("\n");
67
- })
68
- .join("\n\n");
69
- }
70
-
71
- export function buildConflictContext(conflicts: ConflictItem[], maxChunkLength = 200): string {
72
- return conflicts
73
- .map((c) => {
74
- const parts: string[] = [
75
- `- [${c.conflict_type}] ${c.description}`,
76
- ];
77
- for (const snap of c.memory_snapshots ?? []) {
78
- parts.push(` Memory(${snap.memory_id}): ${snap.memory_text.slice(0, maxChunkLength)}`);
79
- }
80
- for (const fc of c.file_chunks ?? []) {
81
- const docLabel = fc.document_name ?? fc.document_id ?? "unknown";
82
- parts.push(` Document(${docLabel}): ${fc.chunk.text.slice(0, maxChunkLength)}`);
83
- }
84
- return parts.join("\n");
85
- })
86
- .join("\n");
87
- }
88
-
89
- export function buildOpenDataContext(results: OpenDataSearchResult[]): string {
90
- const filtered = results.map((r) => {
91
- const item: Record<string, unknown> = {};
92
- if (r.title != null) item.title = r.title;
93
- if (r.url != null) item.url = r.url;
94
- if (r.content != null) item.content = r.content;
95
- if (r.published_date != null) item.published_date = r.published_date;
96
- if (r.category != null) item.category = r.category;
97
- return item;
98
- });
99
- return JSON.stringify(filtered, null, 2);
100
- }
101
-
102
- // ============================================================================
103
- // Option Builders
104
- // ============================================================================
105
-
106
- export function buildAddOptions(effectiveCfg: MemoryLakeConfig, userIdOverride?: string, sessionId?: string): AddOptions {
107
- const opts: AddOptions = {
108
- user_id: userIdOverride || effectiveCfg.userId,
109
- infer: true,
110
- metadata: { source: "OPENCLAW", plugin_version: PLUGIN_VERSION },
111
- };
112
- if (sessionId) opts.chat_session_id = sessionId;
113
- return opts;
114
- }
115
-
116
- export function buildSearchOptions(
117
- effectiveCfg: MemoryLakeConfig,
118
- userIdOverride?: string,
119
- limit?: number,
120
- ): SearchOptions {
121
- return {
122
- user_id: userIdOverride || effectiveCfg.userId,
123
- top_k: limit ?? effectiveCfg.topK,
124
- threshold: effectiveCfg.searchThreshold,
125
- rerank: effectiveCfg.rerank,
126
- };
127
- }
@@ -1,62 +0,0 @@
1
- /**
2
- * Vendored from openclaw/src/shared/chat-envelope.ts.
3
- *
4
- * upstream commit: 05cac5b980f60f2de9f27332c3bc55f6ff9f64e0 (2026-04-16)
5
- *
6
- * Reason for vendoring: same as lib/utils/strip-inbound-meta.ts — the
7
- * openclaw plugin SDK does not expose these helpers via any
8
- * `openclaw/plugin-sdk/*` subpath. openclaw's own gateway/chat-sanitize.ts
9
- * chains stripInboundMetadata + stripEnvelope + stripMessageIdHints for
10
- * user-role messages; we vendor all three to keep the chain identical.
11
- *
12
- * No local edits. Pure copy.
13
- */
14
-
15
- const ENVELOPE_PREFIX = /^\[([^\]]+)\]\s*/;
16
- const ENVELOPE_CHANNELS = [
17
- "WebChat",
18
- "WhatsApp",
19
- "Telegram",
20
- "Signal",
21
- "Slack",
22
- "Discord",
23
- "Google Chat",
24
- "iMessage",
25
- "Teams",
26
- "Matrix",
27
- "Zalo",
28
- "Zalo Personal",
29
- "BlueBubbles",
30
- ];
31
-
32
- const MESSAGE_ID_LINE = /^\s*\[message_id:\s*[^\]]+\]\s*$/i;
33
- function looksLikeEnvelopeHeader(header: string): boolean {
34
- if (/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z\b/.test(header)) {
35
- return true;
36
- }
37
- if (/\d{4}-\d{2}-\d{2} \d{2}:\d{2}\b/.test(header)) {
38
- return true;
39
- }
40
- return ENVELOPE_CHANNELS.some((label) => header.startsWith(`${label} `));
41
- }
42
-
43
- export function stripEnvelope(text: string): string {
44
- const match = text.match(ENVELOPE_PREFIX);
45
- if (!match) {
46
- return text;
47
- }
48
- const header = match[1] ?? "";
49
- if (!looksLikeEnvelopeHeader(header)) {
50
- return text;
51
- }
52
- return text.slice(match[0].length);
53
- }
54
-
55
- export function stripMessageIdHints(text: string): string {
56
- if (!/\[message_id:/i.test(text)) {
57
- return text;
58
- }
59
- const lines = text.split(/\r?\n/);
60
- const filtered = lines.filter((line) => !MESSAGE_ID_LINE.test(line));
61
- return filtered.length === lines.length ? text : filtered.join("\n");
62
- }
@@ -1,14 +0,0 @@
1
- import fs from "node:fs";
2
- import JSON5 from "json5";
3
-
4
- /**
5
- * Read and parse a JSON5-compatible config file.
6
- */
7
- export function readJson5ConfigFile(filePath: string): unknown {
8
- const source = fs.readFileSync(filePath, "utf-8");
9
- try {
10
- return JSON5.parse(source);
11
- } catch (err) {
12
- throw new Error(`Failed to parse JSON5 config file "${filePath}": ${String(err)}`);
13
- }
14
- }
@@ -1,12 +0,0 @@
1
- /**
2
- * The reminder string our auto-recall hook prepends to every user turn via
3
- * `prependContext`. Auto-capture has to know the exact same string to strip
4
- * it back out before storing the message — putting it in its own file keeps
5
- * the auto-recall (producer) and stripUserBody (consumer) decoupled and
6
- * lets the strip path be unit-tested without dragging in the provider /
7
- * runtime dependencies that auto-recall.ts has to load.
8
- */
9
- export const MEMORYLAKE_REMINDER = [
10
- `[MEMORYLAKE REMINDER] Before responding to this message, call \`retrieve_context\` first`,
11
- `to fetch relevant memories and documents. Do not skip this step.`,
12
- ].join(" ");
@@ -1,76 +0,0 @@
1
- import type { MemoryItem, AddResult, WebSearchResponse, OpenDataSearchResult, OpenDataSearchResponse, WebSearchDomain, OpenDataCategory } from "../types";
2
- import { WEB_SEARCH_DOMAIN_SET, OPEN_DATA_CATEGORY_SET } from "../types";
3
-
4
- /** Normalize domain: accept string at runtime; if not a valid enum value, return "auto". */
5
- export function normalizeWebSearchDomain(value: unknown): WebSearchDomain {
6
- if (value == null) return "auto";
7
- const s = typeof value === "string" ? value.toLowerCase().trim() : "";
8
- return (WEB_SEARCH_DOMAIN_SET.has(s) ? s : "auto") as WebSearchDomain;
9
- }
10
-
11
- /** Normalize category: accept string at runtime; return undefined if not a valid enum value. */
12
- export function normalizeOpenDataCategory(value: unknown): OpenDataCategory | undefined {
13
- if (value == null) return undefined;
14
- const s = typeof value === "string" ? value.toLowerCase().trim() : "";
15
- return OPEN_DATA_CATEGORY_SET.has(s) ? (s as OpenDataCategory) : undefined;
16
- }
17
-
18
- export function normalizeMemoryItem(raw: any): MemoryItem {
19
- return {
20
- id: raw.id ?? "",
21
- content: raw.content ?? "",
22
- user_id: raw.user_id,
23
- created_at: raw.created_at,
24
- updated_at: raw.updated_at,
25
- has_unresolved_conflict: raw.has_unresolved_conflict ?? false,
26
- };
27
- }
28
-
29
- export function normalizeSearchResults(raw: any): MemoryItem[] {
30
- if (raw?.results && Array.isArray(raw.results))
31
- return raw.results.map(normalizeMemoryItem);
32
- if (Array.isArray(raw)) return raw.map(normalizeMemoryItem);
33
- return [];
34
- }
35
-
36
- export function normalizeAddResult(raw: any): AddResult {
37
- const items = raw?.results ?? (Array.isArray(raw) ? raw : []);
38
- return {
39
- results: items.map((r: any) => ({
40
- event_id: r.event_id ?? "",
41
- status: r.status ?? "",
42
- message: r.message ?? "",
43
- })),
44
- };
45
- }
46
-
47
- export function normalizeWebSearchResponse(raw: any): WebSearchResponse {
48
- return {
49
- results: Array.isArray(raw?.results) ? raw.results : [],
50
- total_results: typeof raw?.total_results === "number" ? raw.total_results : 0,
51
- };
52
- }
53
-
54
- export function normalizeOpenDataResult(raw: any): OpenDataSearchResult {
55
- return {
56
- title: typeof raw?.title === "string" ? raw.title : undefined,
57
- url: typeof raw?.url === "string" ? raw.url : undefined,
58
- summary: typeof raw?.summary === "string" ? raw.summary : undefined,
59
- content: typeof raw?.content === "string" ? raw.content : undefined,
60
- source: typeof raw?.source === "string" ? raw.source : undefined,
61
- category: typeof raw?.category === "string" ? raw.category : undefined,
62
- published_date: typeof raw?.published_date === "string" ? raw.published_date : undefined,
63
- author: typeof raw?.author === "string" ? raw.author : undefined,
64
- score: typeof raw?.score === "number" ? raw.score : undefined,
65
- metadata: raw?.metadata && typeof raw.metadata === "object" && !Array.isArray(raw.metadata)
66
- ? raw.metadata as Record<string, unknown>
67
- : undefined,
68
- };
69
- }
70
-
71
- export function normalizeOpenDataSearchResponse(raw: any): OpenDataSearchResponse {
72
- return {
73
- results: Array.isArray(raw?.results) ? raw.results.map(normalizeOpenDataResult) : [],
74
- total_results: typeof raw?.total_results === "number" ? raw.total_results : 0,
75
- };
76
- }