@nowledge/openclaw-nowledge-mem 0.6.14 → 0.6.15
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 +10 -0
- package/CLAUDE.md +9 -6
- package/README.md +15 -12
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/client.js +1 -1
- package/src/config.js +54 -8
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the Nowledge Mem OpenClaw plugin will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.6.15] - 2026-03-18
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **Shared config for remote credentials.** The plugin now reads `apiUrl` and `apiKey` from `~/.nowledge-mem/config.json` — the same file used by nmem CLI, Bub, Claude Code, and other integrations. One config file connects all your tools. The legacy `~/.nowledge-mem/openclaw.json` is still honored at highest priority for backward compatibility, but is no longer the recommended path. New cascade for credentials: `openclaw.json` (legacy) > OpenClaw dashboard > `config.json` (shared) > env vars > defaults.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Trailing slash in API URL no longer causes 404.** URLs like `https://mem.example.com/` (with trailing slash) produced double-slash paths in API fallback requests. The URL is now normalized at construction time.
|
|
14
|
+
|
|
5
15
|
## [0.6.14] - 2026-03-17
|
|
6
16
|
|
|
7
17
|
### Added
|
package/CLAUDE.md
CHANGED
|
@@ -9,7 +9,7 @@ Continuation guide for `community/nowledge-mem-openclaw-plugin`.
|
|
|
9
9
|
- Memory backend: `nmem` CLI (fallback: `uvx --from nmem-cli nmem`)
|
|
10
10
|
- OpenClaw minimum: `2026.3.7` (`appendSystemContext` / system-context guidance required)
|
|
11
11
|
- Architecture: **CLI-first via OpenClaw runtime** - all CLI execution goes through `api.runtime.system.runCommandWithTimeout`, not direct `child_process`
|
|
12
|
-
- Remote mode:
|
|
12
|
+
- Remote mode: `~/.nowledge-mem/config.json` (shared) or OpenClaw dashboard. Legacy `openclaw.json` still honored.
|
|
13
13
|
|
|
14
14
|
## Design Philosophy
|
|
15
15
|
|
|
@@ -30,7 +30,7 @@ src/
|
|
|
30
30
|
index.js - plugin registration (tools, hooks, commands, CLI)
|
|
31
31
|
client.js - CLI wrapper with API fallback; async runtime command execution; credential handling
|
|
32
32
|
spawn-env.js - env-only credential injection for the nmem runner
|
|
33
|
-
config.js - config cascade:
|
|
33
|
+
config.js - config cascade: openclaw.json (legacy) > pluginConfig > config.json (credentials) > env > defaults
|
|
34
34
|
hooks/
|
|
35
35
|
behavioral.js - always-on behavioral guidance (~50 tokens/turn)
|
|
36
36
|
recall.js - before_prompt_build: inject Working Memory + recalled memories
|
|
@@ -49,7 +49,8 @@ skills/
|
|
|
49
49
|
memory-guide/
|
|
50
50
|
SKILL.md - agent behavioral skill: when/how to search, save, explore memory (auto-discovered by OpenClaw)
|
|
51
51
|
openclaw.plugin.json - manifest + config schema (version, uiHints, configSchema, skills)
|
|
52
|
-
~/.nowledge-mem/openclaw.json -
|
|
52
|
+
~/.nowledge-mem/openclaw.json - legacy config file (still honored, deprecated in docs)
|
|
53
|
+
~/.nowledge-mem/config.json - shared credentials (apiUrl/apiKey) read by all Nowledge Mem tools
|
|
53
54
|
```
|
|
54
55
|
|
|
55
56
|
## Tool Surface (10 tools)
|
|
@@ -92,7 +93,8 @@ openclaw.plugin.json - manifest + config schema (version, uiHints, configSchema,
|
|
|
92
93
|
|
|
93
94
|
## Config Keys
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
Plugin settings: OpenClaw dashboard (pluginConfig). Legacy `~/.nowledge-mem/openclaw.json` still honored.
|
|
97
|
+
Credentials (apiUrl/apiKey): also reads `~/.nowledge-mem/config.json` (shared with all Nowledge Mem tools).
|
|
96
98
|
|
|
97
99
|
| Key | Type | Default | Env Var | Description |
|
|
98
100
|
|-----|------|---------|---------|-------------|
|
|
@@ -105,9 +107,10 @@ Optional config file at `~/.nowledge-mem/openclaw.json`. Falls through to OpenCl
|
|
|
105
107
|
| `apiUrl` | string | `""` | `NMEM_API_URL` | Remote server URL. Empty = local (127.0.0.1:14242) |
|
|
106
108
|
| `apiKey` | string | `""` | `NMEM_API_KEY` | API key. Never logged. |
|
|
107
109
|
|
|
108
|
-
**Priority
|
|
110
|
+
**Priority** (plugin-specific keys): `openclaw.json` (legacy) > pluginConfig > env var > default.
|
|
111
|
+
**Priority** (apiUrl/apiKey): `openclaw.json` (legacy) > pluginConfig > `config.json` (shared) > env var > default.
|
|
109
112
|
|
|
110
|
-
`parseConfig()` returns `_sources` object tracking where each value came from (`"file"`, `"pluginConfig"`, `"env"`, `"default"`). Used by `nowledge_mem_status` tool.
|
|
113
|
+
`parseConfig()` returns `_sources` object tracking where each value came from (`"file"`, `"pluginConfig"`, `"sharedConfig"`, `"env"`, `"default"`). Used by `nowledge_mem_status` tool.
|
|
111
114
|
|
|
112
115
|
Legacy aliases accepted silently in all sources for backward compat:
|
|
113
116
|
`autoRecall`→`sessionContext`, `autoCapture`→`sessionDigest`, `captureMinInterval`→`digestMinInterval`, `maxRecallResults`→`maxContextResults`.
|
package/README.md
CHANGED
|
@@ -372,24 +372,18 @@ To change settings, use the OpenClaw plugin settings UI. Changes take effect on
|
|
|
372
372
|
| `apiUrl` | string | `""` | Remote server URL. Empty = local (`http://127.0.0.1:14242`) |
|
|
373
373
|
| `apiKey` | string | `""` | API key for remote access. Injected as `NMEM_API_KEY` env var, never logged |
|
|
374
374
|
|
|
375
|
-
###
|
|
375
|
+
### Remote access
|
|
376
376
|
|
|
377
|
-
|
|
377
|
+
Create `~/.nowledge-mem/config.json` with your credentials. This file is shared by all Nowledge Mem integrations (nmem CLI, Bub, Claude Code, etc.) so one file connects everything:
|
|
378
378
|
|
|
379
379
|
```json
|
|
380
380
|
{
|
|
381
|
-
"
|
|
382
|
-
"
|
|
383
|
-
"digestMinInterval": 300,
|
|
384
|
-
"maxContextResults": 5,
|
|
385
|
-
"recallMinScore": 0,
|
|
386
|
-
"maxThreadMessageChars": 800,
|
|
387
|
-
"apiUrl": "",
|
|
388
|
-
"apiKey": ""
|
|
381
|
+
"apiUrl": "https://<your-url>",
|
|
382
|
+
"apiKey": "nmem_..."
|
|
389
383
|
}
|
|
390
384
|
```
|
|
391
385
|
|
|
392
|
-
|
|
386
|
+
See [Access Mem Anywhere](https://mem.nowledge.co/docs/remote-access).
|
|
393
387
|
|
|
394
388
|
### Advanced: environment variables
|
|
395
389
|
|
|
@@ -401,16 +395,25 @@ NMEM_SESSION_DIGEST=true
|
|
|
401
395
|
NMEM_DIGEST_MIN_INTERVAL=300
|
|
402
396
|
NMEM_MAX_CONTEXT_RESULTS=5
|
|
403
397
|
NMEM_RECALL_MIN_SCORE=0
|
|
398
|
+
NMEM_MAX_THREAD_MESSAGE_CHARS=800
|
|
404
399
|
NMEM_API_URL=https://...
|
|
405
400
|
NMEM_API_KEY=your-key
|
|
406
401
|
```
|
|
407
402
|
|
|
408
403
|
### Priority
|
|
409
404
|
|
|
405
|
+
Plugin-specific settings:
|
|
410
406
|
```
|
|
411
|
-
|
|
407
|
+
openclaw.json (legacy) > OpenClaw dashboard > env vars > defaults
|
|
412
408
|
```
|
|
413
409
|
|
|
410
|
+
Credentials (apiUrl, apiKey):
|
|
411
|
+
```
|
|
412
|
+
openclaw.json (legacy) > OpenClaw dashboard > config.json (shared) > env vars > defaults
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
`~/.nowledge-mem/openclaw.json` is still honored for backward compatibility but is no longer the recommended path. New users should configure plugin-specific settings via the OpenClaw dashboard and shared credentials via `~/.nowledge-mem/config.json`.
|
|
416
|
+
|
|
414
417
|
Use `nowledge_mem_status` (or `openclaw nowledge-mem status`) to see where each value comes from.
|
|
415
418
|
|
|
416
419
|
### Trust warning after install
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -83,7 +83,7 @@ export class NowledgeMemClient {
|
|
|
83
83
|
this.nmemCmdPromise = null;
|
|
84
84
|
// Resolved once from config + env (config wins over env, both win over default)
|
|
85
85
|
this._apiUrl =
|
|
86
|
-
(credentials.apiUrl || "").trim() || "http://127.0.0.1:14242";
|
|
86
|
+
((credentials.apiUrl || "").trim() || "http://127.0.0.1:14242").replace(/\/+$/, "");
|
|
87
87
|
this._apiKey = (credentials.apiKey || "").trim();
|
|
88
88
|
}
|
|
89
89
|
|
package/src/config.js
CHANGED
|
@@ -39,13 +39,20 @@ const ALIAS_KEYS = {
|
|
|
39
39
|
maxRecallResults: "maxContextResults",
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
// --- config
|
|
42
|
+
// --- config files --------------------------------------------------------
|
|
43
43
|
|
|
44
44
|
const CONFIG_DIR = join(homedir(), ".nowledge-mem");
|
|
45
|
+
|
|
46
|
+
// Legacy dedicated config (deprecated — still honored for backward compat)
|
|
45
47
|
const CONFIG_PATH = join(CONFIG_DIR, "openclaw.json");
|
|
46
48
|
|
|
49
|
+
// Shared config read by all Nowledge Mem integrations (nmem CLI, Bub, Claude Code, etc.)
|
|
50
|
+
const SHARED_CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
51
|
+
|
|
47
52
|
/**
|
|
48
53
|
* Read ~/.nowledge-mem/openclaw.json if it exists.
|
|
54
|
+
* Deprecated: new users should use the OpenClaw dashboard for plugin settings
|
|
55
|
+
* and ~/.nowledge-mem/config.json for shared credentials (apiUrl, apiKey).
|
|
49
56
|
* Returns {} when the file is missing or unreadable.
|
|
50
57
|
*/
|
|
51
58
|
function readConfigFile(logger) {
|
|
@@ -64,8 +71,37 @@ function readConfigFile(logger) {
|
|
|
64
71
|
}
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Read apiUrl and apiKey from the shared ~/.nowledge-mem/config.json.
|
|
76
|
+
* Only credentials are extracted — plugin-specific keys are ignored.
|
|
77
|
+
* Returns { apiUrl?, apiKey? } or {} when the file is missing or unreadable.
|
|
78
|
+
*/
|
|
79
|
+
function readSharedConfig(logger) {
|
|
80
|
+
try {
|
|
81
|
+
if (!existsSync(SHARED_CONFIG_PATH)) {
|
|
82
|
+
return {};
|
|
83
|
+
}
|
|
84
|
+
const content = readFileSync(SHARED_CONFIG_PATH, "utf-8").trim();
|
|
85
|
+
if (!content) return {};
|
|
86
|
+
const parsed = JSON.parse(content);
|
|
87
|
+
const result = {};
|
|
88
|
+
if (typeof parsed.apiUrl === "string" && parsed.apiUrl.trim()) {
|
|
89
|
+
result.apiUrl = parsed.apiUrl.trim();
|
|
90
|
+
}
|
|
91
|
+
if (typeof parsed.apiKey === "string" && parsed.apiKey.trim()) {
|
|
92
|
+
result.apiKey = parsed.apiKey.trim();
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
} catch (err) {
|
|
96
|
+
logger?.warn?.(
|
|
97
|
+
`nowledge-mem: could not read ${SHARED_CONFIG_PATH}: ${err instanceof Error ? err.message : err}`,
|
|
98
|
+
);
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
67
103
|
/** Exported for tests / CLI tooling. */
|
|
68
|
-
export { CONFIG_PATH };
|
|
104
|
+
export { CONFIG_PATH, SHARED_CONFIG_PATH };
|
|
69
105
|
|
|
70
106
|
// --- env var helpers -----------------------------------------------------
|
|
71
107
|
|
|
@@ -130,11 +166,18 @@ function firstDefined(...options) {
|
|
|
130
166
|
|
|
131
167
|
/**
|
|
132
168
|
* Parse plugin config with cascade:
|
|
133
|
-
* ~/.nowledge-mem/openclaw.json > pluginConfig > env vars > defaults
|
|
134
169
|
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
170
|
+
* Plugin-specific keys (sessionContext, sessionDigest, etc.):
|
|
171
|
+
* openclaw.json (legacy) > pluginConfig (dashboard) > env vars > defaults
|
|
172
|
+
*
|
|
173
|
+
* Credentials (apiUrl, apiKey):
|
|
174
|
+
* openclaw.json (legacy) > pluginConfig (dashboard) > config.json (shared) > env vars > defaults
|
|
175
|
+
*
|
|
176
|
+
* Most users configure via the OpenClaw dashboard (pluginConfig) and
|
|
177
|
+
* ~/.nowledge-mem/config.json for shared credentials across all tools.
|
|
178
|
+
*
|
|
179
|
+
* ~/.nowledge-mem/openclaw.json is still honored for backward compat
|
|
180
|
+
* but is no longer the recommended path.
|
|
138
181
|
*
|
|
139
182
|
* Canonical keys: sessionContext, sessionDigest, digestMinInterval,
|
|
140
183
|
* maxContextResults, recallMinScore, maxThreadMessageChars, apiUrl, apiKey
|
|
@@ -158,6 +201,7 @@ function firstDefined(...options) {
|
|
|
158
201
|
export function parseConfig(raw, logger) {
|
|
159
202
|
const pluginCfg = raw && typeof raw === "object" ? raw : {};
|
|
160
203
|
const fileCfg = readConfigFile(logger);
|
|
204
|
+
const sharedCfg = readSharedConfig(logger);
|
|
161
205
|
|
|
162
206
|
// Resolve aliases in both sources
|
|
163
207
|
const resolvedPlugin = resolveAliases(pluginCfg);
|
|
@@ -269,7 +313,7 @@ export function parseConfig(raw, logger) {
|
|
|
269
313
|
);
|
|
270
314
|
_sources.maxThreadMessageChars = mtmc.source;
|
|
271
315
|
|
|
272
|
-
// --- apiUrl: file > pluginConfig > env > "" ---
|
|
316
|
+
// --- apiUrl: file (legacy) > pluginConfig > sharedConfig > env > "" ---
|
|
273
317
|
const fileUrl =
|
|
274
318
|
typeof resolvedFile.apiUrl === "string" && resolvedFile.apiUrl.trim();
|
|
275
319
|
const pluginUrl =
|
|
@@ -277,13 +321,14 @@ export function parseConfig(raw, logger) {
|
|
|
277
321
|
const au = firstDefined(
|
|
278
322
|
{ value: fileUrl || undefined, source: "file" },
|
|
279
323
|
{ value: pluginUrl || undefined, source: "pluginConfig" },
|
|
324
|
+
{ value: sharedCfg.apiUrl || undefined, source: "sharedConfig" },
|
|
280
325
|
{ value: envStr("NMEM_API_URL"), source: "env" },
|
|
281
326
|
{ value: "", source: "default" },
|
|
282
327
|
);
|
|
283
328
|
const apiUrl = au.value;
|
|
284
329
|
_sources.apiUrl = au.source;
|
|
285
330
|
|
|
286
|
-
// --- apiKey: file > pluginConfig > env > "" ---
|
|
331
|
+
// --- apiKey: file (legacy) > pluginConfig > sharedConfig > env > "" ---
|
|
287
332
|
const fileKey =
|
|
288
333
|
typeof resolvedFile.apiKey === "string" && resolvedFile.apiKey.trim();
|
|
289
334
|
const pluginKey =
|
|
@@ -291,6 +336,7 @@ export function parseConfig(raw, logger) {
|
|
|
291
336
|
const ak = firstDefined(
|
|
292
337
|
{ value: fileKey || undefined, source: "file" },
|
|
293
338
|
{ value: pluginKey || undefined, source: "pluginConfig" },
|
|
339
|
+
{ value: sharedCfg.apiKey || undefined, source: "sharedConfig" },
|
|
294
340
|
{ value: envStr("NMEM_API_KEY"), source: "env" },
|
|
295
341
|
{ value: "", source: "default" },
|
|
296
342
|
);
|