memorylake-openclaw 1.0.2-beta.7 → 1.1.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,55 @@
1
+ # Changelog
2
+
3
+ ## v1.1.0 — 2026-04-21
4
+
5
+ Major release introducing **model-driven memory recall**, **cross-platform archive upload**, and a full modular refactor of the plugin.
6
+
7
+ ### Features
8
+
9
+ #### Memory & retrieval
10
+ - **Model-driven recall** (#27): replaced server-side prefetch/inject with instructions that prompt the model to call `retrieve_context` itself — eliminates query-rewrite + search latency on every turn.
11
+ - **Renamed** `memory_search` → `retrieve_context`; the tool now searches **both memories and documents in a single call**, running provider searches in parallel via `Promise.allSettled`.
12
+ - **Memory conflicts** are surfaced in `retrieve_context` results (previously only in auto-recall path).
13
+ - **Per-turn `[MEMORYLAKE REMINDER]`** prepended to each user turn to keep retrieval enforcement alive in long conversations where the system prompt is far away.
14
+
15
+ #### Upload & documents
16
+ - New **`openclaw memorylake upload`** CLI command (`--agent`, `--project-id`).
17
+ - **Auto-detect files / archives / directories** — a single path can be a plain file, an archive, or a directory tree.
18
+ - **Cross-platform archive extraction via npm packages** (no external tools required):
19
+ - zip, tar, tar.gz, tgz — `adm-zip` + `tar`
20
+ - 7z, bz2, tar.bz2 — `7zip-min` (bundled 7za binaries)
21
+ - rar — `node-unrar-js` (WASM)
22
+ - xz, tar.xz, txz — `xz-decompress` (streaming, OOM-safe)
23
+ - New **`document_download`** tool: streams file to `{workspaceDir}/.memorylake/downloads/`, extracts filename from `Content-Disposition` (supports RFC 5987 / Unicode).
24
+ - Sliding-window concurrency pool: 10 uploads in flight, next file starts as soon as one finishes.
25
+
26
+ #### Config & install
27
+ - **Hot-reload global config** (#35): each tool/hook call re-reads `~/.openclaw/openclaw.json`, so `apiKey` / `projectId` / `host` / `topK` changes take effect without gateway restart.
28
+ - **Installer auto-sets `tools.profile = "full"`** (#34), prompting before overwriting a non-`full` value.
29
+ - **Installer `--host` / `-MLHost` / `MEMORYLAKE_HOST`** (#36) for overriding the MemoryLake host URL.
30
+ - Plugin version now included in memory metadata.
31
+
32
+ ### Refactor
33
+ - Monolithic `index.ts` (~2190 lines) split into focused modules under `lib/`:
34
+ - `types.ts`, `config.ts`, `provider.ts`, `plugin-context.ts`, `core-bridge.ts`
35
+ - `tools/` (memory-tools, document-tools, search-tools)
36
+ - `hooks/` (auto-recall, auto-capture, auto-upload)
37
+ - `cli/`, `prompt/`, `helpers/`, `utils/`
38
+ - `index.ts` is now ~60 lines — plugin skeleton only.
39
+
40
+ ### Removed
41
+ - `document_search` tool — redundant with `retrieve_context`.
42
+ - `memory_get` tool — rarely needed.
43
+
44
+ ### Fixes
45
+ - Strip `[MEMORYLAKE REMINDER]` prefix before auto-capturing user messages so reminders don't leak into stored memories.
46
+ - `execSync` → `execFileSync` to prevent command injection via malicious filenames in archive extraction.
47
+ - Filter junk files (`.DS_Store`, `__MACOSX`, `Thumbs.db`, dotfiles) when collecting from archives/directories.
48
+ - Await `uploadMany` in archive handler so temp dir isn't deleted before uploads finish.
49
+ - Make mandatory `retrieve_context` language conditional on `autoRecall` being enabled.
50
+ - 500-file guard on directory collection to avoid accidental `node_modules` uploads.
51
+ - Plugin manifest: added `name`, `description`, `configSchema`; added `compat` / `build` fields for ClawHub publishing.
52
+
53
+ ### Manifest
54
+ - `package.json`: `1.0.1` → `1.1.0`.
55
+ - Tag: [`v1.1.0`](https://github.com/memorylake-ai/memorylake-openclaw/releases/tag/v1.1.0).
@@ -1,6 +1,14 @@
1
1
  import type { PluginContext } from "../plugin-context";
2
2
  import { getProvider } from "../provider";
3
3
  import { buildAddOptions } from "../utils/builders";
4
+ import { MEMORYLAKE_REMINDER } from "./auto-recall";
5
+
6
+ function stripReminder(content: string): string {
7
+ if (content.includes(MEMORYLAKE_REMINDER)) {
8
+ return content.replace(MEMORYLAKE_REMINDER, "").trim();
9
+ }
10
+ return content;
11
+ }
4
12
 
5
13
  export function registerAutoCapture(pctx: PluginContext): void {
6
14
  const { api, resolveConfig } = pctx;
@@ -56,6 +64,10 @@ export function registerAutoCapture(pctx: PluginContext): void {
56
64
  }
57
65
  }
58
66
 
67
+ if (role === "user") {
68
+ textContent = stripReminder(textContent);
69
+ }
70
+
59
71
  if (!textContent) continue;
60
72
 
61
73
  formattedMessages.push({
@@ -4,6 +4,11 @@ import { getProvider } from "../provider";
4
4
 
5
5
  const sessionIndustriesCache = new Map<string, OpenDataIndustry[]>();
6
6
 
7
+ export const MEMORYLAKE_REMINDER = [
8
+ `[MEMORYLAKE REMINDER] Before responding to this message, call \`retrieve_context\` first`,
9
+ `to fetch relevant memories and documents. Do not skip this step.`,
10
+ ].join(" ");
11
+
7
12
  export function registerAutoRecall(pctx: PluginContext): void {
8
13
  const { api, resolveConfig } = pctx;
9
14
 
@@ -39,10 +44,7 @@ export function registerAutoRecall(pctx: PluginContext): void {
39
44
 
40
45
  // Per-turn reminder injected right before the user's message.
41
46
  // Survives long conversations because it is not buried in the system prompt.
42
- result.prependContext = [
43
- `[MEMORYLAKE REMINDER] Before responding to this message, call \`retrieve_context\` first`,
44
- `to fetch relevant memories and documents. Do not skip this step.`,
45
- ].join(" ");
47
+ result.prependContext = MEMORYLAKE_REMINDER;
46
48
 
47
49
  const memoryDirectiveParts: string[] = [
48
50
  `<memory-instructions>`,
package/lib/types.ts CHANGED
@@ -123,6 +123,7 @@ export interface DocumentSearchResult {
123
123
  title?: string;
124
124
  footnote?: string;
125
125
  sheet_name?: string;
126
+ semantic_sheet_name?: string;
126
127
  figure_id?: number;
127
128
  }
128
129
 
@@ -21,7 +21,9 @@ export function buildDocumentContext(
21
21
 
22
22
  if (result.type === "table") {
23
23
  const title = result.title || "Untitled Table";
24
- parts.push(`### Table: ${title} (from ${source}, doc_id: ${docId})`);
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})`);
25
27
  if (result.footnote) parts.push(`Note: ${result.footnote}`);
26
28
 
27
29
  for (const innerTable of highlight?.inner_tables ?? []) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorylake-openclaw",
3
- "version": "1.0.2-beta.7",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "description": "MemoryLake memory backend for OpenClaw",
6
6
  "license": "MIT",
@@ -5,6 +5,7 @@
5
5
  param(
6
6
  [string]$ApiKey = $env:MEMORYLAKE_API_KEY,
7
7
  [string]$ProjectId = $env:MEMORYLAKE_PROJECT_ID,
8
+ [string]$MLHost = $env:MEMORYLAKE_HOST,
8
9
  [switch]$Help
9
10
  )
10
11
 
@@ -54,11 +55,13 @@ Usage:
54
55
  Parameters:
55
56
  -ApiKey <key> MemoryLake API key (required)
56
57
  -ProjectId <id> MemoryLake project ID (required)
58
+ -MLHost <url> MemoryLake host URL (optional, defaults to https://app.memorylake.ai)
57
59
  -Help Show this help
58
60
 
59
61
  Environment variables:
60
62
  MEMORYLAKE_API_KEY API key (alternative to -ApiKey)
61
63
  MEMORYLAKE_PROJECT_ID Project ID (alternative to -ProjectId)
64
+ MEMORYLAKE_HOST Host URL (alternative to -MLHost)
62
65
  NPM_REGISTRY Override npm registry (e.g. https://registry.npmmirror.com for China)
63
66
 
64
67
  Get apiKey and projectId from https://app.memorylake.ai
@@ -346,12 +349,16 @@ function Write-Config {
346
349
  $config.plugins | Add-Member -NotePropertyName "entries" -NotePropertyValue ([PSCustomObject]@{}) -Force
347
350
  }
348
351
 
352
+ $pluginConfig = [PSCustomObject]@{
353
+ apiKey = $ApiKey
354
+ projectId = $ProjectId
355
+ }
356
+ if (-not [string]::IsNullOrWhiteSpace($MLHost)) {
357
+ $pluginConfig | Add-Member -NotePropertyName "host" -NotePropertyValue $MLHost -Force
358
+ }
349
359
  $pluginEntry = [PSCustomObject]@{
350
360
  enabled = $true
351
- config = [PSCustomObject]@{
352
- apiKey = $ApiKey
353
- projectId = $ProjectId
354
- }
361
+ config = $pluginConfig
355
362
  }
356
363
  $config.plugins.entries | Add-Member -NotePropertyName "memorylake-openclaw" -NotePropertyValue $pluginEntry -Force
357
364
 
@@ -46,11 +46,13 @@ Usage:
46
46
  Options:
47
47
  --api-key, -a <key> MemoryLake API key (required)
48
48
  --project-id, -p <id> MemoryLake project ID (required)
49
+ --host <url> MemoryLake host URL (optional, defaults to https://app.memorylake.ai)
49
50
  --help, -h Show this help
50
51
 
51
52
  Environment variables:
52
53
  MEMORYLAKE_API_KEY API key (alternative to --api-key)
53
54
  MEMORYLAKE_PROJECT_ID Project ID (alternative to --project-id)
55
+ MEMORYLAKE_HOST Host URL (alternative to --host)
54
56
  NPM_REGISTRY Override npm registry (e.g. https://registry.npmmirror.com for China)
55
57
 
56
58
  Get apiKey and projectId from https://app.memorylake.ai
@@ -60,6 +62,7 @@ EOF
60
62
  parse_args() {
61
63
  API_KEY="${MEMORYLAKE_API_KEY:-}"
62
64
  PROJECT_ID="${MEMORYLAKE_PROJECT_ID:-}"
65
+ HOST="${MEMORYLAKE_HOST:-}"
63
66
  HELP=0
64
67
 
65
68
  while [[ $# -gt 0 ]]; do
@@ -72,6 +75,10 @@ parse_args() {
72
75
  PROJECT_ID="${2:-}"
73
76
  shift 2
74
77
  ;;
78
+ --host)
79
+ HOST="${2:-}"
80
+ shift 2
81
+ ;;
75
82
  --help|-h)
76
83
  HELP=1
77
84
  shift
@@ -278,13 +285,14 @@ write_config() {
278
285
 
279
286
  check_tools_profile "$config_path"
280
287
 
281
- CONFIG_PATH="$config_path" API_KEY="$API_KEY" PROJECT_ID="$PROJECT_ID" CLAW_MODE="$CLAW_MODE" SET_TOOLS_PROFILE="$SET_TOOLS_PROFILE" python3 -c '
288
+ CONFIG_PATH="$config_path" API_KEY="$API_KEY" PROJECT_ID="$PROJECT_ID" HOST="$HOST" CLAW_MODE="$CLAW_MODE" SET_TOOLS_PROFILE="$SET_TOOLS_PROFILE" python3 -c '
282
289
  import json
283
290
  import os
284
291
 
285
292
  path = os.environ["CONFIG_PATH"]
286
293
  api_key = os.environ["API_KEY"]
287
294
  project_id = os.environ["PROJECT_ID"]
295
+ host = os.environ.get("HOST", "")
288
296
  claw_mode = os.environ.get("CLAW_MODE", "")
289
297
  set_tools_profile = os.environ.get("SET_TOOLS_PROFILE", "")
290
298
 
@@ -298,12 +306,16 @@ if "plugins" not in config:
298
306
  if "entries" not in config["plugins"]:
299
307
  config["plugins"]["entries"] = {}
300
308
 
309
+ plugin_config = {
310
+ "apiKey": api_key,
311
+ "projectId": project_id
312
+ }
313
+ if host:
314
+ plugin_config["host"] = host
315
+
301
316
  config["plugins"]["entries"]["memorylake-openclaw"] = {
302
317
  "enabled": True,
303
- "config": {
304
- "apiKey": api_key,
305
- "projectId": project_id
306
- }
318
+ "config": plugin_config
307
319
  }
308
320
 
309
321
  # Set tools profile if user approved (or no prior value existed)